title: Hooking CopyFile in Kernel32.dll makes recursive instances
body: <p>My goal is to <em>weakly</em> monitor file movement.  I found a very easy <a href="http://www.codeproject.com/Articles/49319/Easy-way-to-set-up-global-API-hooks" rel="nofollow">guide</a> to create a global hook and got it to work just fine (note the need to compile both 64bit and 32bit versions, and putting them in different registry locations).  As a personal exercise, I wanted to hook CopyFile (chosen randomly from MoveFile, CreateFile, and all of their wonderful variants).  Following the exact same procedure from the guide, I came to this very short code.</p>
  
  <pre><code>#include "stdafx.h"
  #include "mhook/mhook-lib/mhook.h"
  
  //////////////////////////////////////////////////////////////////////////
  // Defines and typedefs
  
  typedef BOOL (WINAPI *CopyFileFP)(
      _In_  LPCTSTR lpExistingFileName,
      _In_  LPCTSTR lpNewFileName,
      _In_  BOOL bFailIfExists
      );
  
  //////////////////////////////////////////////////////////////////////////
  // Original function
  
  CopyFileFP OriginalCopyFile = (CopyFileFP)::GetProcAddress(::GetModuleHandle(L"kernel32"), "CopyFileW");
  
  //////////////////////////////////////////////////////////////////////////
  // Hooked function
  
  BOOL WINAPI HookedCopyFile(
      _In_  LPCTSTR lpExistingFileName,
      _In_  LPCTSTR lpNewFileName,
      _In_  BOOL bFailIfExists
      )
  {
      BOOL out = OriginalCopyFile(
                  lpExistingFileName,
                  lpNewFileName,
                  bFailIfExists);
  
       char hello[] = "Hello\n";
       DWORD charsWritten = 0;
  
       WriteConsole(
           GetStdHandle(STD_OUTPUT_HANDLE),
           hello,
           6,
           &amp;charsWritten,
           NULL);
  
      return out;
  }
  
  //////////////////////////////////////////////////////////////////////////
  // Entry point
  
  BOOL WINAPI DllMain(
      __in HINSTANCE  hInstance,
      __in DWORD      Reason,
      __in LPVOID     Reserved
      )
  {        
      switch (Reason)
      {
      case DLL_PROCESS_ATTACH:
          AllocConsole();
          Mhook_SetHook((PVOID*)&amp;OriginalCopyFile, HookedCopyFile);
          break;
  
      case DLL_PROCESS_DETACH:
          FreeConsole();
          Mhook_Unhook((PVOID*)&amp;OriginalCopyFile);
          break;
      }
  
      return TRUE;
  }
  </code></pre>
  
  <p>I wanted to see how the DLL was doing, so I needed some form of output.  I added a few console commands, however none of them use any spectacular functions (I don't do any string processing to print the source and destination filepaths).  After registering the dll and restarting a process (usually explorer.exe because it's so easy and only requires the 64bit dll), my dll seems to recursively call itself.  </p>
  
  <p>As mentioned before, the major difference between my code and the guide's code is the use of a console window.  The guide does state:</p>
  
  <blockquote>
    <p>As hooking is performed in DllMain of User32.dll you can call
    functions only from Kernel32.dll and Ntdll.dll (other libraries are
    not initialized yet).</p>
  </blockquote>
  
  <p>However I have verified that <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681944%28v=vs.85%29.aspx" rel="nofollow">AllocConsole()</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms687401%28v=vs.85%29.aspx" rel="nofollow">WriteConsole()</a>, <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms683150%28v=vs.85%29.aspx" rel="nofollow">FreeConsole()</a>, and <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms683231%28v=vs.85%29.aspx" rel="nofollow">GetStdHandle()</a> are all a part of Kernel32.dll.</p>
  
  <p><strong>Why does this DLL recursively call itself?  How would I make sure to stop any continued calls, or what should I change to stop the recursiveness?</strong>  </p>
  
  <p>On another note, my computer runs out of RAM really quickly when a globally hooked DLL recursively calls itself, even if each new console only consumes 2MB of memory. XD</p>