19

I have an old project in VB which created an unique pc code from MAC address and disc id. This was used to identify a pc so credentials cannot be used between pcs.

This project migrated to C#, and I encapsulated this logic in a DLL which simply calls a method that returns the pc_id.

The issue I have now is that it's damn easy to just create a new DLL which has the same class name and method signature and return whatever pc_id they wish.

How can I ensure the DLL my program is referencing is actually mine?

I thought of comparing the hash of my DLL with a hardcoded one, but is this safe between different OS? Will the hash of the file change between file systems?

Or which method is preferred when ensuring files integrity/origin?

RoraΖ
  • 12,317
  • 4
  • 51
  • 83
Vallo
  • 319
  • 1
  • 2
  • 7
  • You can use a hash, or you could sign the file with a private key. You could then store the public key hardcoded, and verify that the DLL is yours. – RoraΖ Apr 21 '15 at 11:41
  • 21
    How do you ensure that the program running is actually yours? If you can't do that what use is ensuring the DLL is yours. – bdsl Apr 21 '15 at 16:30
  • 7
    Whom you're trying to protect with a hash? A hash is useful to protect the user by detecting if a DLL has been tampered with by some other party (e.g. if the DLL was downloaded from somewhere). However, if the user itself is actively trying to replace the DLL, then all bets are off. The user likely also could just modify the main program to check against a different hash or to skip validation altogether. – jamesdlin Apr 21 '15 at 19:05
  • 4
    Please edit your question to explain your threat model. What kinds of threats are you trying to defend against? What kinds of attackers or scenarios? What are your goals, i.e., what are you trying to prevent? Are you trying to ensure the user has a valid licensed copy of your software? Are you trying to do DRM? How would you respond to @bdsl? Please read the comments in http://security.stackexchange.com/help/on-topic and edit your question accordingly (e.g., "What background should I give in my question?"). – D.W. Apr 21 '15 at 22:40
  • 2
    Imagine if you could. Then how do you ensure they don't just modify your program to remove the DLL modification check? – user253751 Apr 22 '15 at 06:49
  • 1
    I the DLL is really small, couldn't you just encode its bytes into a static variable in your main program and load it from there and not from the file-system ? – Falco Apr 22 '15 at 09:16
  • Since your new program in in C# it's trivial to modify it and remove the check. Decompilers like ILspy get you simple to understand code to change. [1]http://ilspy.net/ – Josef Apr 22 '15 at 11:26
  • 4
    Sounds like the usual impossible to solve DRM problem. – CodesInChaos Apr 22 '15 at 20:11
  • I understand there's always a workaround to skip any validation. Security is not a huge issue here (and I'm very underqualified in this subject), but at least I try to not make it very easy to skip this validation. Also this pc_id is just to prevent a user using same account across pcs, it's not the real DRM. Thank you all for your replies! – Vallo Apr 23 '15 at 12:33

5 Answers5

41

For Windows binaries, I would suggest to digitally sign the file.

Where you use certificates, almost the same technology of HTTPS.

Introduction to Code Signing

SignTool

Then you should use Windows cryptographic APIs to verify the signature of loaded DLLs.

I know that to get this done, you need lot of work. But, for Windows, this is the safest path. If SHA hashes are not enough, this is the alternative.

Marcos Zolnowski
  • 456
  • 1
  • 5
  • 5
  • I'm confused. I agree that a digital signature backed by a trusted authority is the better route, however don't all the comments in the original post still hold? Can't the attacker still modify the assembly to skip the signature verification check? Or by 'For Windows binaries' do you mean unmanaged code (which is more difficult to modify)? – JohnZaj Mar 24 '17 at 02:26
  • Before loading the DLL, you check his signature. The signature holds the checksum of the content. If you change a single bit of it (managed or unmanaged), they will not match. – Marcos Zolnowski Mar 24 '17 at 17:35
  • Sure, makes sense. I guess it really depends on the threat model. For example: ASSUME they have access to the DLL which does the loading and validates the signature. They can just remove that defensive code doing the signature validation. (quite easily, it took me a few minutes). Hopefully my obfuscation tooling holds this up I guess... – JohnZaj Mar 24 '17 at 18:19
  • 1
    Yes, the next step would be to remove the verification from the EXE. So, you must also sign the EXE. Setup Windows to verify the EXE before execution. They are called Group Policy - Software Restriction Policies. This means Windows will only execute files signed with your certificate. For Windows, this is the best you get on security. – Marcos Zolnowski Mar 24 '17 at 18:29
  • Do these Group Policy Software Restriction Policies only apply to an EXE file (or rather a process?). For instance I am really only trying to protect a couple of managed DLLs, would that still be possible? Or are you saying that I have to introduce an exe into the mix, such as having one of my assemblies load the exe which has been digitally signed? "This means Windows will only execute files signed with your certificate" can that file be a dll rather than an exe? – JohnZaj Mar 26 '17 at 17:41
  • The thing is, someone has to load your DLLs. If the process (instance) is compromised, having a signed DLL will be of little help. Whoever controls the system, can bypass the system. – Marcos Zolnowski Mar 26 '17 at 19:56
30

With the low level of protection the MAC address offers, I wouldn't bother. It is less effort to change the MAC address than it is to exchange your DLL.

Simon Richter
  • 1,482
  • 11
  • 8
16

Hashes do not change between file systems. Check the SHA1 hash of the file against the known "good" value in your code and you should be away!

AlexH
  • 1,168
  • 6
  • 8
  • 13
    Which is also trivial to work around with a [shim](https://technet.microsoft.com/en-us/library/dd837644%28v=ws.10%29.aspx). Not a bad answer, mind you, but you have to understand about the limitation – Stephane Apr 21 '15 at 12:15
  • 5
    And yet, you can just nop out the function that's checking the hash and bypass it. You cannot 100% ensure that the DLL is the correct one. – rev Apr 21 '15 at 19:19
  • 4
    IMHO this is a bad answers as long as it doesn't **also** explain that **the question is wrong**. – o0'. Apr 22 '15 at 16:03
7

If you goal is to prevent credentials from being used on other PCs, then take a look at Windows Data protection API. With it, you can encrypt your credentials, or any other data, and it will be decryptable only on this computer (or only under current windows user account, if you need that).

alex
  • 171
  • 5
0

Not only is the MAC address not a lot of protection but keying it to a disk ID is a bad thing--not all "disks" return a consistent disk ID. The problem is some RAID controllers respond to a request for a disk ID by obtaining it from whatever drive happens to be available.

Not to mention what happens if someone upgrades some hardware.

Loren Pechtel
  • 763
  • 4
  • 9
  • If they upgrades their hardware they just request a reset of their pc_id. This validation is just to prevent using the same credential in several pcs. I didn't know that about RAID, since any of our users had a RAID. Our clients generally use old hardware and notebooks mostly, so we never had any issues with this topic. – Vallo Apr 23 '15 at 12:31
  • @Vallo I've seen a RAID array in a machine from the mid 00s--admittedly a high end machine when it was bought. I've owned RAID-capable laptops since about that time, also (but I've never actually used the RAID capabilities.) – Loren Pechtel Apr 23 '15 at 17:28