A customer found that when they obtained the token to a process with OpenÂProcessÂToken
and passed that token to CreateÂEnvironmentÂBlock
, the returned environment variables didn’t match the actual environment variables of the other process. Is CreateÂEnvironmentÂBlock
broken?
No, CreateÂEnvironmentÂBlock
is not broken. The thing that’s broken is your expectations.
Nowhere does it say that CreateÂEnvironmentÂBlock
copies the environment of another process. After all, it’s not called CopyÂProcessÂEnvironmentÂBlock
. Indeed, the handle that you pass to CreateÂEnvironmentÂBlock
isn’t even a process handle!
What CreateÂEnvironmentÂBlock
does is create a new environment block for the user specified by the token. This is the mechanism that the system uses to create the initial environment for a user when they log in.
Environment variables are local to a process, and there is no documented way of extracting them. We asked the customer why they needed to extract the environment variables of another process. We never heard back.
If you really really needed to know what the environment in another process was, you could use code injection and ask from within that process.
I had to do something like this in a COM surrogate when I ported an in-process COM server component from 32-bit to 64-bit. The large MFC-based hosting application needed to stay 32-bit (for now) so I had it invoke the new 64-bit COM component out-of-process using the surrogate. Then I discovered that the surrogate does not inherit the creator's environment (it needed the PATH and a few other variables), and always starts up in C:\WINDOWS\SYSTEM32....
Hmmm; I had the reverse problem and found the simplest solution was to launch the executable that would contain the COM component myself. Oh well.
Sounds like a diagnostic tool. On modern Unix variants you can get this stuff out of PS if you are the user of the process you want to look at.
I wouldn’t be surprised if there’s a decent way to get this out of a process on Windows but I only came up with a terrible way. Hint: GetEnviornmentVariable has to be implemented somehow.
I’m certain that there is a way because Process Explorer is able to display the environment for processes on the system.
The most obvious way would be to inject a DLL.
There’s an edge case whereby if you’re the debugger of the process then you can just ask the process to call
GetEnvironmentVariable
for you.My gut says that the PEB has it. So use NtQueryInformationProcess to get the PEB base address and ReadProcessMemory to extract the data. I would consider the relevant struct part to be “stable enough” for widespread use. But it’s still not officially documented.