Reveal hidden API usage tricks from any .NET application

Normal

0

21

false

false

false

FR

X-NONE

X-NONE

Share/Bookmark

How many times did you use a .NET application and ended-up wondering:
how the heck did they implement that particular feature? I would like to
present here a way to reveal some of the best kept secrets of a .NET code base.

 

Let’s take a concrete example. Suppose that you noticed that in the
NDepend
UI, the search dialog comes with a
convenient eyes candy: when searching
for the name of a code element by patterns, the pattern(s) are highlighted in
the result. In the screenshot below we are searching for .NET framework types
where the name contains both patterns Form
and Dia (case insensitive). Btw,
notice how a CQL query
is generated with 2 CQL clauses
NameLike “regex”. This is the kind of featurettes that makes me happy
[:)]:

 

 

Now suppose that in your application you also have the need to measure
the width of a string. After a few seconds googling, you’ll find out the MeasureString(…) methods implemented in
the 2.NET Framework classes System.Drawing.Graphics 
and System.Windows.Forms.TextRenderer. Let’s prototype a bit and then … disappointment:
All these MeasureString(…) methods are not accurate at all (I learnt
afterthought in this
article that this lack of accuracy
came from GDI+ problem with font-anti aliasing).

 

But still you know that it is possible since the NDepend UI comes with
accurate string width measurement. Here, you’ll certainly end up digging deeper
into web search … or … you can use the following trick.

 

 

The idea is to compare your application code with the NDepend code. This
sounds absurd, there is nothing to compare right? Actually, the trick is that we focus the
comparison on the API usage.

 

First let’s compare your assemblies with the NDepend assemblies:

 

Second, go to the search panel and ask for tier methods used recently. Tier methods are methods from tier assemblies (like the .NET Framework assemblies) that are used by an application. Normally, used recently means that one is asking
for tier methods that were not used by the older version of the code and that are
now used. We are in fact hi-jacking
this feature to ask for .NET framework methods used by NDepend and not used by
your application. Let’s focus the search on the System.Drawing.dll assembly since the astute used by NDepend
implementation certainly resides there. Here are the methods not used by the
application but used by NDepend. Let’s notice the CharacterRange structure
and the Graphics.MeasureCharacterRanges(…) method :

 

 

Typing MeasureCharacterRanges
CharacterRange
in google will immediately point you to this CodeProject
article
that will explain you how to use
this API to have accurate string width measurement. Of course, you could have
found this article directly by Googling but here, the cool thing is that this
way, you directly target the exact accuracy you need. If it works for a lambda
application I don’t need prototyping, it’ll work for my application too. And also
try that: typing string width
measurement
in google only points to MeasureString()
inaccurate implementations!

 

 

API used only by your application

The same trick can be used to know types used only by your application. You just need
to use the option not used anymore
instead of the option used recently.

 

Win32 P/Invoked API

In the same vein, you might want to spy which
win32 API is used by an application (through P/Invoke). Here you just ask for methods tagged with
the DllImport attribute
.

 

Legal issue

I found this trick particularly powerful. It
works even if the code of the application has been obfuscated (and actually,
the NDepend code is obfuscated!).

 

Most commercial application End User License
Agreement (EULA) specifies that the
application shouldn’t be decompiled by the end-user to preserve intellectual
property. Ironically, the NDepend EULA
specifies this point clearly:

 

If the licensed right of use for this SOFTWARE
PRODUCT(S) is purchased by you with any intent to reverse engineer, decompile,
create derivative works, and the exploitation or unauthorized transfer of (…)Any
sale or resale of intellectual property or created derivatives so obtained will
be prosecuted to the fullest extent of all local, federal and international
law.

 

In this post I don’t provide a good moral example. I wanted to present a
relevant/real-world illustration with something that our team learnt the hard
way.

 

Anyway, respect the EULA of other applications as you would like your
own EULA being respected and use this trick only on applications you can legaly decompile and re-engineer.

Share/Bookmark

This entry was posted in API usage, CQL, CQL query, decompilation, decompile, Pattern, re-engineering. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://www.opac.ch/people/arnaud/ Pierre Arnaud

    Following your link, I was pleasantly surprised to reach my article on Code Project (Bypass MeasureString limitations). I must admit that I no longer use GDI+. It was too painful, inefficient and buggy. I finally settled on the AntiGrain library for my own projects, the most visible one being Creative Docs .NET (http://www.creativedocs.net). And since I paint my character glyphs myself (OpenType font glyph decoding done in a mix of managed C# code and native C++), I can fix my own bugs when they arise ;-)

  • Marcel

    Actually, MSDN does mention the MeasureCharacterRanges method on the MeasureString reference page. But I doubt if I would have explored it further…
    Nice find!