Proxy DLLs are replacements of the original DLL. We know this. We have it mimic and forward exported symbols and functions to the original library, usually a simple jmp to the original exported function or structure which the module exposes. Things get more complicated when a function or structure references internal allocated stack memory (say a global variable that isn't exported for the proxy DLL to mimic yet it's used internally inside say an exported function). All you can do is load the proxy and within your substitute library load the original DLL which you've replaced, during the load you have the module handle to work on. It's typical of a shim which Windows has used for many things over the years. Patching anything in the original DLLs memory is possible at that point, and it's still system-wide since your replacement DLL is loaded by any process that wanted to load the original DnsXxX.dll. Am I missing something?
P.S: I see your updated post now, likely the crash occurs because the Dns_.DLL was performing the request and when it went to return your proxy DLL was already freed, so this EAT hook (residing in your proxy DLL) was no longer available. As soon as your DLL is freed that memory will not be resident, anymore. As long as your proxy DLL is loaded it's 100% responsible for forwarding everything to the original DLL. Really, this entire concept of proxy DLLs isn't something most will recommend unless it's only affecting a single process. Doing this system-wide is instability waiting to happen
Forum for discussion about user-mode development.
On modern versions of Windows the AppInit_DLLs registry key allows for system processes to be injected, in older versions of Windows user32's initialization code loaded them, which is why only processes that loaded user32 allowed them to load. Is that an option for you at all? You would still need 2 DLL entries however, a 32-bit and 64-bit DLL of course.
Accept nothing less than STATUS_SUCCESS