Detecting native .NET types

  • Thread starter Thread starter John W.
  • Start date Start date
J

John W.

Hi there,

Does anyone know if there's a (simple) way to detect whether an arbitrary
"System.Type" originates from the .NET framework opposed to a user-defined
assembly. Thanks.
 
Thanks for the feedback ...
Define ".NET Framework". Do you mean just the CLR? Or do you mean to
include any assembly provided by Microsoft as part of .NET?

Yes, the CLR - anything that's installed with the framework installer.
I don't know if there's a canonical mechanism for identifying types as
.NET or not

You're probably right. I was hoping there might be a way ...

, but it shouldn't be too hard to track down the names of all
the assemblies you consider to be part of .NET, and then look at the
System.Type.Assembly property to see if the type in question comes from
one of those assemblies.

I was also hoping to avoid this route if possible. My app will be processing
arbitrary types on 2.0 or later and I need to distinguish between
user-defined types and native .NET types. I didn't want to have to track
down all assemblies in 2.0 and 3.X. It would be cleaner if there was a way
to dynamically determine things on-the-fly.
 
All due respect, that's an inconsistent answer. The CLR is just the
run-time (mscorlib.dll). The .NET Framework includes more than that.
Different parts of .NET are found in different assemblies.

My mistake then. It was my understanding that the CLR consisted of all
assemblies installed with the framework (not just "mscrolib.dll")
I'm curious as to why, if you don't mind sharing. It seems to me to be a
somewhat arbitrary requirement, since the types would otherwise behave
exactly the same. What is it about .NET types versus third-party types
that makes them so different that you need to track them independently?

Unfortunately I can't get specific right now.What I can say is that I'm
working on a tool that will be processing Visual Studio solutions. As a
result, I'm processing a lot of arbitrary types originating from source code
itself. I therefore have a (legitimate) need to distinguish between native
..NET types and types created by the solution's developers (including
3rd-party types).
I don't know. Maybe someone else will have better advice as to how to
identify all of the types that come from .NET, or alternatively how to
automatically determine a complete list of the assemblies that make up
.NET (I figure that would be a reasonable alternative). But on the face
of it, if it were me, I'd be working to redefine the problem so that it's
easier. :)

The problem can't be "redfined" unfortunately. It's a very specific and
unique requirement which would become clear if I could say more about it.
Note that the object browser in VS itself allows you to browse the ".NET
Framework" assemblies so I'd be interesed in knowing how they're doing it.
It's too bad that "System.Type" itself doesn't provide some property or
method similar to "IsPrimitive" for instance. I can see an "IsNative" or
"IsFramework" property for example.
 
John said:
Unfortunately I can't get specific right now.What I can say is that I'm
working on a tool that will be processing Visual Studio solutions. As a
result, I'm processing a lot of arbitrary types originating from source code
itself. I therefore have a (legitimate) need to distinguish between native
.NET types and types created by the solution's developers (including
3rd-party types).
The problem can't be "redfined" unfortunately. It's a very specific and
unique requirement which would become clear if I could say more about it.
Note that the object browser in VS itself allows you to browse the ".NET
Framework" assemblies so I'd be interesed in knowing how they're doing it.
It's too bad that "System.Type" itself doesn't provide some property or
method similar to "IsPrimitive" for instance. I can see an "IsNative" or
"IsFramework" property for example.

I don't think you can find a perfect solution.

But here are 2 things that may give a good indication:

If t.FullName starts with System or Microsoft then
it is probably .NET !

If t.Assembly.Location starts with C:\Windows then
it is probably .NET !

Arne
 
I don't think you can find a perfect solution.
But here are 2 things that may give a good indication:

If t.FullName starts with System or Microsoft then
it is probably .NET !

If t.Assembly.Location starts with C:\Windows then
it is probably .NET !

Thanks for the suggestion. I don't think it will fly unfortunately. It's too
imprecise and therefore subject to failure (anyone can apply "System" or any
other namespace to their type and nothing's stopping them from installing a
3rd-party assembly in the system folder - rare as this might be).
 
John said:
Thanks for the suggestion. I don't think it will fly unfortunately. It's too
imprecise and therefore subject to failure (anyone can apply "System" or any
other namespace to their type and nothing's stopping them from installing a
3rd-party assembly in the system folder - rare as this might be).

If you want to protect against someone deliberately trying to
trick you, then:
1) you need to have a positive list with assembly names and
cryptographic strong checksums
2) have you considered if people can decompile your app, remove
the check and recompile ?

Arne
 
Thanks for the suggestion. I don't think it will fly unfortunately. It's
Well, I think the latter is actually more likely. It seems like a
legitimate installation behavior for certain kinds of software.

But the former seems very unlikely except in the case of willful
impersonation. And if you're concerned about that, then there's not
really anything you can do to avoid someone bypassing your check.

The real issue to me is that both techniques are hacks. While the namespace
suggestion would probably work in practice, it's cleaner and safer to rely
on "legitimate" techniques. I do appreciate his suggestions however :)
Unfortunately, your unwillingness to describe the problem further makes it
difficult to offer suggestions.

I can't for reasons beyond my control.
If this is a tool to aid the user, I think that there are things like
what Arne suggests as well as just looking at what the input to the tool
is (i.e. types that are part of assemblies the user doesn't specifically
provide to the tool are inferred to be .NET types).

There's more to the story which is why I can't just use a "process of
elimination" technique. All I really need is a clean way to make the
determination given the "System.Type" itself (or even its assembly-qualified
name).
If you're looking for some sort of secure analysis of the code, then I
think the best you can do is build your own "white list" of .NET
assemblies and base the analysis on that. And even in that case, someone
who wants to would be able to hack your tool in order to get it to
produce whatever results _they_ want rather than the results you wanted.

I'm not going to worry about hackers. That's always an issue but my code is
already reasonably secure (very painful to hack anyway).
 
I don't think you can find a perfect solution.
If you want to protect against someone deliberately trying to
trick you, then:
1) you need to have a positive list with assembly names and
cryptographic strong checksums

It's not about someone trying to deceive my app, it's about programmers who
might actually use the namespace "System" or install their app in the system
folder. Foolish as it might be (the former in particular), I know from long
experience that it's safer to rely on "official" techniques. I do appreciate
your help however :)
2) have you considered if people can decompile your app, remove
the check and recompile ?

Yes but it would be difficult given the security I've implemented. It's not
really a serious concern however. Any program is subject to this and it's
beyond my control. Again, it's not about trickery anyway (as per above).
 
how about checking the public key token?

it's not foolproof, but assembly.GetName().GetPublicKeyToken() will be a
byte array : b77a5c561934e089 for Microsoft signed assemblies.

I don't think there is a foolproof method for all the reasons everyone else
has given. I suspect the best answer is as already given - to just grit your
teeth and write up a big list of all the assemblies you need to identify,
and consider some other heuristics to make a good guess as to the origin of
the assembly in question.

you could check the copyright and company too...eg

object[] atts =
assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
if (atts != null && atts.Length == 1)
{
if(false == String.Equals(
((AssemblyProductAttribute)atts[0]).Product,
"Microsoft® .NET Framework"))
{
return false;
}
}
// passed product attribute test...


and the AssemblyCompanyAttribute.Company will be Microsoft Corporation.

Now I suspect all of this could be bluffed somehow, but somebody would have
to be seriously trying hard to mess with your product to achieve it - this
won't happen by accident - it depends how big a deal it is if you get a
false positive because somebody's trying to hack your software.

L
 
How about doing like Redgate's ANTS profiler?
Simply prompt the user for a filter to decide about the unprocessed
assemblies...
 
how about checking the public key token?
it's not foolproof, but assembly.GetName().GetPublicKeyToken() will be a
byte array : b77a5c561934e089 for Microsoft signed assemblies.

Yes, I already considered that before posting but didn't think it was
bulletproof.
I don't think there is a foolproof method for all the reasons everyone
else has given. I suspect the best answer is as already given - to just
grit your teeth and write up a big list of all the assemblies you need to
identify, and consider some other heuristics to make a good guess as to
the origin of the assembly in question.

You're probably right (as are the others). It looks like I'll be pursuing
this.
you could check the copyright and company too...eg

object[] atts =
assembly.GetCustomAttributes(typeof(AssemblyProductAttribute), false);
if (atts != null && atts.Length == 1)
{
if(false == String.Equals(
((AssemblyProductAttribute)atts[0]).Product,
"Microsoft® .NET Framework"))
{
return false;
}
}
// passed product attribute test...


and the AssemblyCompanyAttribute.Company will be Microsoft Corporation.

I also considered this as well and even looked at some of the other
available attributes. It's still hacky but since there's no official way I
can find so far (other than enumerating the list ahead of time) it's worth
considering (along with the other ideas). Of course I don't know if this
will be affected by culture in anyway.
Now I suspect all of this could be bluffed somehow, but somebody would
have to be seriously trying hard to mess with your product to achieve it -
this won't happen by accident - it depends how big a deal it is if you get
a false positive because somebody's trying to hack your software.

Again, I'm not concerned about this. I've taken adequate security
precautions but this is a ubiquitous problem that all software is subject
to. In any case, thanks for the feedback (appreciated).
 
You're making this too hard. Simply install the framework and then take a
look at the DLLs installed. If it's not from one of those DLLs it's not a
"native" class. You will need to do this for every version of the
framework that you want to target.

Agreed that appears to be the only viable solution. A dynamic check would
have been better but I'll likely be pursuing this instead. Note that I put
in a request to MSFT to add a "Type.IsFramework" property for a future
release, similar to the existing "Type.IsPrimitive". It will be very
low-priority no doubt and I don't expect to see it in any case (very few
likely need this) but you never know. Anyway, thanks for your input.
 
Back
Top