injlib.c

来自「一本已经绝版的好书」· C语言 代码 · 共 230 行

C
230
字号
/*************************************************************
Module name: InjLib.C
Notices: Copyright (c) 1995-1997 Jeffrey Richter
*************************************************************/


#include "..\CmnHdr.H"                  /* See Appendix C. */
#include <windows.h>
#include "ProcMem.H"
#include "InjLib.H"


//////////////////////////////////////////////////////////////


typedef HINSTANCE (WINAPI *PROCLOADLIBRARY)(LPBYTE);
typedef BOOL (WINAPI *PROCFREELIBRARY)(HINSTANCE);

typedef struct {
   PROCLOADLIBRARY fnLoadLibrary;
   PROCFREELIBRARY fnFreeLibrary;
   BYTE pbLibFile[MAX_PATH * sizeof(WCHAR)];
} INJLIBINFO, *PINJLIBINFO;


//////////////////////////////////////////////////////////////


// Calls to the stack checking routine must be disabled.
#pragma check_stack (off)

static DWORD WINAPI ThreadFunc (PINJLIBINFO pInjLibInfo) {
   // There must be less than a page worth of local
   // variables used in this function.
   HINSTANCE hinstDll;

   // Call LoadLibrary(A/W) to load the DLL.
   hinstDll = pInjLibInfo->
      fnLoadLibrary(pInjLibInfo->pbLibFile);

   // Calling LoadLibrary causes the system to map the DLL
   // into the remote process's address space and call
   // the DLL's DllMain with an fdwReason value of
   // DLL_PROCESS_ATTACH. The DLL can do whatever it wants 
   // during this processing. When DllMain returns, the system
   // returns the HINSTANCE of the DLL back from our call to 
   // LoadLibrary.  At this point, we call FreeLibrary, 
   // passing the library's HINSTANCE in order to free it.

   // If the DLL could not be loaded or if the library's
   // DllMain (DLL_PROCESS_ATTACH) returns FALSE, hinstDll
   // will come back as NULL.

   // If the library initialized successfully, free it.
   if (hinstDll != NULL)  {
      // Calling FreeLibrary causes the system to call the
      // DLL's DllMain with a reason of DLL_PROCESS_DETACH.
      // The DLL can perform whatever cleanup is necessary.
      pInjLibInfo->fnFreeLibrary(hinstDll);
   }

   // The thread's exit code is the handle of the DLL.
   return((DWORD) hinstDll);
}


//////////////////////////////////////////////////////////////


// This function marks the memory address after ThreadFunc.
// ThreadFuncCodeSizeInBytes =
//    (PBYTE) AfterThreadFunc - (PBYTE) ThreadFunc.
static void AfterThreadFunc (void) {
}
#pragma check_stack 


//////////////////////////////////////////////////////////////


static BOOL InjectLibWorA (HANDLE hProcess,
   const BYTE * const pbLibFile, BOOL fUnicode) {

   // Kernel32.DLL's HINSTANCE is used to get the
   // address of LoadLibraryA or LoadLibraryW and
   // FreeLibrary.
   HINSTANCE hinstKrnl = GetModuleHandle(__TEXT("Kernel32"));

   INJLIBINFO InjLibInfo;

   // The address to which code will be copied in the
   // remote process
   PDWORD pdwCodeRemote = NULL;

   // Calculate the number of bytes in the ThreadFunc
   // function.
#ifndef _PPC_
   const int cbCodeSize = ((LPBYTE) (DWORD)
      AfterThreadFunc - (LPBYTE) (DWORD) ThreadFunc);
#else
   // Note: The PowerPC does not support 32-bit immediate
   // values. So, the VC++ PowerPC compiler implements 32-bit
   // immediates using an offset into a table and grabbing
   // the 32-bit value from the table. The references to
   // the functions below, are actually offsets into this
   // table. So, we have to subtract the contents of these
   // offsets to get the actual code size.
   const int cbCodeSize = ((LPBYTE) *(PDWORD)
      AfterThreadFunc - (LPBYTE) *(PDWORD) ThreadFunc);
#endif

   // The address to which INJLIBINFO will be copied in
   // the remote process
   PINJLIBINFO pInjLibInfoRemote = NULL;

   // The number of bytes written to the remote process
   DWORD dwNumBytesXferred = 0;

   // The handle and ID of the thread executing the
   // remote copy of ThreadFunc
   DWORD dwThreadId = 0;
   const DWORD cbMemSize =
      cbCodeSize + sizeof(InjLibInfo) + 3;
   HANDLE hThread = NULL;
   HINSTANCE hinstDllRemote = NULL;

   BOOL fOk = FALSE;
   DWORD dwOldProtect;

   // Initialize the INJLIBINFO structure here, and
   // then copy it to memory in the remote process.
   InjLibInfo.fnLoadLibrary = (PROCLOADLIBRARY)
      GetProcAddress(hinstKrnl,
         (fUnicode ? "LoadLibraryW" : "LoadLibraryA"));
   InjLibInfo.fnFreeLibrary = (PROCFREELIBRARY)
      GetProcAddress(hinstKrnl, "FreeLibrary");
   InjLibInfo.pbLibFile[0] = 0;   // Initialized later

   __try {
      // Finish initializing the INJLIBINFO structure
      // by copying the desired DLL's pathname.
      if (fUnicode)
         wcscpy((LPWSTR) InjLibInfo.pbLibFile,
            (LPCWSTR) pbLibFile);
      else
         strcpy((LPSTR) InjLibInfo.pbLibFile,
            (LPCSTR) pbLibFile);

      // Allocate enough memory in the remote process's
      // address space to hold our ThreadFunc function
      // and an INJLIBINFO structure.
      pdwCodeRemote = (PDWORD)
         AllocProcessMemory(hProcess, cbMemSize);

      if (pdwCodeRemote == NULL)
         __leave;

      // Change the page protection of the allocated memory
      // to executable, read, and write.
      fOk = VirtualProtectEx(hProcess, pdwCodeRemote,
         cbMemSize, PAGE_EXECUTE_READWRITE, &dwOldProtect);
      if (!fOk)
         __leave;

      // Write a copy of ThreadFunc to the remote process.
      fOk = WriteProcessMemory(hProcess, pdwCodeRemote,
         (LPVOID)(DWORD) ThreadFunc, cbCodeSize,
         &dwNumBytesXferred);
      if (!fOk)
         __leave;


      // Write a copy of INJLIBINFO to the remote process.
      // (The structure MUST start on an even 32-bit boundary.)
      pInjLibInfoRemote = (PINJLIBINFO) 
         ((PBYTE) pdwCodeRemote + ((cbCodeSize + 4) & ~3));

      // Put InjLibInfo in the remote thread's memory block.
      fOk = WriteProcessMemory(hProcess, pInjLibInfoRemote,
         &InjLibInfo, sizeof(InjLibInfo), &dwNumBytesXferred);
      if (!fOk)
         __leave;


      hThread = CreateRemoteThread(hProcess, NULL, 0, 
         (LPTHREAD_START_ROUTINE)(DWORD) pdwCodeRemote,
         pInjLibInfoRemote, 0, &dwThreadId);
      if (hThread == NULL)
         __leave;

      WaitForSingleObject(hThread, INFINITE);
   }  // __try
   __finally {
      if (hThread != NULL) {
         GetExitCodeThread(hThread, (PDWORD) &hinstDllRemote);
         CloseHandle(hThread);
      }

      // Let the remote thread start executing the remote 
      // ThreadFunc function using our modified stack, which
      // now contains an initialized INJLIBINFO structure.
      FreeProcessMemory(hProcess, pdwCodeRemote);
   }  //__finally

   // Return TRUE if the DLL loaded successfully.
   return(hinstDllRemote != NULL);
}


//////////////////////////////////////////////////////////////


BOOL WINAPI InjectLibA (HANDLE hProcess, LPCSTR lpszLibFile) {

   return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile,
      FALSE));
}


//////////////////////////////////////////////////////////////


BOOL WINAPI InjectLibW (HANDLE hProcess, LPCWSTR lpszLibFile) {

   return(InjectLibWorA(hProcess, (LPBYTE) lpszLibFile, TRUE));
}


//////////////////////// End Of File /////////////////////////

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?