none
private communication between .NET and C++ native DLL. RRS feed

  • Question

  • Hello

    I have a .net program that use DllImport to call a c++ native function exposed in a dll. My .NET program calls this function with a password that I would like to keep secret. I care about the security of my application and I would like to know if it's possible for someone to catch the password at runtime during the time between it is emitted by the .NET program till it's received by the DLL. I wonder if it's easier to catch confidential data in such context of communication between 2 different programs?

    I'm not well aware about such spying technique.. so I'm very grateful for any explanations you can give.

    Max
    Friday, August 9, 2013 10:05 AM

Answers

  • DLLImport is for communications between a program and a native dll in the same process, not a method for communication between programs.

    The thing you should not do to an encrypted string is to copy it to another a string (regardless of the method). That means you should not pass it in plain form to the C++ code, and better not to pass to/from the C++ code at all. It is very easy to set breakpoints to all exported function of a dll and inspect parameter values.



    Visual C++ MVP


    Friday, August 9, 2013 11:18 PM
  • Either write the whole thing in C++ or in C# (e.g. using SecureString). 

    You can refuse to run when you find your program is being debugged, but then the debugger can hook whatever you use to check the presence and report false values. 

    A managed dll won't have exported functions for debugging, but you got so many tools to decompile the whole thing. 



    Visual C++ MVP

    Monday, August 12, 2013 7:17 PM
  • This thread is going nowhere. There's no such thing as private communication between 2 dlls.

    They're both running on the same machine and that means that whoever is trying to hack has access to all necessary passwords, encryption keys and so on. One can simply use a debugger and place a breakpoint on the native function or he can decompile the .NET dll and figure out what password it sends or he can disassembly the native dll to figure out the password or remove the password check completely.

    In the end is only a matter of how much is that dll worth to someone. If it's valuable enough then someone will find a way to hack it.

    SSL has nothing to do with this. SSL relies on the 3 parties involved not having direct access to each others information.

    Thursday, August 15, 2013 5:54 AM
    Moderator

All replies

  • DLLImport is for communications between a program and a native dll in the same process, not a method for communication between programs.

    The thing you should not do to an encrypted string is to copy it to another a string (regardless of the method). That means you should not pass it in plain form to the C++ code, and better not to pass to/from the C++ code at all. It is very easy to set breakpoints to all exported function of a dll and inspect parameter values.



    Visual C++ MVP


    Friday, August 9, 2013 11:18 PM
  • Thank you for you reply.

    > That means you should not pass it in plain form to the C++ code

    How can I do then? I want exported function of the DLL to check the password before to execute. That is because I would like to make it difficult for any process other than my .NET program to use this function.

    > It is very easy to set breakpoints to all exported function of a dll and inspect parameter values.

    ah.. How can I make debugging more difficult?

    Is it also easy to set breakpoints inside the .NET compiled program?

    Saturday, August 10, 2013 5:52 AM
  • Either write the whole thing in C++ or in C# (e.g. using SecureString). 

    You can refuse to run when you find your program is being debugged, but then the debugger can hook whatever you use to check the presence and report false values. 

    A managed dll won't have exported functions for debugging, but you got so many tools to decompile the whole thing. 



    Visual C++ MVP

    Monday, August 12, 2013 7:17 PM
  • I wrote the function in a native C++ DLL because I want to protect the source code while keeping efficiency. If I would write it in C#, MSIL would be easy to spy even with obfuscation. On the other hand, I don't want to write the whole program in C++, so it's necessary to call the function from C# and to authorize only the C# program to use the C++ function.

    Let me come back to what you said in your first post:

    • The thing you should not do to an encrypted string is to copy it to another a string (regardless of the method).

    > I don't understand this sentence. Why to copy is a problem?

    • That means you should not pass it in plain form to the C++ code, and better not to pass to/from the C++ code at all.

    > If not in plain form, how can I pass it to the C++ code? Despite C++ debugging, is it possible to catch the password from the C# call (I mean before it's received by the C++ function)?

    • Edited by mathmax Wednesday, August 14, 2013 4:39 AM
    Wednesday, August 14, 2013 4:38 AM
  • Making a copy (e.g. pass to a C++ dll) requires you to decode the string. Can be easily attacked by debugging aka MIIM.

    You can have a handshake then use a session key to encrypt the transportation. But then you need to secure the handshake. You probably want to check how SSL/TLS works against eavesdropping.



    Visual C++ MVP

    Wednesday, August 14, 2013 4:31 PM
  • Sorry I read several times your message but I really can't understand what you mean by "decode the string": I simply pass a password to the C++ DLL, no need to encode nor decode anything. However I understand that the password can be caught by debugging. What does 'MIIM' stand for?

    SSL/TLS is a protocol for network communication. Can it also be used to secure communications between a program and a native dll? I can't find articles on internet that explain usage for similar case.. if you have any examples or further explanation, I would be very interested to read them.

    Well.. I also had the idea to use the password as public key (no worry if someone spies it with debugging tool). Then the return values will be encrypted with the password by the C++ function and decrypted with a private key by the .NET program. This would not prevent the execution of the C++ function but it would make the results only readable by the .NET program. How do you think about this ?

    Wednesday, August 14, 2013 6:08 PM
  • MIIM stands for man in the middle. Say if I drop a proxy dll into the application folder and dump anything close on the stack then forward all calls to your original, then your password would be revealed when your program thinks it is calling the C++ dll (e.g. http://www.codeforfun.it/2012/08/30/directx-hooking-with-a-proxy-dll/). It can also be a human that set the breakpoint at exported functions and watch parameters when they pass.

    You can encrypt what you are passing like SSL/TLS does to web authentication. E.g. generate an one-time key to encrypt the password then pass the password in the encrypted form.




    Visual C++ MVP

    Wednesday, August 14, 2013 9:31 PM
  • Thank you for explaining.

    • You can encrypt what you are passing like SSL/TLS does to web authentication. E.g. generate an one-time key to encrypt the password then pass the password in the encrypted form.

    > Then what does the DLL do with the encrypted password? Could you complete the following schema:

    .NET program :                                                                   C++ native DLL

    1. create one-time private key

    2. encrypt the password with the one-time key

    3. send the password        ----------------------->   ???  

                                                                                     5. execute the function

                                            <-----------------------    6. send back the results (encrypted?)








    • Edited by mathmax Thursday, August 15, 2013 3:31 AM
    Thursday, August 15, 2013 3:28 AM
  • You can decrypt the password into a buffer, use the password to log on, then zero out the buffer.

    Does the result contain confidential information too?



    Visual C++ MVP

    Thursday, August 15, 2013 3:32 AM
  • How can the DLL decrypt the password without access to the one-time private key?

    Does the result contain confidential information too?

    No. The function only return calculated results. But if the results are encrypted, they are unusable.

    Thursday, August 15, 2013 4:51 AM
  • you can pass the key in the same call but that would be too obvious. Pass in another function. Hide it anyway you want.


    Visual C++ MVP

    Thursday, August 15, 2013 5:33 AM

  • why is it similar to SSL? SSL doesn't send the private key for decrypting on the other side..
    Thursday, August 15, 2013 5:43 AM
  • This thread is going nowhere. There's no such thing as private communication between 2 dlls.

    They're both running on the same machine and that means that whoever is trying to hack has access to all necessary passwords, encryption keys and so on. One can simply use a debugger and place a breakpoint on the native function or he can decompile the .NET dll and figure out what password it sends or he can disassembly the native dll to figure out the password or remove the password check completely.

    In the end is only a matter of how much is that dll worth to someone. If it's valuable enough then someone will find a way to hack it.

    SSL has nothing to do with this. SSL relies on the 3 parties involved not having direct access to each others information.

    Thursday, August 15, 2013 5:54 AM
    Moderator
  • I read about SSL and try to see the similarity with what Sheng Jiang suggested. However, it's difficult because I'm not very familiar with these concepts. I can't figure out which of DLL and .NET program is associated to the server, and which is associated to the client. I can neither associate the certification Authority to any party.. If you could detail the schema of the handshake protocol, I may be able to understand.

    Besides, I didn't have your feedback to this simple idea:

    I also had the idea to use the password as public key (no worry if someone spies it with debugging tool). The C++ function will only run if the password match its expectation. Then the return values will be encrypted with the password by the C++ function and decrypted with a private key by the .NET program. This would not prevent the execution of the C++ function but it would make the results only readable by the .NET program. How do you think about this ?


    • Edited by mathmax Thursday, August 15, 2013 6:41 AM
    Thursday, August 15, 2013 6:38 AM
  • "I read about SSL..."

    Forget about SSL, it simply has nothing to do with this.

    "Then the return values will be encrypted with the password by the C++ function and decrypted with a private key by the .NET program."

    And the private key will be embedded in the .NET program and anyone who has the dll can retrieve it. That's the difference from SSL, those SSL certificates contain private keys. Normally you don't have access to those keys but if you can break into server and steal the certificate then it's game over. Hacking a server can be difficult, decompiling a dll, especially a .NET one, not so much.

    Thursday, August 15, 2013 6:49 AM
    Moderator
  • yes, but I can take measures to hide the private key inside the .NET program.

    For example, write a binary representation of it, divide it into different blocks and combine them at run time, then obfuscate the parts of the program involved in assembling the private key.


    Thursday, August 15, 2013 7:19 AM
  • Yes, you can make it more difficult for someone to retrieve the key. But you cannot make it impossible, even with obfuscation it can be pretty easy to understand small pieces of the program, enough to be able to retrieve such a key.

    Thursday, August 15, 2013 7:29 AM
    Moderator
  • Yes, that's enough for me. I just want to have a protection... so that it's not too easy for someone to use the DLL.

    I have now another idea for which I don't have to encrypt the results.

    the native DLL has now 2 functions :

    • The first C++ function will wait for a password (the password is a public key). If the password match, the function creates a new GUID, encrypts it with the public key and returns it to the .NET program.
    • The encrypted GUID is decrypted by the .NET program using the private key.
    • Now the second C++ function will wait for receiving the GUID in plain form.
    • The .NET program sends the GUID to the second function + others parameters needed for calculation.
    • If the GUID match, the second C++ function will execute and return the results in plain form.
    • After execution, the second function will be locked, until a new GUID is created.

    Except the fact that i's possible to retrieve the private key by spying the .NET source, do you see other security flaws with this methods?




    • Edited by mathmax Thursday, August 15, 2013 7:51 AM
    Thursday, August 15, 2013 7:50 AM
  • "If the GUID match, the second C++ function will execute and return the results in plain form"

    And I look at the C++ function with a disassembler and then I remove the GUID matching code with a hex editor, that's usually a 2 byte modification. Then I can use the function by supplying any GUID.

    Thursday, August 15, 2013 8:02 AM
    Moderator
  • I don't know how difficult it is because I have never used a disassembler. I should maybe try in order to realize. Which tool do you advise?

    However with the first solution I suggested, I guess it would also be possible to remove the part that encrypts the results, right? Is it so easy to achieve?

    Which one is the safest : first idea or second idea?



    • Edited by mathmax Thursday, August 15, 2013 8:48 AM
    Thursday, August 15, 2013 8:47 AM
  • "I don't know how difficult it is because I have never used a disassembler. I should maybe try in order to realize. Which tool do you advise?"

    If you don't know disassembly then it's probably pointless. IDA is a well known disassembler (and native decompiler) but I don't think it has a free version.

    "However with the first solution I suggested, I guess it would also be possible to remove the part that encrypts the results, right? Is it so easy to achieve? "

    Removing the encryption could be more difficult, it really depends on how it is done. In this case it may be easier for someone to extract the key.

    In general, the problem is not how to do it. Just come up with some convoluted enough scheme that prevents the dll to be used easily. The problem is when enough is enough? It really depends on how much time (and maybe money) you want to spend on this.

    Thursday, August 15, 2013 9:02 AM
    Moderator
  • If you don't know disassembly then it's probably pointless. IDA is a well known disassembler (and native decompiler) but I don't think it has a free version.

    > I tried it. Version 5.0 is free. But you're right, I'm not able to understand assembly language so it's pointless.

    Removing the encryption could be more difficult, it really depends on how it is done. In this case it may be easier for someone to extract the key.

    > Maybe I can twist the GUID matching code to make it more difficult to locate in the assembly code. But as I don't know assembly language, I have no idea how to code it in a more complex way. Would you have an advice?

    Is there any other weak point in the second method I suggested?

    Thursday, August 15, 2013 9:16 AM
  • "Is there any other weak point in the second method I suggested?"

    All methods have some weak points. The best you can hope that whoever might be interested in your dll doesn't have the necessary skills to hack such stuff. But if he does then all this stuff is pretty much useless.

    And seriously, how long are you going to beat the dead horse of dll "protection"? I just realized that you asked a similar question couple of months ago. And I replied to that thread too...

    Thursday, August 15, 2013 9:31 AM
    Moderator
  • well.. ok. Thank for your previous advices anyway.

    I just think it's a pity because there are many scenarios where we want to develop applications in a managed environment and with rich user interface. For this, .NET is the perfect solution.

    On the other hand, .NET is very easy to reverse engineer.. so when we want to protect the intellectual property of an algorithm, MSIL is surely not the best solution.

    I came up with the solution to split concerns and use C++ for the sensitive algorithm while developing the rest of the application with .NET, but the bad side effect is that I have to expose the C++ function publicly.

    It would be very useful to be able to write native code and to 'wrap' it by some means it inside the .NET application so that the whole thing behave as only one program (no public function exposed). Something different than DllImport...?
    Thursday, August 15, 2013 1:01 PM
  • "On the other hand, .NET is very easy to reverse engineer"

    Well, that's why we have obfuscators. You can still decompile obfuscated dlls but it's more difficult to understand the code. And don't forget that native code can be decompiled too, the only difference is that the results are usually poorer than for MSIL.

    "It would be very useful to be able to write native code and to 'wrap' it by some means it inside the .NET application so that the whole thing behave as only one program"

    That's something C++/CLI can do but then it means that you have to write the app in C++/CLI instead of C# or VB. And that doesn't mean that someone can't look at the MSIL code, figure out that it calls a native function and attempt to call it directly. It's a lot more trouble but it's not impossible.

    "Something different than DllImport...?"

    Well, you could use LoadLibrary/GetProcAddress but anyway the dll must export the function.

    Thursday, August 15, 2013 1:55 PM
    Moderator
  • "And that doesn't mean that someone can't look at the MSIL code, figure out that it calls a native function and attempt to call it directly."

    well.. but the native function would be exposed publicly in a separate DLL? How can it be called directly?

    it's difficult to use WPF with C++/CLI, isn't it?



    • Edited by mathmax Friday, August 16, 2013 4:15 AM
    Friday, August 16, 2013 4:14 AM
  • "well.. but the native function would be exposed publicly in a separate DLL? How can it be called directly?"

    Well, it's difficult but it's not impossible. Basically once you find the native function one can try to modify the executable to export that function. Anyway, the main point here is that as soon as you mix native and managed code you make it easier for someone to figure out where are the native functions.

    "it's difficult to use WPF with C++/CLI, isn't it?"

    Yep, VS doesn't have a WPF project type for C++/CLI so XAML won't work, you're constrained to create the UI in code and that's certainly not the way to do things in XAML.

    Friday, August 16, 2013 4:52 AM
    Moderator
  • Maybe it's possible to mix C#, C++/CLI and C++ native in the same assembly. I found this :

    http://blogs.msdn.com/b/junfeng/archive/2006/05/20/599434.aspx

    How do you think?

    Friday, August 16, 2013 5:41 AM
  • Well, that works when compiling on the command line. Not sure how well it works in Visual Studio, AFAIR it doesn't have support for building modules from C# code.
    Friday, August 16, 2013 6:00 AM
    Moderator
  • Thank you

    Is it possible (easy?) to extract the modules of an assembly, then to recompose a new assembly with a a new module that would export the native function?

    Else, there is the possibility to compile in separate assemblies with Visual Studio and use ilmerge. But the same question applies.. is it possible to extract the original assemblies?


    • Edited by mathmax Friday, August 16, 2013 9:46 AM
    Friday, August 16, 2013 9:45 AM
  • "Is it possible (easy?) to extract the modules of an assembly"

    It may be possible but I don't know of any tool which does that.

    "Else, there is the possibility to compile in separate assemblies with Visual Studio and use ilmerge"

    You can try but AFAIK ilmerge doesn't deal with assemblies containing native code.

    Friday, August 16, 2013 11:11 AM
    Moderator
  • mmmm.. but I'm thinking about something: the unmanaged function has to be wrapped into a C++/CLI function in order to be used by C#. And even if the C++/CLI function is marked 'internal', it's always possible to call it from outside via reflection, isn't it?

    Friday, August 16, 2013 11:36 AM
  • Indeed, that's possible.
    Friday, August 16, 2013 1:11 PM
    Moderator