我的目的是想截获用户创建文件,删除文件等操作,并能由程序决定这些操作能否成功执行.我知道SHChangeNotifyRegister,ReadDirectoryChanges可以捕获这些事件,但是仅仅只能知道发生了这些事件,而不能控制.所以想用HOOK Api的方法试试.
    我用全局WH_GETMESSAGE和IAT方法来HOOK ZwCreateFile,我调试的时候发现确实跳转到了我自己的MyZwCreateFile,但是很奇怪,通过在MyZwCreateFile输出的日志中我发现只能截获到一种的信息:[System]进程对 [\??\PIPE\lsarpc]调用了ZwCreateFile.
    是不是仅仅拦截ZwCreateFile还不行?那么我该拦截哪些API呢,CreateFileW我也拦截过了,同样只能截获到很少的信息量,我自己新建一个文档,程序毫无反应.代码:
//---------------------------------------------------------------
#include <windows.h>
#include "DdkDef.h"
#pragma hdrstop
//---------------------------------------------------------------------------
#pragma argsused#define WM_X_CRTFL_W (WM_APP+0X177)   //CreatrFileW Notify
#define WM_X_CRTFL_A (WM_APP+0X178)   //CreatrFileA Notify
#define WM_X_CRTFL_Z (WM_APP+0X179)   //ZwCreatrFile Notify#define _TEST_ONLY
#define HOOK_ZW_ONLY
//#define HOOK_ANSI
//#define _TEST_NOHOOK_SYSPROC
//#define _TEST_FILTER_FILES
#ifdef _TEST_ONLY
unsigned long iCount=0;
#endifpZW_CREATE_FILE ZwCreateFileFunc;COPYDATASTRUCT CopyData;
HHOOK f_Hook=NULL;
HINSTANCE f_hinstDll;
HMODULE hModule=NULL;
HMODULE hModule2=NULL;
FARPROC f_farCreateFileW;
FARPROC f_farCreateFileA;
FARPROC f_farZwCreateFile;
BYTE OldCreateFileWCode[5],NewCreateFileWCode[5];
BYTE OldCreateFileACode[5],NewCreateFileACode[5];
BYTE OldZwCreateFileCode[5],NewZwCreateFileCode[5];
bool bCrtFWHooked;
bool bCrtFAHooked;
bool bZwCrtFHooked;
bool bAllHooked;
DWORD dwIdOld,dwIdNew;
HWND hWndApp=NULL;
WCHAR strLastFileNameW[MAX_PATH+1]  ;
char  strLastFileNameA[MAX_PATH+1]  ;
HANDLE MyCreateFileW(
  LPCWSTR lpFileName,
  DWORD dwDesiredAccess,
  DWORD dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD dwCreationDisposition,
  DWORD dwFlagsAndAttributes,
  HANDLE hTemplateFile
);
 HANDLE MyCreateFileA(
  LPCSTR lpFileName,
  DWORD dwDesiredAccess,
  DWORD dwShareMode,
  LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  DWORD dwCreationDisposition,
  DWORD dwFlagsAndAttributes,
  HANDLE hTemplateFile
);
NTSTATUS MyZwCreateFile(
OUT PHANDLE  FileHandle,
    IN ACCESS_MASK  DesiredAccess,
    IN POBJECT_ATTRIBUTES  ObjectAttributes,
    OUT PIO_STATUS_BLOCK  IoStatusBlock,
    IN PLARGE_INTEGER  AllocationSize  OPTIONAL,
    IN ULONG  FileAttributes,
    IN ULONG  ShareAccess,
    IN ULONG  CreateDisposition,
    IN ULONG  CreateOptions,
    IN PVOID  EaBuffer  OPTIONAL,
    IN ULONG  EaLength
);bool __fastcall InstallHook();
bool __fastcall UninstallHook();
bool __fastcall InitHookAPI();
DWORD __fastcall InsertMyFuncs();
DWORD __fastcall RestoreOSFuncs();
DWORD  __fastcall InsertAFunc (FARPROC* fproc,BYTE *JumpNew);
DWORD  __fastcall RestoreAFunc(FARPROC* fproc,BYTE *JumpOld);
LRESULT WINAPI NullHookProc(int nCode,WPARAM wParam,LPARAM lParam);
extern "C" __declspec(dllexport) void __stdcall xStart(HWND hWnd);
extern "C" __declspec(dllexport) __stdcall void xStop();
//---------------------------------------------------------------------------
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if(reason==DLL_PROCESS_ATTACH)
{
//
f_hinstDll=hinst;
}
if(reason==DLL_PROCESS_DETACH)
{
if(bAllHooked)
RestoreOSFuncs();
UninstallHook();
if(hModule)
{
FreeLibrary(hModule);
hModule=NULL;
}
if(hModule2)
{
FreeLibrary(hModule2);
hModule=NULL;
}
}
return 1;
}
//---------------------------------------------------------------------------
void __stdcall xStart(HWND hWnd)
{
hWndApp=hWnd;
InstallHook();
if(!bAllHooked && InitHookAPI())
InsertMyFuncs();
}
void __stdcall xStop()
{
if(bAllHooked)
RestoreOSFuncs();
if(f_Hook)
{
UninstallHook();
f_Hook=NULL;
}
if(hModule2)
{
FreeLibrary(hModule2);
hModule2=NULL;
}
}

解决方案 »

  1.   


    bool __fastcall InitHookAPI()
    {
    hModule=LoadLibrary("Kernel32.dll");
    f_farCreateFileW=GetProcAddress(hModule,"CreateFileW");
    f_farCreateFileA=GetProcAddress(hModule,"CreateFileA");
    hModule2=LoadLibrary("ntdll.dll");
    f_farZwCreateFile=GetProcAddress(hModule2,"ZwCreateFile");
    if(f_farCreateFileW==NULL || f_farCreateFileA==NULL || f_farZwCreateFile==NULL)
    return false;
    ZwCreateFileFunc= (pZW_CREATE_FILE)f_farZwCreateFile;
    //CreateFileW
    _asm
    {
    lea edi,OldCreateFileWCode
    mov esi,f_farCreateFileW
    cld
    movsd
    movsb
    }
    NewCreateFileWCode[0]=0xe9;
    _asm
    {
    lea eax,MyCreateFileW
    mov ebx,f_farCreateFileW
    sub eax,ebx
    sub eax,5
    mov dword ptr [NewCreateFileWCode+1],eax
    }
    //CreateFileA
    _asm
    {
    lea edi,OldCreateFileACode
    mov esi,f_farCreateFileA
    cld
    movsd
    movsb
    }
    NewCreateFileACode[0]=0xe9;
    _asm
    {
    lea eax,MyCreateFileA
    mov ebx,f_farCreateFileA
    sub eax,ebx
    sub eax,5
    mov dword ptr [NewCreateFileACode+1],eax
    }
    //ZwCreateFile
    _asm
    {
    lea edi,OldZwCreateFileCode
    mov esi,f_farZwCreateFile
    cld
    movsd
    movsb
    }
    NewZwCreateFileCode[0]=0xe9;
    _asm
    {
    lea eax,MyZwCreateFile
    mov ebx,f_farZwCreateFile
    sub eax,ebx
    sub eax,5
    mov dword ptr [NewZwCreateFileCode+1],eax
    }
    dwIdNew=GetCurrentProcessId(); //得到所属进程的ID
    #ifdef _TEST_NOHOOK_SYSPROC
    if(dwIdNew<100)
        return false;
    #endif
    dwIdOld=dwIdNew;
    //InsertMyFuncs();//开始拦截
        return true; 
    }DWORD  __fastcall InsertAFunc (FARPROC fproc,BYTE *JumpNew)
    {
    HANDLE hProc;
    dwIdOld=dwIdNew;
    bool dwRet=0;
    hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);//得到所属进程的句柄
    if(hProc==NULL)
    return GetLastError();
    dwRet=VirtualProtectEx(hProc,fproc,5,PAGE_READWRITE,&dwIdOld);
    if(!dwRet)
    return GetLastError();
    dwRet=WriteProcessMemory(hProc,fproc,JumpNew,5,0);
    if(!dwRet)
    return GetLastError();
    dwRet=VirtualProtectEx(hProc,fproc,5,dwIdOld,&dwIdOld);
    if(!dwRet)
    return GetLastError();
    //bHooked=true;
    return 0;
    }
    DWORD  __fastcall RestoreAFunc(FARPROC fproc,BYTE *JumpOld)
    {
    HANDLE hProc;
    dwIdOld=dwIdNew;
    bool dwRet=0;
    hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwIdOld);
    if(hProc==NULL)
    return GetLastError();
    dwRet=VirtualProtectEx(hProc,fproc,5,PAGE_READWRITE,&dwIdOld);
    if(!dwRet)
    return GetLastError();
    dwRet=WriteProcessMemory(hProc,fproc,JumpOld,5,0);
    if(!dwRet)
    return GetLastError();
    dwRet=VirtualProtectEx(hProc,fproc,5,dwIdOld,&dwIdOld);
    if(!dwRet)
    return GetLastError();
    //bHooked=false;
    return 0;
    }DWORD __fastcall InsertMyFuncs()
    {
    DWORD ret;
    #ifndef  HOOK_ZW_ONLY
    ret=InsertAFunc(f_farCreateFileW,NewCreateFileWCode);
    if(ret!=0)
    return ret;
    else
    bCrtFWHooked=true;
    #ifdef HOOK_ANSI
    ret=InsertAFunc(f_farCreateFileA,NewCreateFileACode);
    if(ret!=0)
    return ret;
    else
    bCrtFAHooked=true;
    //if(bCrtFAHooked)
    #endif
    #endif
    ret=InsertAFunc(f_farZwCreateFile,NewZwCreateFileCode);
    if(ret!=0)
    return ret;
    else
    bZwCrtFHooked=true;
    bAllHooked = true;
    return 0;} 
    DWORD __fastcall RestoreOSFuncs()
    {
    DWORD ret;
    #ifndef  HOOK_ZW_ONLY
    ret=RestoreAFunc(f_farCreateFileW,OldCreateFileWCode);
    if(ret!=0)
    return ret;
    else
    bCrtFWHooked=false;
    #ifdef HOOK_ANSI
    ret=RestoreAFunc(f_farCreateFileA,OldCreateFileACode);
    if(ret!=0)
    return ret;
    else
    bCrtFAHooked=false;
    #endif
    #endif
    ret=RestoreAFunc(f_farZwCreateFile,OldZwCreateFileCode);
    if(ret!=0)
    return ret;
    else
    bZwCrtFHooked=false;
    bAllHooked = false;
    return 0;
    }LRESULT WINAPI NullHookProc(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
    {  return(CallNextHookEx(f_Hook,nCode,wParam,lParam));

    bool __fastcall InstallHook()
    {

    f_Hook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)NullHookProc,f_hinstDll,0);
    if (!f_Hook)
    {
    //MessageBoxA(NULL,"SET ERROR","ERROR",MB_OK);
    return false ;
    }
    return true;

    bool __fastcall UninstallHook()//输出御在钩子函数
    {     return(UnhookWindowsHookEx(f_Hook));
    }
      

  2.   


    HANDLE MyCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
    {
    RestoreAFunc(f_farCreateFileW,OldCreateFileWCode);
    HANDLE handle;
    handle=CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);

    #ifdef _TEST_ONLY
    bool bSend  ;
    int i=1;

    if(i==1/*!wcscmp(lpFileName,strLastFileNameW*/
    #ifdef _TEST_FILTER_FILES
    && wcslen(lpFileName)>20
    #endif
    )
    {
            if(iCount>0xFFFFFFFF)
                iCount=0;
    iCount++;
    //#pragma warn -8004
    //bSend=PostMessage(HWND_BROADCAST,WM_X_CRTFL,dwIdOld,iCount);
    bSend=PostMessage(hWndApp,WM_X_CRTFL_W,dwIdOld,iCount);
            //#pragma warn +8004
    }
    wcscpy(strLastFileNameW,lpFileName);#else
       // InsertMyFuncs();
       // return CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #endif
    InsertAFunc(f_farCreateFileW,NewCreateFileWCode);
    return  handle;
    }HANDLE MyCreateFileA(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
    {
    RestoreAFunc(f_farCreateFileA,OldCreateFileACode);
    HANDLE handle;
    handle=CreateFileA(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #pragma warn -8066
    #ifdef _TEST_ONLY
    bool bSend  ;
    int i=1;
    //handle=CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    if(i==1/*!wcscmp(lpFileName,strLastFileNameA*/
    #ifdef _TEST_FILTER_FILES
    && wcslen(lpFileName)>20
    #endif
    )
    {
            if(iCount>0xFFFFFFFF)
                iCount=0;
    iCount++;
    //#pragma warn -8004
    bSend=PostMessage(hWndApp,WM_X_CRTFL_A,dwIdOld,iCount);
    //PostMessage(hWndApp,WM_X_CRTFL,dwIdOld,iCount);
            //#pragma warn +8004
    }
    strcpy(strLastFileNameA,lpFileName);#else
       // InsertMyFuncs();
       // return CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #endif
    InsertAFunc(f_farCreateFileA,NewCreateFileACode);
    return  handle;
    #pragma warn +8066
    }NTSTATUS MyZwCreateFile(
    OUT PHANDLE  FileHandle,                                //  1
    IN ACCESS_MASK  DesiredAccess,                          //  2
    IN POBJECT_ATTRIBUTES  ObjectAttributes,                //  3
    OUT PIO_STATUS_BLOCK  IoStatusBlock,                    //  4
    IN PLARGE_INTEGER  AllocationSize  OPTIONAL,            //  5
    IN ULONG  FileAttributes,                               //  6
    IN ULONG  ShareAccess,                                  //  7
    IN ULONG  CreateDisposition,                            //  8
    IN ULONG  CreateOptions,                                //  9
    IN PVOID  EaBuffer  OPTIONAL,                           //  10
    IN ULONG  EaLength                                      //  11
    )
    { //return CreateFileA(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #pragma warn -8066
    #ifdef _TEST_ONLY
    bool bSend  ;
    int i=1;
    if(i==1/*!wcscmp(lpFileName,strLastFileNameA*/
    #ifdef _TEST_FILTER_FILES
    && wcslen(ObjectAttributes->ObjectName )>4
    #endif
    )
    {
    if(iCount>0xFFFFFFFF)
    iCount=0;
    iCount++;
    //#pragma warn -8004
    //bSend=PostMessage(HWND_BROADCAST,WM_X_CRTFL,dwIdOld,iCount);
    bSend=PostMessage(hWndApp,WM_X_CRTFL_Z,dwIdOld,iCount);
    //#pragma warn +8004
    } wcscpy(strLastFileNameW,ObjectAttributes->ObjectName->Buffer);
    CopyData.dwData=0;
    CopyData.lpData=strLastFileNameW;
    CopyData.cbData=sizeof(CopyData);
    bSend=SendMessage(hWndApp,WM_COPYDATA,0x77,(LPARAM) (LPVOID) &CopyData);
    #else
       // InsertMyFuncs();
       // return CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #endif
        RestoreAFunc(f_farZwCreateFile,OldZwCreateFileCode);
    NTSTATUS ntstatus;
    ntstatus=ZwCreateFileFunc(FileHandle,
    DesiredAccess,
    ObjectAttributes,
    IoStatusBlock,
    AllocationSize,
    FileAttributes,
    ShareAccess ,
    CreateDisposition,
    CreateOptions,
    EaBuffer,
    EaLength
    );
    InsertAFunc(f_farZwCreateFile,NewZwCreateFileCode);
    return  ntstatus;
    #pragma warn +8066
    }
      

  3.   

    拦截的就是ZwCreateFile,ZwCreateFile并非简单的创建磁盘文件那么简单,它还可以创建一些内核对象.参考DDK里面的说明.可以先用windbg对ntdll!ZwCreateFile下断,看一下栈就行了.
      

  4.   

    这么长怎么看呀?难道说你是"gubinary"变种?
      

  5.   

    HWND hWndApp 应该用共享内存
      

  6.   

    HOOK API的方法是行不通的,
    有些CreateFile的API微软没有公开;
    只能用驱动的方法拦截.
      

  7.   

    利用softice对zwcreatefile下个断点看看就知道了
      

  8.   

    我在公司就用API Hook的方式实现你想的类似功能
    ZwCreatefile , 另外还有 ZwOpenFile,
    我以实现
      

  9.   

    如果在驱动里面做用filter,去驱网看帖子如果在应用层做,Hook  CreateFileA,CreateFileW,DeleteFile就可以了,不需要Hook ZwCreateFile目前我的软件也是全局WH_GETMESSAGE和IATHook,Hook了比这多的多的API,工作很正常,基本上都能拦截到,拦截不到也是系统的一些底层操作,恰恰这些我不需要拦截你拦截不到说明你的代码或思路问题,而不是HookAPI的技术方案不行,去看Windows核心编程吧
      

  10.   

    多谢大家提醒,我的代码确实有很多问题,主要是我自己思路还不是很清晰,DLL的有些变量应该为全局的(在每个进程中都能访问到),我修改了一下,用共享内存来保存全局变量.然后在空的钩子回调函数里面做一次插入用来将所有勾到的进程中的CreatFileW替换:
    LRESULT WINAPI NullHookProc(int nCode,WPARAM wParam,LPARAM lParam)//空的钩子函数
    {

    if(bFirst==true)
    { dwCurrentProc= GetCurrentProcessId();
    InitHookAPI();
    SendMessage(*hWndApp,WM_X_DEB,GetCurrentThreadId(),2);
    DWORD dwRet=InsertMyFuncs(dwCurrentProc);
    if(dwRet)//成功
    SendMessage(*hWndApp,WM_X_DEB,dwRet,30);
    bFirst=false;
    }
    return(CallNextHookEx(f_Hook,nCode,wParam,lParam));
    }
    //自定义的CreateFileW函数
    HANDLE MyCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile)
    {
    HANDLE handle=NULL;
    try
    {
    EnterCriticalSection(&pGMem->LockW);//pGMem,hWndApp在共享内存中
    SendMessage(*hWndApp,WM_X_DEB,dwCurrentProc,1001); //handle=CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #ifdef _TEST_ONLY
    bool bSend  ; wcscpy(strLastFileNameW,lpFileName);
    strLastFileNameW[MAX_PATH]='\0\0';
    CopyData.dwData=0;
    CopyData.lpData=strLastFileNameW;
    CopyData.cbData=sizeof(CopyData);
    bSend=SendMessage(*hWndApp,WM_COPYDATA,0x77,(LPARAM) (LPVOID) &CopyData);
    #else
       // InsertMyFuncs();
       // return CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    #endif
    RestoreAFunc(/*pGMem-> */f_farCreateFileW,/*pGMem-> */OldCreateFileWCode,dwCurrentProc);
    handle=CreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
    InsertAFunc(/*pGMem-> */f_farCreateFileW,/*pGMem-> */NewCreateFileWCode,dwCurrentProc);
    }
    catch(...)
    {
    SendMessage(*hWndApp,WM_X_DEB,dwCurrentProc,1002);
    LeaveCriticalSection(&pGMem->LockW);
    throw;
    } SendMessage(*hWndApp,WM_X_DEB,dwCurrentProc,40);
    LeaveCriticalSection(&pGMem->LockW);
    return  handle;
    }
    //修改跳转指令的函数在这里:
    DWORD  __fastcall InsertAFunc (FARPROC fproc,BYTE *JumpNew,DWORD dwProcID)
    { HANDLE hProc;
    DWORD dwNewProtect;
    DWORD dwOldProtect;
    //SendMessage(hWndApp,WM_X_DEB,GetCurrentThreadId()/*GetCurrentProcessId()*/,3);
    SendMessage(*hWndApp,WM_X_DEB,dwProcIDRpt,3);
    bool dwRet=0;
    hProc=OpenProcess(PROCESS_ALL_ACCESS,0,dwProcID);//得到所属进程的句柄
    if(hProc==NULL)
    {
    DWORD err= GetLastError(); return  err;
    }
    dwRet=VirtualProtectEx(hProc,fproc,5,PAGE_READWRITE,&dwOldProtect);//修改所属进程前5个字节的属性为可写
    if(!dwRet)
    {
    DWORD err= GetLastError(); return  err;
    }
    dwRet=WriteProcessMemory(hProc,fproc,JumpNew,5,0);//将所属进程中前5个字节改为JMP 到 Myfunc
    if(!dwRet)
    {
    DWORD err= GetLastError(); return  err;
    }
    dwRet=VirtualProtectEx(hProc,fproc,5,dwOldProtect,&dwNewProtect);//修改所属进程中的前5个字节的属性为原来的属性
    if(!dwRet)
    {
    DWORD err= GetLastError(); return  err;
    }

    SendMessage(*hWndApp,WM_X_DEB,dwProcIDRpt,31); return 0;
    }
    我用的是消息来发送调试信息,现在还有2个问题就是
        1我用WM_COPYDATA把自定义函数中截获到的文件名发送出去,但是收到的时候却总是有截断,类似"c:\win?","d:\acc?"
        2.我在自定义函数中用CriticalSection来防止重入,但好像并不是完全有效果,我的程序老是有内存访问违规,让EXPLORER崩溃.