一直有一个问题不明白,比如我要hook createfilew(),返回一个NULL和返回一个自定义的createfile()有什么不同,具个例子,这里有3种情况,第一种情况同时返回NULL和自定义的createfileDETOUR_TRAMPOLINE(HANDLE WINAPI MyCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile), CreateFileW);
HANDLE WINAPI NewCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile){ CString Drive="G";
if(strncmp(lpFileName,Drive,2) ==0 )
{ return 0; }
return MyCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
}这种情况是,g drive不可以打开文件,其他drive不受影响,并且不可以从g drive复制文件到别的dirve,但可以从别的drive复制文件到g dirve。
第二种情况是,只返回NULL,不返回MyCreateFileW
DETOUR_TRAMPOLINE(HANDLE WINAPI MyCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile), CreateFileW);
HANDLE WINAPI NewCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile){ CString Drive="G";
if(strncmp(lpFileName,Drive,2) ==0 )
{ return 0; }}这种情况是整个电脑都hook住了,不管是什么drive都不可以打开文件和相互复制文件,这我就不明白了,我只是hook g drive,为什么连其他drive都受影响了??如果只是加上返回MyCreateFileW,变成第一种情况,又完全不同拉???第三中情况只返回MyCreateFileW,不返回NULL
DETOUR_TRAMPOLINE(HANDLE WINAPI MyCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile), CreateFileW);
HANDLE WINAPI NewCreateFileW(LPCSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile){ CString Drive="G";
if(strncmp(lpFileName,Drive,2) ==0 )
{ return MyCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
}}这种情况跟第二种相似。唯一不同是可以从g drive复制文件到别的drive,但不可以从别的drive复制到g drive,
到底返回NULL和返回MyCreateFileW是什么意思??同时返回又是什么意思?请大家帮帮忙

解决方案 »

  1.   

    Hook了CreateFile,就是要用自己的代码替代CreateFile的功能。
    返回结果大体上有两种情况:
    1、返回一个有效的句柄值。
    这种情况下,调用者会认为打开成功,通常会使用这个句柄去访问文件,最终还要关闭句柄。因为自己的代码本身并不能打开文件,必须要通过系统来打开,通常的做法是调用真正的CreateFile函数并保存结果。因为Detour是把真正的CreateFile的入口处代码改成了跳转指令,所以需要自己定义一个函数,将真正CreateFile的前几行代码复制过来,执行后再跳转到真正CreateFile的这几行代码的后面继续执行。这样调用这个函数就相当于调用了真正的CreateFile函数,直接使用Hook函数的参数调用这个函数,并返回就等于让调用者调用了真正的CreateFile函数。
    2、返回一个无效的句柄值。
    但不允许调用者打开文件时使用这种方法。不过不应该简单地返回NULL,应该先SetLastError设置一个错误码,通常可以用ERROR_ACCESS_DENIED,然后返回INVALID_HANDLE_VALUE。通常调用者会判断,当返回值为INVALID_HANDLE_VALUE时认为打开失败,可能还会用GetLastError来取错误码,判断失败原因。
      

  2.   

    这里个区别的关键不是因为你返回了什么数值(当然也有影响啦)return MyCreateFileW(...这句话不是返回MyCreateFileW,而是执行MyCreateFileW(...这条语句,然后把它的返回值作为NewCreateFileW的返回值。第一种情况:
    如果lpFileName=="G"什么也不做,直接返回NULL; 否则执行MyCreateFileW(...),我想你这个MyCreateFileW应该就是原CreateFileW代码吧。所以只会对于G这个文件操作有影响,其它与普通CreateFileW无异。第二种情况:
    如果lpFileName=="G"什么也不做,直接返回NULL; 否则还是什么也没做,只是返回值不可预测。 这样当然都受影响了,CreateFileW功能已经完全丧失了。第三种情况:
    如果lpFileName=="G"执行MyCreateFileW(...),否则什么也不做,这样只有G文件正常,对其它文件CreateFileW无效。
      

  3.   

    Hook API其实是把Windows的API的地址用我们的API来代替的过程。
    MyCreateFileW 就是替换前我们保留下来的Windows的API的地址。
    即处理完后,还要调用Windows的API才能创建文件。
      

  4.   

    If the function succeeds, the return value is an open handle to a specified file. If a specified file exists before the function call and dwCreationDisposition is CREATE_ALWAYS or OPEN_ALWAYS, a call to GetLastError returns ERROR_ALREADY_EXISTS, even when the function succeeds. If a file does not exist before the call, GetLastError returns 0 (zero).If the function fails, the return value is INVALID_HANDLE_VALUE. To get extended error information, call GetLastError.
    不是 返回NULL;要么返回INVALID_HANDLE_VALUE
      

  5.   

    WINAPI MyCreateFileW(LPCSTR lpFileName, 等等 里面的LPCSTR lpFileName,是不是LPCWSTR lpFileName,啊?
      

  6.   

    谢谢,各位的解答,感觉一下子思路清晰了许多,刚刚把程序改了一下
    CString Drive_Letter;CString Drive="G:";UINT fixed=GetDriveType(Drive);  if (fixed==DRIVE_REMOVABLE)
    {
    Drive_Letter=Drive.Mid(0,1);if(strncmp(lpFileName,Drive_Letter,1) ==0 )
    {
    return 0; }

    }return MyCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
    我的想法是判断G drive是否为u盘,如果是u盘就直接返回NULL,其他drive返回MyCreateFileW
    这种方法其实跟上面第一种做法是一样的,只是加上了GetDriveType()来判断,结果应该是g drive不可以打开文件,其他drive不受影响,并且不可以从g drive复制文件到别的dirve,但可以从别的drive复制文件到g dirve。
    但出来的结果变成了全部drive都不可以打开文件了,为什么会这样呢??
      

  7.   

    做Hook程序时,应该先测试Hook相关处理是否正确,就是Hook函数中直接调用原函数并返回,不做任何处理,看能否正常运行。
    前面已经提到,CreateFile返回INVALID_HANDLE_VALUE(值为-1)表示失败,并且要用SetLastError设置错误码,否则调用者可能发生无法预知的错误。
    CreateFileW的参数应该是LPCWSTR,而不是LPCSTR。
      

  8.   

    谢谢cnzdgs 和abomber2 的提醒,连LPCWSTR都错,粗心啊
    还有当我返回INVALID_HANDLE_VALUE,进入g drive时,会出现Windows Explorer has encountered a problem and needs to close.  We are sorry for the inconvenience.的错误,为什么??
      

  9.   

    在返回INVALID_HANDLE_VALUE之前,先SetLastError(ERROR_ACCESS_DENIED);
    另外提一下,很多人在写程序的时候,在调用某个函数时会认为肯定会调用程序,因此不去判断函数的返回值,这是就可能造成程序异常。当遇到这种情况的时候,Hook函数就不能返回失败。
      

  10.   

    奇怪,我已经按cnzdgs说得返回INVALID_HANDLE_VALUE,和SetLastError(ERROR_ACCESS_DENIED);但还是会出现Windows Explorer has encountered a problem and needs to close.  We are sorry for the inconvenience.的错误DETOUR_TRAMPOLINE(HANDLE WINAPI MyCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile), CreateFileW);
    HANDLE WINAPI NewCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile){TCHAR   szBuffer[1024];   
     UINT fixed;  CString Drive_Letter;CString Drive="G:";fixed=GetDriveType(Drive);  if (fixed==DRIVE_REMOVABLE)
    {Drive_Letter=Drive.Mid(0,1);   
    wsprintf(szBuffer,TEXT("%s"),Drive_Letter);if(wcsncmp(lpFileName, (LPCWSTR)szBuffer,1) ==0 )
    {
    SetLastError(ERROR_ACCESS_DENIED);  return INVALID_HANDLE_VALUE;
    }
    }return MyCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);}请大家帮帮忙看看那里错了?
      

  11.   

    我刚刚又出现一个问题了,当我把WINAPI MyCreateFileW(LPCSTR lpFileName, 等等 里面的LPCSTR改为正确的LPCWSTR
    按第三种情况重译编译了一次#include <atlconv.h>
    DETOUR_TRAMPOLINE(HANDLE WINAPI MyCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile), CreateFileW);HANDLE WINAPI NewCreateFileW(LPCWSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile){
    CString str=_T("G");USES_CONVERSION;LPCWSTR lpw=T2W(str);
     if(wcsncmp(lpFileName,lpw,2) ==0)
        {
           return MyCreateFileW(lpFileName,dwDesiredAccess,dwShareMode,lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,hTemplateFile);
        }
           }按Waiting4you 的说法是如果lpFileName=="G"执行MyCreateFileW(...),否则什么也不做,这样只有G文件正常,对其它文件CreateFileW无效。但出来的结果是现在连g drive都hook住了,不可以复制文件到别的drive了