Делаю для антивирусной системы модуль эвристического анализа. Для этого из сервиса, работающего под системой, запускается специальный процесс и инжектируется в открывающиеся процессы с целью перенаправить определенные апишные функции на свой обработчик. Принцип инжекта простой - запускаемый процесс инжекта сам себя копирует в инжектируемый процесс, корректируя там релоки и вставляя код в памяти инжектируемого процесса для перенаправления на свои обработчики. Тестировал в системах Win7,8, Windows2008 server x86-x64. Вот код в котором происходит проблема:
BOOL Gl::HookProcess(DWORD idProcess, PVOID entryPoint, PWCHAR dllName, DWORD_PTR dllBaseAddress, Gl::PgFunclist funcList, WORD listCount)
{
    HMODULE hlib = NULL;
    HANDLE hpr = NULL;
    DWORD_PTR adr, BaseAddress = NULL, RemoteAddress = NULL, OldProc = NULL;
    PDWORD_PTR pRemoteAddress = NULL, pBaseAddress = NULL;
    BOOL result = FALSE;
    DWORD deltaf, oldprotect, nb;
    PVOID buf = NULL, p;
    #ifdef DBG
    PWCHAR tmp;    
    tmp = (PWCHAR)VirtualAlloc(NULL, 1000 * sizeof(WCHAR), MEM_COMMIT, PAGE_READWRITE);
    #endif 
    hlib = LoadLibrary(dllName);
    if(!hlib)
    return FALSE;    
    while(1)
   {
	    pBaseAddress = (PDWORD_PTR)VirtualAlloc(NULL, sizeof(DWORD_PTR), MEM_COMMIT, PAGE_READWRITE);
	   if(!pBaseAddress)
	   break;
          pRemoteAddress = (PDWORD_PTR)VirtualAlloc(NULL, sizeof(DWORD_PTR), MEM_COMMIT, PAGE_READWRITE);
	  if(!pRemoteAddress)
	  break;        
		
	   if(!Gl::HookCode(idProcess, entryPoint, &hpr, &BaseAddress, &RemoteAddress))
	   break;
          *pRemoteAddress = RemoteAddress;
          *pBaseAddress = BaseAddress;
          #ifdef DBG
          wsprintf(tmp, L"GHookCode %x %x\n", BaseAddress, RemoteAddress);
	   OutputDebugString(tmp);
          #endif
          buf = VirtualAlloc(NULL, 100, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
		
	   for(int i = 0; i < listCount; i++)
	   {
                  deltaf = Gl::GetDeltaFunction(hlib, funcList[i].funcName);		   		  
                  if(!Gl::SaveOldFunction(hpr, dllBaseAddress, deltaf, &OldProc))
		  continue;                      
           
                   adr = RemoteAddress + ((DWORD_PTR)(funcList[i].oldFunc) - BaseAddress);
		   WriteProcessMemory(hpr, (PVOID)adr, &OldProc, sizeof(DWORD_PTR), (SIZE_T*)&nb);
                    
                  RemoteAddress = *pRemoteAddress;
                  BaseAddress = *pBaseAddress;
                  #ifdef DBG
                  wsprintf(tmp, L"GHookCode %x %x\n", BaseAddress, RemoteAddress);
	          OutputDebugString(tmp);           
                 #endif           	  
		   adr = RemoteAddress + ((DWORD_PTR)(funcList[i].newFunc) - BaseAddress);                     
                  p = buf;
                  *((BYTE*)p) = 0xE9;
	           p = (PVOID)((DWORD_PTR)p + 1);           
                  *((DWORD*)p) = (DWORD)((LONG_PTR)adr - (LONG_PTR)(dllBaseAddress + deltaf + 5));
                  #ifdef DBG
                  wsprintf(tmp, L"delta %x\n", (DWORD)((LONG_PTR)adr - (LONG_PTR)(dllBaseAddress + deltaf + 5)));
	          OutputDebugString(tmp);
                  #endif 
		   adr = dllBaseAddress + deltaf;
                                
                  VirtualProtectEx(hpr, (PVOID)adr, 10, PAGE_READWRITE, &oldprotect);
                  WriteProcessMemory(hpr, (PVOID)adr, buf, 5, (SIZE_T*)&nb);           
                  VirtualProtectEx(hpr, (PVOID)adr, 10, oldprotect, &oldprotect);
                  RemoteAddress = *pRemoteAddress;
                  BaseAddress = *pBaseAddress;
	    }
             result = TRUE;
             break;
	}
	CWA(kernel32, FreeLibrary)(hlib);
	if(pBaseAddress)
        VirtualFree(pBaseAddress, 0, MEM_RELEASE);
        if(pRemoteAddress)
        VirtualFree(pRemoteAddress, 0, MEM_RELEASE);    
        if(buf)
        VirtualFree(buf, 0, MEM_RELEASE);
	if(hpr)
	CloseHandle(hpr);
	#ifdef DBG
	if(tmp)
        VirtualFree(tmp, 0, MEM_RELEASE);           
        #endif
	return result;
}
В 32-битных системах все нормально работает, в 64-битных выявилась следующая бяка:
После вызова WriteProcessMemory в x64 почему то переменные RemoteAddress и BaseAddress сбрасываются в 0. Поэтому пришлось ввести дополнительные переменные pRemoteAddress и pBaseAddress, в которых сохранять значения RemoteAddress и BaseAddress до вызова WriteProcessMemory и восстанавливать эти значения после вызова WriteProcessMemory. Причем пришлось создавать переменные из памяти процесса, а не из стека, иначе вообще код падает. Правда в процессе отключен RTL и проверка переполнения стека. Но все равно непонятно почему именно после вызова WriteProcessMemory происходит подобное.