Curious said:
I never intended to provide my .dll to anyone. But I'm put in this
client-server type of environment where I am a client. Although
my .dll file is on my location machine, when I run it against a server
that belongs to another company and located remotely in their office,
I believe that they are able to see my .dll.
In that case, you need to either trust them with the code (because you
think they're not an adversary; because its not in their interest to
attack you; because you'll go to court and win lots of money; because
they're not clever enough to reverse engineer your code, etc...) or
don't give them the code.
One more question for you gurus: Do you believe that they can get
my .dll file when I run it against their server database ? Could
anyone explain how can they get my .dll through the server?
If you're just connecting to their database server, they shouldn't be
able to see your code.
What do you mean by saying this? Please explain.
It's trivial to reverse engineer any realistic class. Lets take
something kind-of-like System.Drawing.Color as an example (simply
because it's self-contained).
This is 'obfuscated' code I've written manually and does not represent
any particular product:
namespace System.Drawing
{
public struct Color
{
public byte R{get;private set;}
public byte G{get;private set;}
public byte B{get;private set;}
public static Color Black = FromArgb(0,0,0);
public static Color White = FromArgb(0,0,0);
public static Color FromArgb(int a, int b, int c)
{
A(a, "red");
A(b, "green");
A(c, "blue");
return new Color(){R = a, G = b, B = c};
}
private static void A(int a, string b)
{
if(a < 0 || a > 255)
{
throw new ArgumentException(b + " value is out of range");
}
}
}
}
I've removed all non-public names, and thrown away as much information
as I can while still maintaining the same interface. It's still easy to
understand.
There are a few more silly tricks. For example, we could make 3
functions that evaluate to "red", "green" and "blue" so we don't have to
put those literals in the code, but anybody with a debugger is just
going to put a watch on the result of those functions and see what the
result is. Another silly trick is to change all variables to have the
same or similar names (because this is supposedly harder to read - you
can write a tool to parse the code and change them back to a,b,c,... in
less than 2 minutes with Mono Cecil).
And for this 'security', you've lost the information from your stack
trace so it's not clear (if an exception were thrown) that the exception
happened in the CheckByte function (called A here). You've also probably
added some extra bugs from the obfuscation layer. Reflection doesn't
always work any more either, because you might have thrown away the name
of what you're looking for.
Alun Harford