home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / Chapt_04 / Patcher / Patcher.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  3.3 KB  |  121 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   : patcher.cpp                                                         //
  10. //  Description: API hacking by target relocation                                    //
  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 <assert.h>
  19.  
  20. #include "Patcher.h"
  21. #include "DisAsm.h"
  22.  
  23. bool HackCopy(void * pDest, void * pSource, DWORD nSize)
  24. {
  25. #ifdef WRITE_PROCESS
  26.  
  27.     static HANDLE hCurProcess = 0;
  28.  
  29.     DWORD dwWritten;
  30.  
  31.     bool rslt;
  32.     
  33.     if ( hCurProcess==0 )
  34.         hCurProcess = GetCurrentProcess();
  35.  
  36.     rslt = WriteProcessMemory(hCurProcess, pDest, pSource, nSize, & dwWritten) != 0;
  37.  
  38.     return rslt && (dwWritten==nSize);
  39.  
  40. #else
  41.  
  42.     __try
  43.     {
  44.         memcpy(pDest, pSource, nSize);
  45.     }
  46.     __except ( EXCEPTION_EXECUTE_HANDLER )
  47.     {
  48.         __try
  49.         {
  50.             MEMORY_BASIC_INFORMATION mbi;
  51.             
  52.             VirtualQuery(pDest, & mbi, sizeof(mbi));
  53.             VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, & mbi.Protect);
  54.  
  55.             memcpy(pDest, pSource, nSize);
  56.         }
  57.         __except ( EXCEPTION_EXECUTE_HANDLER )
  58.         {
  59.             return false;
  60.         }
  61.     }
  62.  
  63.     return true;
  64.  
  65. #endif
  66. }
  67.  
  68. #pragma pack(1)
  69.  
  70. // the longest instruction possible, 15 bytes
  71. typedef struct
  72. {
  73.     unsigned char opcode;
  74.     unsigned long addr;
  75.     unsigned char nop[10];
  76.  
  77. }   LongInstruction;
  78.  
  79.  
  80. bool KPatcher::Patch(HMODULE hModule, const TCHAR * name, int funcid, 
  81.                      void * pProxy, unsigned long * pNewAddress)
  82. {
  83.     unsigned char * pProc = (unsigned char *) GetProcAddress(hModule, name);
  84.  
  85.     if ( pProc==NULL )
  86.         return false;
  87.  
  88.     // length of first a few instructions no less than 5 bytes
  89.     int len = First5(pProc, name);
  90.  
  91.     if (len < 5)
  92.         return false;
  93.  
  94.     void * start = & m_buffer[m_bufpos];        // remember stub starting address
  95.  
  96.     Asm((char) 0x68); // push                    // push funcid
  97.     Asm((unsigned long) funcid);
  98.  
  99.     Asm((char) 0xE9); // jmp                    // jmp pProxy
  100.     AsmRel(pProxy);                        
  101.  
  102.     * pNewAddress = (unsigned long ) & m_buffer[m_bufpos];    // pProxy will transfer control to here
  103.  
  104.     // copy original function starting instructions    // original function prolog
  105.     memcpy(& m_buffer[m_bufpos], pProc, len); 
  106.     m_bufpos += len;
  107.     
  108.     // jump to instructions after the header        // jump prolog + len
  109.     Asm((char) 0xE9); // jmp
  110.     AsmRel(pProc + len);
  111.  
  112.     // change header to jump to code in m_buffer
  113.     LongInstruction inst;
  114.     memset(& inst, 0x90, sizeof(inst));
  115.     inst.opcode = 0xE9;                                        // jump
  116.     inst.addr   = (unsigned) start - (unsigned) (pProc+5);    // stub
  117.     
  118.     return HackCopy(pProc, & inst, len);
  119. }
  120.  
  121.