home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 October / PCWorld_1999-10_cd1.bin / Hardware / Drivers / APISpy / Injlib.cpp < prev    next >
C/C++ Source or Header  |  1999-07-19  |  7KB  |  225 lines

  1. /*************************************************************
  2. Module name: InjLib.C
  3. Notices: Copyright (c) 1995-1997 Jeffrey Richter
  4. *************************************************************/
  5.  
  6. #include "CmnHdr.H"                  /* See Appendix C. */
  7. #include <windows.h>
  8. #include "ProcMem.H"
  9. #include "InjLib.H"
  10.  
  11.  
  12. //////////////////////////////////////////////////////////////
  13.  
  14.  
  15. typedef HINSTANCE (WINAPI *PROCLOADLIBRARY)(LPBYTE);
  16. typedef BOOL (WINAPI *PROCFREELIBRARY)(HINSTANCE);
  17. typedef HMODULE (WINAPI *PROCGETMODULEHANDLE)(LPBYTE);
  18.  
  19. typedef struct {
  20.    PROCLOADLIBRARY fnLoadLibrary;
  21.    PROCFREELIBRARY fnFreeLibrary;
  22.    PROCGETMODULEHANDLE fnGetModuleHandle;
  23.    BOOL ActionFlag;
  24.    BYTE pbLibFile[MAX_PATH * sizeof(WCHAR)];
  25. } INJLIBINFO, *PINJLIBINFO;
  26.  
  27.  
  28. //////////////////////////////////////////////////////////////
  29.  
  30.  
  31. // Calls to the stack checking routine must be disabled.
  32. #pragma check_stack (off)
  33.  
  34. static DWORD WINAPI ThreadFunc (PINJLIBINFO pInjLibInfo) {
  35.    // There must be less than a page worth of local
  36.    // variables used in this function.
  37.    HINSTANCE hinstDll;
  38.  
  39.    hinstDll = pInjLibInfo->fnGetModuleHandle(pInjLibInfo->pbLibFile);
  40.  
  41.    if (pInjLibInfo->ActionFlag == LOAD_DLL)
  42.    {
  43.      if (hinstDll == NULL)
  44.        hinstDll = pInjLibInfo->fnLoadLibrary(pInjLibInfo->pbLibFile);
  45.    }
  46.    else if (pInjLibInfo->ActionFlag == FREE_DLL)
  47.      pInjLibInfo->fnFreeLibrary(hinstDll);
  48.  
  49.    // The thread's exit code is the handle of the DLL.
  50.  
  51.    return((DWORD) hinstDll);
  52. }
  53.  
  54.  
  55. //////////////////////////////////////////////////////////////
  56.  
  57.  
  58. // This function marks the memory address after ThreadFunc.
  59. // ThreadFuncCodeSizeInBytes =
  60. //    (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
  61. static void AfterThreadFunc (void) {
  62. }
  63. #pragma check_stack 
  64.  
  65.  
  66. //////////////////////////////////////////////////////////////
  67.  
  68.  
  69. static BOOL InjectLibWorA (HANDLE hProcess,
  70.    const BYTE * const pbLibFile, BOOL fUnicode, BOOL ActionFlag)
  71. {
  72.  
  73.    // Kernel32.DLL's HINSTANCE is used to get the
  74.    // address of LoadLibraryA or LoadLibraryW and
  75.    // FreeLibrary.
  76.    HINSTANCE hinstKrnl = GetModuleHandle(__TEXT("Kernel32"));
  77.  
  78.    INJLIBINFO InjLibInfo;
  79.  
  80.    // The address to which code will be copied in the
  81.    // remote process
  82.    PDWORD pdwCodeRemote = NULL;
  83.  
  84.    // Calculate the number of bytes in the ThreadFunc
  85.    // function.
  86. #ifndef _PPC_
  87.    const int cbCodeSize = ((LPBYTE) (DWORD)
  88.       AfterThreadFunc - (LPBYTE) (DWORD) ThreadFunc);
  89. #else
  90.    // Note: The PowerPC does not support 32-bit immediate
  91.    // values. So, the VC++ PowerPC compiler implements 32-bit
  92.    // immediates using an offset into a table and grabbing
  93.    // the 32-bit value from the table. The references to
  94.    // the functions below, are actually offsets into this
  95.    // table. So, we have to subtract the contents of these
  96.    // offsets to get the actual code size.
  97.    const int cbCodeSize = ((LPBYTE) *(PDWORD)
  98.       AfterThreadFunc - (LPBYTE) *(PDWORD) ThreadFunc);
  99. #endif
  100.  
  101.    // The address to which INJLIBINFO will be copied in
  102.    // the remote process
  103.    PINJLIBINFO pInjLibInfoRemote = NULL;
  104.  
  105.    // The number of bytes written to the remote process
  106.    DWORD dwNumBytesXferred = 0;
  107.  
  108.    // The handle and ID of the thread executing the
  109.    // remote copy of ThreadFunc
  110.    DWORD dwThreadId = 0;
  111.    const DWORD cbMemSize =
  112.       cbCodeSize + sizeof(InjLibInfo) + 3;
  113.    HANDLE hThread = NULL;
  114.    HINSTANCE hinstDllRemote = NULL;
  115.  
  116.    BOOL fOk = FALSE;
  117.    DWORD dwOldProtect;
  118.  
  119.    // Initialize the INJLIBINFO structure here, and
  120.    // then copy it to memory in the remote process.
  121.    InjLibInfo.fnLoadLibrary = (PROCLOADLIBRARY)
  122.       GetProcAddress(hinstKrnl,
  123.          (fUnicode ? "LoadLibraryW" : "LoadLibraryA"));
  124.    InjLibInfo.fnFreeLibrary = (PROCFREELIBRARY)
  125.       GetProcAddress(hinstKrnl, "FreeLibrary");
  126.  
  127.    InjLibInfo.fnGetModuleHandle = (PROCGETMODULEHANDLE)
  128.       GetProcAddress(hinstKrnl,
  129.        (fUnicode ? "GetModuleHandleW" : "GetModuleHandleA"));
  130.  
  131.    InjLibInfo.ActionFlag = ActionFlag;
  132.  
  133.    InjLibInfo.pbLibFile[0] = 0;   // Initialized later
  134.  
  135.    __try {
  136.       // Finish initializing the INJLIBINFO structure
  137.       // by copying the desired DLL's pathname.
  138.       if (fUnicode)
  139.          wcscpy((LPWSTR) InjLibInfo.pbLibFile,
  140.             (LPCWSTR) pbLibFile);
  141.       else
  142.          strcpy((LPSTR) InjLibInfo.pbLibFile,
  143.             (LPCSTR) pbLibFile);
  144.  
  145.       // Allocate enough memory in the remote process's
  146.       // address space to hold our ThreadFunc function
  147.       // and an INJLIBINFO structure.
  148.       pdwCodeRemote = (PDWORD)
  149.          AllocProcessMemory(hProcess, cbMemSize);
  150.  
  151.       if (pdwCodeRemote == NULL)
  152.          __leave;
  153.  
  154.       // Change the page protection of the allocated memory
  155.       // to executable, read, and write.
  156.       fOk = VirtualProtectEx(hProcess, pdwCodeRemote,
  157.          cbMemSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
  158.       if (!fOk)
  159.          __leave;
  160.  
  161.       // Write a copy of ThreadFunc to the remote process.
  162.       fOk = WriteProcessMemory(hProcess, pdwCodeRemote,
  163.          (LPVOID)(DWORD) ThreadFunc, cbCodeSize,
  164.          &dwNumBytesXferred);
  165.       if (!fOk)
  166.          __leave;
  167.  
  168.  
  169.       // Write a copy of INJLIBINFO to the remote process.
  170.       // (The structure MUST start on an even 32-bit boundary.)
  171.       pInjLibInfoRemote = (PINJLIBINFO) 
  172.          ((PBYTE) pdwCodeRemote + ((cbCodeSize + 4) & ~3));
  173.  
  174.       // Put InjLibInfo in the remote thread's memory block.
  175.       fOk = WriteProcessMemory(hProcess, pInjLibInfoRemote,
  176.          &InjLibInfo, sizeof(InjLibInfo), &dwNumBytesXferred);
  177.       if (!fOk)
  178.          __leave;
  179.  
  180.  
  181.       hThread = CreateRemoteThread(hProcess, NULL, 0, 
  182.          (LPTHREAD_START_ROUTINE)(DWORD) pdwCodeRemote,
  183.          pInjLibInfoRemote, 0, &dwThreadId);
  184.       if (hThread == NULL)
  185.          __leave;
  186.  
  187.       WaitForSingleObject(hThread, INFINITE);
  188.    }  // __try
  189.    __finally {
  190.       if (hThread != NULL) {
  191.          GetExitCodeThread(hThread, (PDWORD) &hinstDllRemote);
  192.          CloseHandle(hThread);
  193.       }
  194.  
  195.       // Let the remote thread start executing the remote 
  196.       // ThreadFunc function using our modified stack, which
  197.       // now contains an initialized INJLIBINFO structure.
  198.       FreeProcessMemory(hProcess, pdwCodeRemote);
  199.    }  //__finally
  200.  
  201.    // Return TRUE if the DLL loaded successfully.
  202.    return(hinstDllRemote != NULL);
  203. }
  204.  
  205.  
  206. //////////////////////////////////////////////////////////////
  207.  
  208.  
  209. BOOL InjectLibA (HANDLE hProcess, LPCSTR lpszLibFile, BOOL ActionFlag)
  210. {
  211.   return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile, FALSE, ActionFlag));
  212. }
  213.  
  214.  
  215. //////////////////////////////////////////////////////////////
  216.  
  217.  
  218. BOOL InjectLibW (HANDLE hProcess, LPCWSTR lpszLibFile, BOOL ActionFlag)
  219. {
  220.   return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile, TRUE, ActionFlag));
  221. }
  222.  
  223.  
  224. //////////////////////// End Of File /////////////////////////
  225.