《Windows图形编程》的pe文件类的实现代码:
#include "StdAfx.h"
#include "KPEFile.h"KPEFile::KPEFile(HMODULE hModule)
{
m_pModule = (LPBYTE)hModule;
if (::IsBadReadPtr(m_pModule,sizeof(IMAGE_DOS_HEADER)))
{
m_pDosHeader = NULL;
m_pNTHeader = NULL;
}
else
{
m_pDosHeader = (PIMAGE_DOS_HEADER)m_pModule;
if (::IsBadReadPtr(RVA2Ptr(m_pDosHeader->e_lfanew),sizeof(IMAGE_NT_HEADERS)))
{
m_pNTHeader = NULL;
}
else
 m_pNTHeader = (PIMAGE_NT_HEADERS)RVA2Ptr(m_pDosHeader->e_lfanew); }
}KPEFile::~KPEFile(void)
{

}const void* KPEFile::GetDirectory( int id )
{
    return RVA2Ptr(m_pNTHeader->OptionalHeader.DataDirectory[id].VirtualAddress);
}PIMAGE_IMPORT_DESCRIPTOR KPEFile::GetImportDescriptor( LPTSTR pDllName )
{
     PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)GetDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT);
 if (pImport==NULL)
    return NULL;  while (pImport->FirstThunk)
 {  LPCSTR szDllName = static_cast<LPCSTR>(RVA2Ptr(pImport->Name));
         TCHAR szwszDllName[MAX_PATH];
 ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,szDllName,-1,szwszDllName,MAX_PATH);  if (_tcsicmp(pDllName,szwszDllName)==0)
 {
  return pImport;
 }  pImport++;
 }
 return NULL;
}const unsigned long* KPEFile::GetFunctionPtr( PIMAGE_IMPORT_DESCRIPTOR pImport,LPTSTR pProcName )
{
     PIMAGE_THUNK_DATA32 pThunk;
 pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->OriginalFirstThunk);
//  pThunk = (PIMAGE_THUNK_DATA32)RVA2Ptr(pImport->FirstThunk);
 for (int i = 0;pThunk->u1.Function;i++)
 {
 bool match;
 if (pThunk->u1.Ordinal&IMAGE_ORDINAL_FLAG32)
 {
 match = ((pThunk->u1.Ordinal&0xFFFF)==((DWORD)pProcName));
 }
 else
 {
//  LPCSTR szFunctionName = static_cast<LPCSTR>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
 PIMAGE_IMPORT_BY_NAME pFuncName =static_cast<PIMAGE_IMPORT_BY_NAME>(RVA2Ptr((unsigned long)pThunk->u1.AddressOfData));
 TCHAR szwFunctionName[MAX_PATH];
 ::MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,reinterpret_cast<LPCSTR>(pFuncName->Name),-1,szwFunctionName,MAX_PATH);
 match = ((_tcsicmp(pProcName,szwFunctionName))==0);
 }  if (match)
      return (unsigned long*)RVA2Ptr(pImport->FirstThunk)+i;  pThunk++;
 }  return NULL;
}FARPROC KPEFile::SetImportAddress( LPTSTR pDllName,LPTSTR pProcName,FARPROC pNewProc )
{
   PIMAGE_IMPORT_DESCRIPTOR pImport = GetImportDescriptor(pDllName);
   if (NULL!=pImport)
   {
   const unsigned long* pfn = GetFunctionPtr(pImport,pProcName);
   if(::IsBadReadPtr(pfn,sizeof(DWORD)))
   return NULL;    // 读取原来的地址
   FARPROC oldproc = (FARPROC)*pfn;
   DWORD dwWritten;    BOOL bRet = WriteProcessMemory(GetCurrentProcess(),(void*)pfn,&pNewProc,sizeof(DWORD),&dwWritten);
   return oldproc;
   }
   else
   return NULL;
}FARPROC KPEFile::SetExportAddress( LPTSTR pProcName,FARPROC pNewProc )
{
     PIMAGE_EXPORT_DIRECTORY pExport = (PIMAGE_EXPORT_DIRECTORY)GetDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT);  if (NULL==pExport)
    return NULL;  unsigned ord =0;
 if ((unsigned)pProcName<0xFFFF) //ordinal
 {
 ord = (unsigned)pProcName;
 }
 else
 {
 const DWORD* pNames = (const DWORD*)RVA2Ptr(pExport->AddressOfNames);
 const WORD *pOrds = (const WORD*)RVA2Ptr(pExport->AddressOfNameOrdinals);  for (unsigned i =0;i<pExport->AddressOfNames;i++)
 {
            if(_tcsicmp(pProcName,static_cast<TCHAR*>(RVA2Ptr(pNames[i])))==0)
{
ord = pExport->Base + pOrds[i];
break;
}
 }
 }  if ((ord<pExport->Base)||(ord>pExport->NumberOfFunctions))
    return NULL;  DWORD dwWritten = 0;
 DWORD *pRVA = (DWORD*)RVA2Ptr(pExport->AddressOfFunctions)+ord-pExport->Base;
 DWORD rslt = *pRVA;
 DWORD newRVA = (DWORD)pNewProc-(DWORD)m_pModule;
 WriteProcessMemory(GetCurrentProcess(),pRVA,&newRVA,sizeof(DWORD),&dwWritten);  return (FARPROC)RVA2Ptr(rslt);
}
       外部调用这个类的接口的代码:
int WINAPI MyMessageBox(HWND hWnd,LPCTSTR pText,LPCTSTR pCaption,UINT nType)
{
     TCHAR szText[MAX_PATH];
 TCHAR szCaption[MAX_PATH];
 _tcscat(szText,_T("intercepted"));
 _tcscat(szCaption,_T("intercepted"));
 return ::MessageBox(hWnd,pText,pCaption,nType);
}int APIENTRY _tWinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPTSTR    lpCmdLine,
                     int       nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);  // TODO: 在此放置代码。    KPEFile pe(hInstance);
pe.SetImportAddress(_T("user32.dll"),_T("MessageBoxW"),(FARPROC)MyMessageBox);
::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK); return 0;
}
     这个程序要实现的功能是将该进程导入的user32.dll中的MessageBoxW函数动态替换为我编写的MyMessageBox,程序编译环境为VS C++2005,unicode字符集。经过调试进入 KPEFile::SetImportAddress后能找到MessageBoxW函数的地址,WriteProcessMemory函数的返回值也是正确的,但是运行完::MessageBox(NULL,_T("Test"),_T("SetImportaddress"),MB_OK);这一步后却出现写入冲突,错误图片如下: