home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / pehack.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  5.3 KB  |  206 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : pehack.cpp                                                             //
  10. //  Description: API hooking through import/export table                             //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include "pehack.h"
  19.  
  20. KPEFile::KPEFile(HMODULE hModule)
  21. {
  22.     pModule = (const char *) hModule;
  23.  
  24.     if ( IsBadReadPtr(pModule, sizeof(IMAGE_DOS_HEADER)) )
  25.     {
  26.         pDOSHeader = NULL;
  27.         pNTHeader  = NULL;
  28.     }
  29.     else
  30.     {
  31.         pDOSHeader = (PIMAGE_DOS_HEADER) pModule;
  32.  
  33.         if ( IsBadReadPtr(RVA2Ptr(pDOSHeader->e_lfanew), 
  34.             sizeof(IMAGE_NT_HEADERS)) )
  35.             pNTHeader = NULL;
  36.         else
  37.             pNTHeader = (PIMAGE_NT_HEADERS) RVA2Ptr(pDOSHeader->
  38.                 e_lfanew);
  39.     }
  40. }
  41.  
  42.  
  43. // returns address of a PE directory
  44. const void * KPEFile::GetDirectory(int id)
  45. {
  46.     return RVA2Ptr(pNTHeader->OptionalHeader.DataDirectory[id].
  47.         VirtualAddress);
  48. }
  49.  
  50.  
  51. // returns PIMAGE_IMPORT_DESCRIPTOR for an imported module
  52. PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor(
  53.     LPCSTR pDllName)
  54. {
  55.     // first IMAGE_IMPORT_DESCRIPTOR
  56.     PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR) 
  57.         GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
  58.     
  59.     if ( pImport==NULL )
  60.         return NULL;
  61.  
  62.     while ( pImport->FirstThunk )
  63.     {
  64.         if ( stricmp(pDllName, RVA2Ptr(pImport->Name))==0 )
  65.             return pImport;
  66.  
  67.         // move to next imported module
  68.         pImport ++;
  69.     }
  70.  
  71.     return NULL;
  72. }
  73.  
  74.  
  75. // returns address of __imp__xxx variable for an import function
  76. const unsigned * KPEFile::GetFunctionPtr(
  77.     PIMAGE_IMPORT_DESCRIPTOR pImport, LPCSTR pProcName)
  78. {
  79.     PIMAGE_THUNK_DATA pThunk;
  80.  
  81.     pThunk = (PIMAGE_THUNK_DATA) RVA2Ptr(pImport->
  82.         OriginalFirstThunk);
  83.  
  84.     for (int i=0; pThunk->u1.Function; i++)
  85.     {
  86.         bool match;
  87.  
  88.         if ( pThunk->u1.Ordinal & 0x80000000 )    // by ordinal
  89.             match = (pThunk->u1.Ordinal & 0xFFFF) == 
  90.                      ((DWORD) pProcName);
  91.         else
  92.             match = stricmp(pProcName, RVA2Ptr((unsigned) 
  93.                      pThunk->u1.AddressOfData)+2) == 0;
  94.  
  95.         if ( match )
  96.             return (unsigned *) RVA2Ptr(pImport->FirstThunk)+i;
  97.         
  98.         pThunk ++;
  99.     }
  100.  
  101.     return NULL;
  102. }
  103.  
  104.  
  105. BOOL HackWriteProcessMemory(HANDLE hProcess, void * pDest, void * pSource, DWORD nSize, DWORD * pWritten)
  106. {
  107.     __try
  108.     {
  109.         memcpy(pDest, pSource, nSize);
  110.     }
  111.     __except ( EXCEPTION_EXECUTE_HANDLER )
  112.     {
  113.         __try
  114.         {
  115.             MEMORY_BASIC_INFORMATION mbi;
  116.             
  117.             VirtualQuery(pDest, & mbi, sizeof(mbi));
  118.             VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, & mbi.Protect);
  119.  
  120.             memcpy(pDest, pSource, nSize);
  121.         }
  122.         __except ( EXCEPTION_EXECUTE_HANDLER )
  123.         {
  124.             return FALSE;
  125.         }
  126.     }
  127.  
  128.     * pWritten = nSize;
  129.  
  130.     return TRUE;
  131. }
  132.  
  133. FARPROC KPEFile::SetImportAddress(LPCSTR pDllName, 
  134.     LPCSTR pProcName, FARPROC pNewProc)
  135. {
  136.     PIMAGE_IMPORT_DESCRIPTOR pImport = 
  137.         GetImportDescriptor(pDllName);
  138.  
  139.     if ( pImport )
  140.     {
  141.         const unsigned * pfn = GetFunctionPtr(pImport, pProcName);
  142.  
  143.         if ( IsBadReadPtr(pfn, sizeof(DWORD)) )
  144.             return NULL;
  145.  
  146.         // read the original function address
  147.         FARPROC oldproc = (FARPROC) * pfn;
  148.  
  149.         DWORD dwWritten;
  150.  
  151.         // overwrite with new function address
  152.         HackWriteProcessMemory(GetCurrentProcess(), (void *) pfn, 
  153.             & pNewProc, sizeof(DWORD), & dwWritten);
  154.  
  155.         return oldproc;
  156.     }
  157.     else
  158.         return NULL;
  159. }
  160.  
  161.  
  162. FARPROC KPEFile::SetExportAddress(LPCSTR pProcName, 
  163.     FARPROC pNewProc)
  164. {
  165.     PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)
  166.         GetDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);
  167.  
  168.     if ( pExport==NULL )
  169.         return NULL;
  170.  
  171.     unsigned ord = 0;
  172.  
  173.     if ( (unsigned) pProcName < 0xFFFF ) // ordinal ?
  174.         ord = (unsigned) pProcName;
  175.     else
  176.     {
  177.         const DWORD * pNames = (const DWORD *) RVA2Ptr(pExport->AddressOfNames);
  178.         const WORD  * pOrds  = (const WORD  *) RVA2Ptr(pExport->AddressOfNameOrdinals);
  179.         
  180.         // find the entry with the function name
  181.         for (unsigned i=0; i<pExport->AddressOfNames; i++)
  182.             if ( stricmp(pProcName, RVA2Ptr(pNames[i]))==0 )
  183.             {
  184.                 // get the corresponding ordinal
  185.                 ord = pExport->Base + pOrds[i];
  186.                 break;
  187.             }
  188.     }
  189.  
  190.     if ( (ord<pExport->Base) || (ord>pExport->NumberOfFunctions) )
  191.         return NULL;
  192.  
  193.     // use ordinal to get the address where export RVA is stored
  194.     DWORD * pRVA = (DWORD *) RVA2Ptr(pExport->AddressOfFunctions) +
  195.         ord - pExport->Base;
  196.  
  197.     // read original function address
  198.     DWORD rslt = * pRVA;
  199.  
  200.     DWORD dwWritten = 0;
  201.     DWORD newRVA = (DWORD) pNewProc - (DWORD) pModule;
  202.     HackWriteProcessMemory(GetCurrentProcess(), pRVA, & newRVA, sizeof(DWORD), & dwWritten);
  203.  
  204.     return (FARPROC) RVA2Ptr(rslt);
  205. }
  206.