Mi duda me surge cuando vi este código:
#include <windows.h>
#include <stdio.h>
 
typedef int (WINAPI *_MessageBoxA)(HWND, LPCTSTR, LPCTSTR, UINT);
 
struct sTDatos_MessageBoxA
{
    _MessageBoxA direccionMessageBoxA;
    char titulo[255], texto[255];
};
 
typedef struct sTDatos_MessageBoxA TDatos_MessageBoxA;
 
void Hilo_MessageBoxA(TDatos_MessageBoxA *datos)
{
    datos->direccionMessageBoxA(0, datos->texto, datos->titulo, 0);
}
 
void Inyectar_MessageBoxA(DWORD pID, char* titulo, char* texto)
{
    DWORD tamFunc;
    HANDLE tHandle, funcionRemota;
    TDatos_MessageBoxA datos, *direccionDatosRemotos;
    void* direccionFuncionRemota;
 
    tHandle = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, 0, pID);
 
    datos.direccionMessageBoxA = (_MessageBoxA)GetProcAddress(GetModuleHandle("USER32.DLL"), "MessageBoxA");
 
    direccionDatosRemotos = (TDatos_MessageBoxA*)VirtualAllocEx(tHandle, 0, sizeof(TDatos_MessageBoxA), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    WriteProcessMemory(tHandle, direccionDatosRemotos, &datos, sizeof(TDatos_MessageBoxA), NULL);
 
tamFunc = (DWORD)Inyectar_MessageBoxA - (DWORD)Hilo_MessageBoxA;
 
direccionFuncionRemota = VirtualAllocEx(tHandle, 0, tamFunc, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
WriteProcessMemory(tHandle, direccionFuncionRemota, (void*)Hilo_MessageBoxA, tamFunc, NULL);
 
funcionRemota = CreateRemoteThread(tHandle, NULL, 0, (LPTHREAD_START_ROUTINE)direccionFuncionRemota, direccionDatosRemotos, 0, NULL);
 
WaitForSingleObject(funcionRemota,INFINITE);
   CloseHandle(funcionRemota);
 
   VirtualFreeEx(tHandle,direccionFuncionRemota,0,MEM_RELEASE);
   VirtualFreeEx(tHandle,direccionDatosRemotos,0,MEM_RELEASE);   
 
   CloseHandle(tHandle);   
}
 
int main()
{
    DWORD pID;
    HWND hWnd;
 
    hWnd = FindWindow("SciCalc", NULL);
 
    if(hWnd!=NULL)
    {
        GetWindowThreadProcessId(hWnd, &pID);
        Inyectar_MessageBoxA(pID, "descifra.me", "Codigo inyectado!");
    }
 
    return 0;
}
 
Cómo es que al crear un hilo en otro proceso se puede utilizar esta dirección en el hilo creado en el otro proceso:
datos.direccionMessageBoxA = (_MessageBoxA)GetProcAddress(GetModuleHandle("USER32.DLL"), "MessageBoxA");
Me surge la duda porque la llamada a GetModuleHandle se hace en un proceso distinto.