Your very design - treating non-sandboxed processes running with the same privileges and owner as yours as untrusted - is incompatible with the Windows security model.
There exist ways to authenticate an application to another via IPC, and even to verify the binary that an application is running from and the signature on that binary. However, there is no way to prevent the following cases which would break your security objective:
- a DLL loaded into the add-in / client process has created a hostile thread that can read the process memory, turning the client untrusted.
- another process has used debug APIs to modify the client process in memory, turning the client malicious.
- another process uses debug APIs to read the secret out of the client process after its retrieval (processes have ACLs which could prevent this, but any process with the same owner can overwrite that ACL).
Note that some of these could be prevented by doing things like checking the loaded DLLs or ACLs of the client process, or checking for open HANDLEs to the client process in other processes. However, these all fall victim to "Time Of Check to Time Of Use" (TOCTOU) attacks, where the attacker can ensure that the check passes (the client looks clean and trustworthy) and then invalidate the check result (inject DLLs, change ACLs, etc.) prior to the use of that check result (the service actually returning the secret).
Additionally, it is of course possible for any privileged (admin / SYSTEM / has SeDebug privilege) process to read the secret right out of your service's address space, without bothering with cooperative IPC mechanisms. Consider that MMC is frequently run as Administrator, implying that the user running it at least has the ability to launch privileged processes.
Leaving aside the privileged process case, though, you can avoid exposing the secret itself (assuming it's stored somewhere that other non-privileged users can't read) by instead having the IPC channel function as a relay for the information. That is, instead of the IPC client saying "Hey service, what's the secret?" and then directly using the secret to get the sensitive data, the IPC client could say "Hey service, what's sensitive data ?" and get the data without ever learning the secret.
Of course, this doesn't prevent that data from being exposed to other processes. Nor does it prevent other processes from taking over the legitimate IPC client and making it request all the sensitive data for them. At the end of the day, if you don't trust the programs that the user is running with the same privileges that they are using to run your process, you are trying to do the impossible. In that scenario - where the user themselves is potentially hostile (since they are presumably choosing to run, or at least enabling the running of, processes that want to steal your secret), there is no way in "full" Windows to prevent the user (or one of their "agents" i.e. processes they run with their full privileges) from learning a secret in one of their own processes.
Now, in fairness, you can make it hard to pull off such attacks. That's what DRM (in the form of media or software license checks) tries to do: it can't put a security boundary between the process and the secret (such as a license key, encrypted media key, or similar), so DRM authors put up what one security researcher described as a "nonsense boundary" instead. If the target process' address space makes no sense, and the process itself is constantly checking its own integrity and the binary is so obfuscated that it's hard to reverse engineer and remove all those checks quickly enough, then it can be quite hard to extract secrets from it. Still possible with time - anybody familiar with the history of DRM will note that most DRM schemes of interest to anybody (and some that were pure curiosities) have been cracked, sometimes very quickly - but maybe getting at least a short time is sufficient?
A few good questions, at this point, are:
- What assets are you trying to protect, and how valuable is each one?
- Where are the assets stored, and what are the trust boundaries around them?
- Who are the attackers, that would want to access the assets? (If the user or any system admin is a potential attacker, you're squarely stuck on the DRM problem).
- What are the attackers' privileges (if they're low, such as sandboxed Windows Store apps, then that's not a problem; if they're the same as your own - as seems to be the case - you have a problem)?
- What are the practical attack vectors by which the attackers could try to access the assets? Answering this question requires thinking about everything each attacker can do - for example, things like the
ReadProcessMemory API or potentially reading secrets right out of the file system or registry if they have enough privileges to satisfy, overwrite, or bypass the ACL - and is the part that is often trickiest for a novice to enumerate, but if you provide the info others can help you (as we've tried to do here).
- For each attack vector, how severe is the actual threat (likelihood of successful attack multiplied by damage)?
- How severe does a threat need to be before it becomes important to avoid it? In other words, how much risk can you accept?
- For each threat that poses too much risk, is there any way to mitigate it?
This process - enumerating the assets, their protections, their attackers, the potential attacks against them, the threat due to each potential attack, and mitigations (if any) for those threats - is called threat modeling, and is very useful.