Holy cow, I wrote a book!
I can't believe you people are actually asking for backdoors.
If an end user can do it, then so can a bad guy.
What does that parenthetical mean?
How do you protect a registry key from an application?
And if applications don't have privileges to modify a key,
then who does?
The Windows security model is based on identity.
Applications don't have privileges.
Users have privileges.
If an application is running in your user context, then it can do
anything you can,
and that includes setting that "obscure registry key".
(This is a variation on
"Your debugging code can be a security hole".)
Same goes for DLLs.
There's no such thing as something
only an individual program/library can read/write to
You can't check the "identity of the calling library" because
you can't trust the return address.
Coming up with some other "magic encryption key" like the full path
to the DLL won't help either, because a key that anybody can guess
with 100% accuracy isn't much of a key.
UNIX has setuid,
but that still doesn't make applications security principals.
Even in UNIX, permissions are assigned to users, not to applications.
That's one of the reasons I get so puzzled when I hear people
"Windows should let me do whatever I want with my system",
while simultaneously saying,
"Windows should have used ACLs to prevent applications from
doing whatever they want with my system."
But when you are running an application,
the application is you.
If you can do it, then an application can do it
because the application is you.
Some people want to extend the concept of security principal
to a chunk of code.
"This registry key can be written to only by this function."
But how could you enforce this?
Once you let untrusted code enter a process,
you can't trust any return addresses any more.
How else could you identify the caller, then?
"Well, the DLL when it is created is given a magic cookie
that it can use to prove its identity by passing that cookie
to these 'super-secure functions'.
// SECRET.DLL - a DLL that protects a secret registry key
// this function is called by means to be determined;
// it tells us the magic cookie to use to prove our identity.
void SetMagicCookie(HANDLE hMagicCookie)
g_hMagicCookie = hMagicCookie;
and then the program can use the magic cookie to prove
that it is the caller.
For example, you could have
RegSetValueWithCookie(g_hMagicCookie, hkey, ...),
where passing the cookie means 'It's me calling, please give
me access to that thing that only I have access to."
RegSetValueWithCookie(g_hMagicCookie, hkey, ...)
That won't stop the bad guys for long.
They just have to figure out where the DLL saves that cookie
and read it, and bingo, they're now you.
// bad-guy program
int CALLBACK WinMain(...)
// call some random function from SECRET.DLL
// so it gets loaded and the magic cookie gets
// experimentation tells us that SECRET.DLL
// keeps its magic cookie at address 0x70131970
HANDLE hMagicCookie = *(HANDLE*)0x70131970;
RegSetValueWithCookie(hMagicCookie, hkey, ...);
Ta-da, we now have a program that writes to that
registry key that SECRET.DLL was trying to protect.
It does it by merely waiting for SECRET.DLL to receive
its magic cookie, then stealing that cookie.
"Well, sure, but if I combine that with the check-the-return-address
technique, then that'll stop them."
No, that doesn't stop anybody. All the bad guy has to do is
change the RegSetValueWithCookie(hMagicCookie, hkey, ...)
to code that hunts for a trusted address inside SECRET.DLL
and cooks up a fake stack so that when control reaches
RegSetValueWithCookie, everything in memory looks just
like a legitimate call to the function, except that the attacker
got to pass different parameters.
RegSetValueWithCookie(hMagicCookie, hkey, ...)
You can come up with whatever technique you want,
it won't do any good.
Once untrusted code has been granted access to a process,
the entire process is compromised and you cannot trust it.
Worst case, the attacker just sets a breakpoint on
RegSetValueWithCookie, waits for the breakpoint
to hit, then edits the stack to modify the parameters and resumes
That's why code is not a security principal.
Corollary: Any security policy that says "Applications cannot do X
without permission from the user" is flawed from conception.
The application running as the user is the user.
It's one thing to have this rule as a recommendation,
even a logo requirement,
but it's another thing to enforce this rule in the security subsystem.