Security: Preventing Unauthorized Loading/Calls into C++ DLL - c++

I have a C++ DLL, foo.dll, that provides API methods that give cleartext answers to encrypted data. I want to come up with a robust solution to only allow friendlies (eg. user.dll) to load this DLL and use its functions.
This is not a problem of DLL spoofing, but rather a question of how to hobble a DLL to only work in certain contexts. I'm in a potentially non-networked context on multiple platforms, so phoning home or relying on a system call is not a likely solution.
Something I've considered is a home brewed initialization step sharing a 'magic key' for initialization. With security, 'roll your own' is often bad.
Any advice of accepted practices for this kind of DLL level security?

The only way to protect encrypted data is by ensuring that it requires a very long, unpredictable and secret key to decrypt it. The security comes not from obscuring the method of decryption, but the key itself.
You cannot prevent someone from calling into your DLL but the functions in the DLL can require that the caller provide a decryption key as a parameter.
This way, only clients that know the secret key will be able to decrypt the contents.
You can try to cheat by embedding the decryption key somewhere in your DLL, but it can then be found simply by loading the DLL into a debugger. So don't do that.

Related

Are preprocessor directives safe for sensitive information?

I am creating an archive which contains HTML/CSS/JS files for my C++ application, and I don't want users to have access to these files. So, i decided to encrypt archive with password.
My first thought was to store a password inside a program via preprocessor macro (through CMake). But, is it safe?
Can you access the password back from compiled application? (exe, in my case)
And if you can, how to protect from it? Is it technically possible or i should give up and leave it as is?
If the macro is actually used in the application then yes, it's accessible in the executable file -- it has to be for the program to use it.
Any credential you embed in your program can be recovered by a sufficiently-motivated attacker. There is no encryption mechanism you can use to prevent this, as you would need to provide the decryption key for the program to function.
The proof is very simple: if the program itself can obtain the credential without any user input, then the executable file must contain the key, or all of the information needed to produce/derive the key. Therefore, it must be possible for anyone (with the requisite expertise) to produce the credential with only the information in the executable file.
This could be done by inspecting the executable. It could also be done by running the executable under the supervision of a debugger and watching what it is doing.
This is the same reason DRM schemes are pointless -- the consumer must be in possession of a key to use the material, and if they can get their hands on the key (they must be able to in order for them to consume the content) then they scheme doesn't work. (Of course, in newer DRM schemes the key is buried in a chip that is designed to destroy the key if it is opened, but that just means it's difficult to get the key, not impossible.)
tl;dr: It's never a question of whether it's possible to recover an embedded key. It's always possible. It's a question of how much effort it will take to recover that key.

keeping DLL on local computer secret, despite sharing with other programs on local computer

I've seen lots of discussion on this forum about keeping code secret, mainly in terms of preventing reverse engineering and decompiling. The typical answer is something along the lines of reverse engineering is always possible, and only thing 100% secure is not distributing your code.
I wrote a c++ function and compiled into a DLL that will only be kept on my computer. However, it needs to be used by an executable on my computer that (1) I didn't write, and (2) needs an internet connection. Is there anything I can do to ensure that the executable doesn't "reveal" the inner-workings my function to anyone at a remove location?
Your computer could be hacked, either by the one program using your DLL or by any other software you're using, and once hacked the DLL can be collected if it's of any interest to the attacker.
The software using your DLL may have the capability to upload the DLL, either directly or indirectly (such as by reporting crashes and logs)
If this DLL is manually injected into the program (or does anything else that may seem suspicious), it may be identified as a cheating/hacking tool either by part of the program or by things such as third party AVs (which occasionally love uploading files to their backend).
The three scenarios are not all that plausible, and unless this DLL contains a real secret or you have a real adversary interested in the content of your DLL i'd say you don't need to worry too much.

Is it safe to store sensitive data in a C++ compiled binary?

It's well known that dlls produced by .NET can be easily decompiled. This means that sensitive information (e.g. encryption keys) should not be stored in .NET binaries.
Would it be a sensible alternative to store sensitive data in (for example) C++ binaries which could be consumed by my .NET code? I don't yet know anything about interop stuff, but am curious about whether this could be an avenue worth pursuing. I guess to clarify, my questions are:
Could a binary produced in C++ (or C) be readily decompiled to access sensitive string data?
Is this a totally harebrained idea, either because it wouldn't work, would be very difficult to accomplish, or because a far better alternative exists which I haven't encountered yet?
The answer is no. Whilst its true a .NET dll can be trivially decompiled to its original structure, and a C/C++ dll can only be decompiled to a monster mess that a compiler would love, the data that's stored in there will be placed in a big, un-mangled, bucket so anyone who knew which part to look at (and, ok, all that data is crammed up close to each other so it becomes difficult to know which bit is which) but the data will be there for all to see.
Google for data segment which is where the static data in a native windows binary gets placed.
quick edit: of course, you can store encrypted information in your C++ binary, pre-encrypt it but you will have to use something else to store the decrypt key (eg your windows user password or similar). .NET allows you to store sensitive information in a config file and will easily encrypt it on first-run or install, this encrypts and decrypts it based on the user account details the app runs under (so don't change it, and keep a copy of the un-encrypted config file somewhere :-) )
String literals can be read from native(c c++ code compiled) binary (exe or dll)
There's always a way to sniff out the sensitive information in your binary file. The differences between .NET binaries and native binaries are the complexity of their reverse analysis (the root cause is NET code is run on process virtual machine (VM), so the protection mechanisms of .NET barely do some tricks beyond the VM). As you mentioned, .NET binaries can be easily decompiled, even you obfuscated your binary file by some obfuscator, such deobfuscators like de4dot can deobfuscate it easily. But the reverse analysis of native binaries is more difficult than the former. There are plenty more effective protection mechanisms in this field, such as anti-debugging, the virtual machine obfuscation and so on. These techniques could make your code more secure, of course this is a relative thing.
The answer is YES. Sensitive data can be stored in C++ compiled binaries. People who don't know anything about security do it all the time.
There are various degrees of security with different costs and inconveniences to users. Storing keys in code is fairly common but not very secure. Since you are using .NET that implies Windows and you might want to look into the data protection API (DPAPI). It encrypts data using your Windows user id password as the key.
Many laptops and servers includes a Trusted Platform Module (TPM) chip which will do encryption for you and protect the key for you.

How can I restrict access to an unmanaged dll to only a specific 3rd party (denying access to all others)?

I created an unmanaged C++ DLL that I'd like to provide to a 3rd-party. The DLL will be distributed publically but I don't want anyone else to be able to call methods in the DLL. What's a good way to restrict access?
FWIW - the DLL will be used on both Mac and Windows.
Ultimately, you can't stop somebody who's determined, but you can do a few things to make life difficult for unauthorized users.
The obvious would be to encrypt (at least most of) the code in the DLL. Have a single entry point that the user has to call to get (for example) a table of pointers to the real functions. When the entry point is called, a key has to be supplied and that is used to decrypt the rest of the content, and then the pointers are returned. If the user supplies the wrong key, they get pointers, but the data won't be decrypted correctly, so when they try to call it, it doesn't work.
That's not foolproof by any means. Just for an obvious example, if somebody runs the authorized program under a debugger they can see what key is passed, and simply re-use it. If you want to make life a bit trickier for an attacker, you can do something like having the DLL do a checksum on the executable, and use that as the key (and the user will have to embed some data to get the checksum to come out right). That can still be figured out, but it will at least take some work.
Edit: The exact encryption doesn't matter a lot. I'd probably use AES, simply because it's easy to find an implementation and it runs pretty fast, so there's not much reason to use something else.
As far as how the calling code would work, it would be something like this:
struct functions {
rettype1 (*func1)(args1);
rettype2 (*func2)(args2);
rettype3 (*func3)(args3);
// ...
};
void entry_point(key_type key) {
functions f;
decrypt(data_block);
f.func1 = data_block.offset1;
f.func2 = data_block.offset2;
// ...
return f;
}
In the calling code you'd have initialization something like:
functions f = entry_point(myKey);
and then calling a function would be something like:
f.whatever(arg1, arg2, arg3);
In essence, you're re-creating a small piece of object oriented programming, and having your entry point return an "object" of sorts, with the DLL's real functions as "member functions" of that "object".
As far as getting the checksum goes, I haven't thought through it in a lot of detail. Basically just just want the address where the executable is stored. You can walk through modules with VirtualQuery, or you can use GetModuleHandle(NULL).
Anyone with access to the dll will be able to inspect it, load it, and get pointers to functions in the dll. I'm not sure you strictly mean dll though as you say:
FWIW - the DLL will be used on both Mac and Windows.
Dlls aren't a Mac thing--they are a Windows specific implementation of a runtime loaded/linked library. So you're real question, I'm assuming, must simply be about limiting access to a library for only certain 3rd parties. To achieve your goal, some other options may be more appropriate:
Instead of a dll, compile everything into a single monolothic exe. Run that exe as a service or a second process on the box. Have the 3rd party connect to it through sockets/named pipes/whatever other forms of interprocess communication. Authenticate the users of the service so that only the 3rd party software with the right credentials can access the service. Everyone else gets denied access.
Create an account for the 3rd party application. The 3rd party application can only run when that account is logged in. Place the dll (or dylib in the case of Mac) in a folder only accessible to that account. Noone else has access to that location, so no other applications can run it barring those run as administrator.

Global (process wide) properties in Win32

I am trying to share some data across DLLs in a project which has an extremely complicated dependency structure (numberous DLLs).
I want to be able to associate a key with some data in one part of the application, and then extract that data by supplying the appropriate key in some other part of the app. In a way, one can say that I looking for something that is similar to Java's System.setProperty()/getProperty().
I was sure that the Process APIs would give me some access to a process-wide buffer, but I had no luck. Any ideas?
(I know that the clean solution is to introduce a new DLL and to link it properly to the existing DLLs. Unfortunately, this type of solution is beyond the mandate of my team).
You don't need fancy API's for that. Windows has a much older API precisely for this kind of stuff. These things are known as "atoms". You'd use functions as AddAtom and FindAtom. By default atoms are process-wide.
To be clear here there is one exe with multiple DLL's in only one process but multiple modules. So you aren't looking for inter-process communications.
In answer I see two strategies:
use Windows API atoms which are slightly limited (basically only string data) which can work within or between processes.
If you write a DLL which contains your speculated SetProperty/getproperty functionality you don't have to compile ALL the other DLL's again (which is presumably what is beyond your team's specification) - you only need to recompile those DLL's which are currently using your new features (set/getproperty) (which is presumably within your teams power). So this seems a direct and powerful solution.