Monday 20 October 2014

.NET Obfuscation using Dotfuscator for Source Code Protection

Do you know that .NET Compiled code can be revert back to C# and VB.NET Source code. Yes it is possible by using decompiler we can get the original source code, then what about security. We can use .NET Obfuscation using dotfuscator for source code protection ...
image
All the lanugage compilers exists nowadays are producing the byte code or intermediate code that could be understandable to thier language interpreters. Microsoft .NET compiler converts the C# and VB.NET source code to MSIL (Microsoft Intermediate Languages). Java compiler converts the Java source code to byte code called class file and.
Now intersting part is there are lots of decompilers are available in market like Reflector for .NET, Dcafe for Java, hackers can get back the source code anytime from intermediate code using these decompilers. Now how we provide security for the source code. Here is the solution using ... Obfuscation  and Obfuscation Tools like Dotfuscator.
Overview
  1. Outline
  2. Define the problem
  3. Define Obfuscation
  4. Why Obfuscate?
  5. Layout Obfuscation
  6. How are we going to do it?
  7. Alternatives
  8. Conclusion
1. Outline and 2. Define the problem
Security is becoming increasingly important in the world of software. This session will discuss the various software security mechanisms focusing on applications built with .NET or Java. Topics covered include obfuscation and encryption. This session will also discuss common security vulnerabilities and provide tips and best practices to protect our code.
How.Net code is compiled ? image
image
3. Define Obfuscation
  • Obfuscate – “to confuse”
  • Behavior preserving transformations on code that preserve function but reduce readability or understandability
    •Hide what’s required, remove the rest
    •Confuse observers, but give Runtime Environment the same delivery
    •How do we confuse the reader?
4. Why Obfuscate? •IP should be protected
•Obfuscation provides important "trade secret" level protection
•Also, obfuscating may provide more legal options, since it indicates that the IP owner has taken measures to secure the IP
Code obfuscation
  • Obfuscating Arrays
image
  • Obfuscating Class
  • Obfuscating Variables
image 
Reverse engineering extracts piece of program
Obfuscation1
Obfuscation makes reverse engineering difficult
Obfuscation2 
5. Layout Obfuscation
Remove comments, identifiers
Scramble identifiers
Limited format changes
Method overloading
getPayroll() becomes a()
makeDeposit(float amount)becomes a(float a)
sendPayment(String dest) becomes a(String a)
How do we confuse the reader?
  • Control Flow Obfuscation
       - Rearranges control flow structures to make the application's logic harder to follow.
  • Removal of Unused Members
       - Removes members that are not used from the IL.
  • String Encryption
       - Encrypts strings so that they do not appear in plain text in the IL.
  • Data obfuscation
Control Flow Obfuscation
  • Change the flow of the program
  • Break the link between the original code and the obfuscated code
  • §Must ensure doesn’t introduce any bugs
  • For example, if or while statements can be transformed into other statements that are logically equivalent but more complex appearing by using the rules of logic. An obfuscator might also insert GoTo statements and labels to turn your neat logic into "spaghetti code" to further confuse human readers.
Removal of Unused Members An obfuscator can also evaluate your application's entire source code to determine whether there are any methods that are actually unused, and if so, remove them from the obfuscated assembly. This situation can easily arise if you've developed code with a code generator or used classes from a general-purpose utility library. For example: you might have collection classes with the full range of methods that any collection should support, but only use a small fraction of those methods in your application. An obfuscator can remove the unused code, making the remaining code harder to understand and shrinking the program as a beneficial side effect.
String Encryption String constants and literal strings in your .NET source code appear unchanged in your compiled .NET assemblies. Such strings can provide valuable clues for anyone trying to reverse-engineer your code. For example, an attacker trying to break a licensing routine would first focus attention on strings having to do with licensing to locate the appropriate section of code. Obfuscators can make this more difficult by encrypting the strings in the .NET assembly. This is accomplished by inserting a decryption routine into the assembly and calling the decryption code at runtime to return the original strings.
Data obfuscation
Storage obfuscation
    -Alters how data is stored in memory
     E.g. Making local variables to global and vice versa.
Aggregation obfuscation
    -Spliting an array into several array.
.NET Obfuscator Benefits: Protects and Improves .NET Code
  • Dotfuscator Professional obfuscator significantly enhances source code security.
. NET rich intermediate language is focused on application flexibility and inherently provides significant information on how an application was written. Because of this, .NET applications are more prone to reverse-engineering attack than most previous computer programs. Dotfuscator Pro includes state-of-the-art obfuscation technology to protect .NET applications - securing the important intellectual property contained within.
  • Dotfuscator Professional decreases the size of your .NET program.
Dotfuscator analyzes your application and figures out exactly which parts of your program you're really using (down to the method level!). From there it can parse out those pieces leaving you with the smallest executable possible.
  • Dotfuscator Professional improves run-time performance.
By removing unneeded program elements and renaming identifiers to small names, Dotfuscator .NET obfuscator can actually speed up programs.
  • Dotfuscator Professional provides tamper detection and notification.
Dotfuscator's Tamper Detection and Notification service notifies your organization when one of your applications detects tampering. Tampered applications cost millions in revenue to suppliers and introduce material security and liability risks to consumers.
  • Assembly Linking
Assembly linking, sometimes called merging, is the ability to merge multiple assemblies into one or more output assemblies. This can make an application even smaller and simplify deployment scenarios. When combined with obfuscation and pruning, assembly linking provides a powerful packaging solution for .NET applications.
6. How are we going to do it?

Obfuscators used in .NET

  • Salamander .NET Obfuscator
  • Spices .NET Obfuscator
  • DotFuscator

    Salamander .NET Obfuscator
§Remotesoft's Salamander .NET Obfuscator provides both a GUI environment (Remotesoft .NET Explorer) for exploring and obfuscating .NET applications.
Salamander .NET Obfuscator operates directly on your original binary exe and dll files, without altering debug and line number information. This makes source-level debugging easy; you can just drop the obfuscated assembly in place of the original, invoke the debugger, and go into your original source code
Overall, Salamander .NET Obfuscator appears to work well and the user interface makes a good deal of data on your assemblies readily accessible.
Dotfuscator - Introduction
Dotfuscator is an obfuscator, pruner, linker, and watermarker for .NET applications. It is a key component of a Secure .NET Software Development Life Cycle Process. It adds a new level of protection and application efficiency to any .NET application.
image

7. DotFuscator How to use dotfuscator
1. To open a DotFuscator you need to start up Visual Studio .Net.
Then you will be able to start up DotFuscator Community Edition.
2. All Visual Studio Programs → Microsoft 2005 → Visual Studio Tools → Dotfuscator Community Edition
image
3. Once the “Dotfuscator Community Edition” is clicked. The Dotfuscator application will startup.
image
4. Click on “input” tab and provide the dll/exe file that we have created as input.
image
5. Once the File (dll) has been taken as input, press Ctrl+B to Build the Project. You can use File → Build for the same. The result of the build can visible in output tab.
image
7. Alternatives for Legal protection
  • License agreements – EULA
  • Copyright
  • Patents
      –Dash-O example
  • DMCA and DeCSS
  • Lots of very nasty laws coming
      –Life imprisonment, P2P attacks
8. Conclusion

  • Protecting software is as important as protecting hosts
  • Watermarking, tamper-proofing and obfuscation are important tools for protecting software
  • However, no technique can prevent all attacks
  • Goal is to increase the cost for the attacker
  • Please Mail me if you need PPT version of this Article msdotnetsupport.blogspot@live.com

Wednesday 8 October 2014

Managing Your JavaScript Library in ASP.NET

Introduction

It is common for ASP.NET developers to adopt lax practices in their management of JavaScript. I believe this is because there is not a lot of reliable information online for how to properly deal with JavaScript in an ASP.NET application. The purpose of this article is to present an optimal technique to manage your JavaScript in your ASP.NET applications. The following issues will be addressed:
  • Inline JS - Page bloat caused by placing JavaScript directly in the page
  • Deploying JS - Forgetting to deploy JavaScript files
  • Bad References - Links to JavaScript not working when used in another web application
  • Dependencies - Needing to remember dependencies between JavaScript files
  • Unused JS - Referencing JavaScript on pages it is not used
  • HTTP / HTTPS - Referencing JavaScript over HTTP from an HTTPS page
  • Refactoring - Refactoring for a new version can take some time
  • Redundancy - Including a JavaScript file more than once

Prerequisites

Make sure you have Visual Studio 2010. Some concepts presented in this article may not work with the Express editions.

Overview

Most of the above problems are caused by placing JavaScript or references to JavaScript files directly in the ASPX page. The solution to almost all of the above problems is to use ASP.NET's built-in capability to embed JavaScript files into a DLL and then reference those files dynamically. This article will present those capabilities, as well as some techniques to take full advantage of them. A tutorial format will be used to explain how each step is done.

Getting Started

First things first. Start up Visual Studio 2010 and create a new empty web application called ParchmentPurveyor (we are making a website for somebody who wants to sell fancy paper):
New Empty Web Application (ParchmentPurveyor)
Now, add a new web form called "Default.aspx", and add some simple HTML to it. It should look something like this:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
    Inherits="ParchmentPurveyor.Default" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Parchment Purveyor</title>
</head>
<body>
    <form id="form1" runat="server">
        <h1>Parchment Purveyor</h1>
        <p>Paper for printers, painting, publication,
            paper planes, and plenty of other plebeian projects!</p>
    </form>
</body>
</html>

Adding JavaScript

Now that we have a fully functional website that is sure to get the attention of a plethora of people, we can focus on the JavaScript coding. Rather than add a JavaScript file to our main project, we will do things a little differently. We are going to create a new project to hold all of our JavaScript files. Start by adding a new class library project, calledJavaScriptLibrary, to the solution:
Add Class Library (JavaScriptLibrary)
When you added that project, a file called "Class1.cs" was added for you. We don't need that, so delete it. Add a folder to JavaScriptLibrary called "JavaScript". You will also add two JavaScript files to that folder. Call them "ShowMessage.js" and "GreetUser.js". Next, create a new class called JavaScriptHelper (do not place this in the "JavaScript" folder... it will go at the root level of the JavaScriptLibrary project). By now, your solution structure should look something like the following:
Solution Structure (2 Projects, 2 JS Files, 1 Code File, and 1 Webpage)
A couple of empty JavaScript files aren't going to do us any good, so let's put something in them. For starters, "ShowMessage.js" will hold a function called ShowMessage():
function ShowMessage(msg) {
    alert("Message From Website: " + msg);
}
The "GreetUser.js" file will have its own function, GreetUser():
function GreetUser() {
    ShowMessage("Greetings and Salutations!");
}
Notice that GreetUser() is dependent upon ShowMessage(). We will be handling that later.

Embedding the JavaScript Files

Rather than have to deploy our JavaScript files to our website, we'd like them to be embedded into the DLL. That way, if the DLL is deployed to the website, all JavaScript files are also automatically deployed. Doing this is very simple; all we need to do is go to the properties for each JavaScript file and change the "build action" from "content" to "embedded resource":
Set Build Action To Embedded Resource
While that will ensure the files get embedded into the DLL, you must still make them available to the web client. Before you do that, the JavaScriptLibrary project needs to reference System.Web:
Add Reference To System.Web
Once you have added that reference, edit "JavaScriptHelper.cs" by adding the following using statement and assembly attributes:
using System.Web.UI;

[assembly: WebResource("JavaScriptLibrary.JavaScript.ShowMessage.js",
 "application/x-javascript")]
[assembly: WebResource("JavaScriptLibrary.JavaScript.GreetUser.js",
 "application/x-javascript")]
That will enable your embedded JavaScript files to be accessible from the client computer.

Including the Embedded JavaScript Files

Now that you have embedded the JavaScript files and made them accessible via the client computer, you must actually reference them from the pages they are used on. To facilitate this, we will fill in our JavaScriptHelper class:
using System;
using System.Web.UI;

[assembly: WebResource("JavaScriptLibrary.JavaScript.ShowMessage.js",
 "application/x-javascript")]
[assembly: WebResource("JavaScriptLibrary.JavaScript.GreetUser.js",
 "application/x-javascript")]

namespace JavaScriptLibrary
{

    /// <summary>
    /// Helps include embedded JavaScript files in pages.
    /// </summary>
    public class JavaScriptHelper
    {
        #region Constants

        private const string NAME_SHOW_MESSAGE = 
   "JavaScriptLibrary.JavaScript.ShowMessage.js";
        private const string NAME_GREET_USER = 
   "JavaScriptLibrary.JavaScript.GreetUser.js";

        #endregion

        #region Public Methods

        /// <summary>
        /// Includes ShowMessage.js in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        public static void Include_ShowMessage(ClientScriptManager manager)
        {
            IncludeJavaScript(manager, NAME_SHOW_MESSAGE);
        }

        /// <summary>
        /// Includes GreetUser.js (and all dependencies) in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        public static void Include_GreetUser(ClientScriptManager manager)
        {
            // Dependency (ShowMessage.js).
            Include_ShowMessage(manager);

            // Include GreetUser.js.
            IncludeJavaScript(manager, NAME_GREET_USER);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Includes the specified embedded JavaScript file in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        /// <param name="resourceName">The name used to identify the 
        /// embedded JavaScript file.
        /// </param>
        private static void IncludeJavaScript
  (ClientScriptManager manager, string resourceName)
        {
            var type = typeof(JavaScriptLibrary.JavaScriptHelper);
            manager.RegisterClientScriptResource(type, resourceName);
        }

        #endregion
    }
}
The IncludeJavaScript() function is what does all the magic. It ensures a script tag gets inserted for an embedded JavaScript file, which it does by calling RegisterClientScriptResource()IncludeJavaScript() is called by Include_GreetUser(). Notice also that Include_GreetUser() calls Include_ShowMessage(), which means it handles dependencies for the user of the class. Any page that includes the GreetUser() function will also include the ShowMessage() function.
Now that we have that class available for our use, let's put it to use on the "Default.aspx" page. You can start by making sure ParchmentPurveyor has a reference to JavaScriptLibrary:
Add Reference To JavaScriptLibrary
Next, we'll need to modify the code behind to include the JavaScript on the page.
using System;
using System.Web.UI;

namespace ParchmentPurveyor
{
    public partial class Default : System.Web.UI.Page
    {
        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);
        }
    }
}
Finally, we just have one thing left to do -- call the GreetUser() function from the page. To do this, all we need to do is add the following JavaScript to the page (I chose to add it in the head tag):
<head runat="server">
    <title>Parchment Purveyor</title>
    <script type="text/javascript">
        window.onload = function () { GreetUser(); };
    </script>
</head>
That's it! You are done! Well, mostly. There are a few more niggling cases to handle. Before we get to those, however, let's look at the fruits of our labor:
It Works!
Here is what your HTML might look like when you view the source of the page (I shortened and removed some values):
<html xmlns="http://www.w3.org/1999/xhtml">
<head><title>
 Parchment Purveyor
</title>
    <script type="text/javascript">
        window.onload = function () { GreetUser(); };
    </script>
</head>
<body>
    <form method="post" action="Default.aspx" id="form1">
<div class="aspNetHidden">
<input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="..." />
</div>

<script src="/WebResource.axd?d=fslk3GLsk3Slek&amp;t=1234" type="text/javascript">
</script>
<script src="/WebResource.axd?d=fglk3kSl3LS5&amp;t=5678" type="text/javascript"></script>
        <h1>Parchment Purveyor</h1>
        <p>Paper for printers, painting, publication,
            paper planes, and plenty of other plebeian projects!</p>
    </form>
</body>
</html>
Notice there are two script tags that reference something called "WebResource.axd". That is basically a service which serves embedded information to the client. You can read more about "WebResource.axdhere. The important thing to note is that the first script tag is serving up the ShowMessage() function and the second script tag is serving up the GreetUser() function. Both of those script tags were included in the page when you called theInclude_GreetUser() function in your JavaScript library.

Late Includes

Sometimes, the above technique does not include the JavaScript file. For example, I work with a third-party tool that prevents me from calling .NET code before the render stage. When you call the include functions above during the render stage, the script tags do not get inserted into the page. This is because the beginning of the page has already been rendered to HTML. My solution to this problem is to create an alternate form of the function that inserts thescript tag near the bottom of the HTML. I call this a "late include". We can support this technique with a few changes to JavaScriptHelper:
using System;
using System.Web;
using System.Web.UI;

[assembly: WebResource("JavaScriptLibrary.JavaScript.ShowMessage.js",
 "application/x-javascript")]
[assembly: WebResource("JavaScriptLibrary.JavaScript.GreetUser.js",
 "application/x-javascript")]

namespace JavaScriptLibrary
{
    /// <summary>
    /// Helps include embedded JavaScript files in pages.
    /// </summary>
    public class JavaScriptHelper
    {

        #region Constants

        private const string TEMPLATE_SCRIPT = 
   "<script type=\"text/javascript\" src=\"{0}\">
     </script>\r\n";
        private const string NAME_SHOW_MESSAGE = 
   "JavaScriptLibrary.JavaScript.ShowMessage.js";
        private const string NAME_GREET_USER = 
   "JavaScriptLibrary.JavaScript.GreetUser.js";

        #endregion

        #region Public Methods

        /// <summary>
        /// Includes ShowMessage.js in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        /// <param name="late">Include the JavaScript at the bottom of the HTML?</param>
        public static void Include_ShowMessage
  (ClientScriptManager manager, bool late = false)
        {
            IncludeJavaScript(manager, NAME_SHOW_MESSAGE, late);
        }

        /// <summary>
        /// Includes GreetUser.js (and all dependencies) in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        /// <param name="late">Include the JavaScript at the bottom of the HTML?</param>
        public static void Include_GreetUser
  (ClientScriptManager manager, bool late = false)
        {
            // Dependency (ShowMessage.js).
            Include_ShowMessage(manager, late);

            // Include GreetUser.js.
            IncludeJavaScript(manager, NAME_GREET_USER, late);
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// Includes the specified embedded JavaScript file in the page.
        /// </summary>
        /// <param name="manager">Accessible via Page.ClientScript.</param>
        /// <param name="resourceName">The name used to identify the 
        /// embedded JavaScript file.
        /// </param>
        /// <param name="late">Include the JavaScript at the bottom of the HTML?</param>
        private static void IncludeJavaScript(ClientScriptManager manager,
   string resourceName, bool late)
        {
            var type = typeof(JavaScriptLibrary.JavaScriptHelper);
            if (!manager.IsStartupScriptRegistered(type, resourceName))
            {
                if (late)
                {
                    var url = manager.GetWebResourceUrl(type, resourceName);
                    var scriptBlock = string.Format
    (TEMPLATE_SCRIPT, HttpUtility.HtmlEncode(url));
                    manager.RegisterStartupScript(type, resourceName, scriptBlock);
                }
                else
                {
                    manager.RegisterClientScriptResource(type, resourceName);
                    manager.RegisterStartupScript(type, resourceName, string.Empty);
                }
            }
        }

        #endregion
    }
}
I modified each method to accept an additional parameter, late. This defaults to false, so the methods can still be called the same way they used to be. A value of false will preserve the old behavior. A value of true will cause thescript blocks to be included near the end of the HTML. Note also that in the case that late is false, I still callRegisterStartupScript(), but I pass it an empty string (so that function call does not actually insert anything into the HTML). This is done so IsStartupScriptRegistered() will return the correct value. That way, the JavaScript will never be included more than once, even if one of the functions is called with late set to false and then again with late set to true. If you want to see this in action, comment out the OnPreRender() in the code behind and modify the body of the page to look like this:
<body>
    <form id="form1" runat="server">
        <h1>Parchment Purveyor</h1>
        <p>Paper for printers, painting, publication,
            paper planes, and plenty of other plebeian projects!</p>
        <%  // This gets called during the render stage.
            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser
   (Page.ClientScript, true); %>
    </form>
</body>
That will call the version of the function that includes the script tags near the bottom of the HTML, which you can observe by viewing the source of the page when you run the application.

External JavaScript

So far, I've only demonstrated how to include embedded JavaScript. However, it is sometimes desirable to link to an external JavaScript file. To facilitate this, we need to add a new helper function in JavaScriptHelper:
/// <summary>
/// Includes the specified external JavaScript file in the page.
/// </summary>
/// <param name="page">The current page.</param>
/// <param name="key">The name used to uniquely identify the external JavaScript file.
/// </param>
/// <param name="httpUrl">The URL of the external JavaScript file.</param>
/// <param name="httpsUrl">The URL of the external JavaScript file when SSL is enabled.
/// </param>
/// <param name="late">Include the JavaScript at the bottom of the HTML?</param>
private static void IncludeExternalJavaScript
 (Page page, string key, string httpUrl, string httpsUrl, bool late)
{
    var manager = page.ClientScript;
    var type = typeof(JavaScriptLibrary.JavaScriptHelper);
    bool isStartupRegistered = manager.IsStartupScriptRegistered(type, key);
    bool isScriptRegistered = manager.IsClientScriptIncludeRegistered(type, key);
    if (!(isStartupRegistered || isScriptRegistered))
    {
        string url;
        if (page.Request.Url.Scheme.ToLower() == "http")
        {
            url = httpUrl;
        }
        else
        {
            url = httpsUrl;
        }
        if (late)
        {
            manager.RegisterStartupScript(type, key,
  string.Format(TEMPLATE_SCRIPT, HttpUtility.HtmlEncode(url)));
        }
        else
        {
            manager.RegisterClientScriptInclude(type, key, url);
        }
    }
}
As an example of an external file you might include, I'll use the jQuery file hosted by Microsoft's CDN. Just like the other JavaScript files, you will create a function in JavaScriptHelper to include jQuery on the page:
private const string NAME_JQUERY = "jQuery";
private const string URL_JQUERY = "http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js";
private const string URL_JQUERY_HTTPS =
 "https://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js";

/// <summary>
/// Includes jQuery.js in the page.
/// </summary>
/// <param name="page">The current page. Pass in null to get
/// the current page from the HTTP context.</param>
/// <param name="late">Include the JavaScript at the bottom of the HTML?</param>
public static void Include_jQuery(Page page, bool late = false)
{
    if (page == null)
    {
        page = (Page)HttpContext.Current.Handler;
    }
    IncludeExternalJavaScript(page, NAME_JQUERY, URL_JQUERY, URL_JQUERY_HTTPS, late);
}
Finally, you can include jQuery on your page by calling your function from the OnPreRender() function in your page:
protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    JavaScriptLibrary.JavaScriptHelper.Include_jQuery(Page);
    JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);
}
If you run your application and view the source of the page, you'll see that jQuery gets included:
<script src=http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js 
type="text/javascript"></script>

Adding New JavaScript Files

Once you have everything setup, there are only a few steps you need to complete when adding new JavaScript files:
  • Add the ".js" file to the "JavaScript" folder. Skip this step for external JavaScript files.
  • Set the "build action" to "embedded resource". Skip this step for external JavaScript files.
  • Add the assembly attribute to indicate the JavaScript file is a web resource. Skip this step for external JavaScript files.
  • Create a function in JavaScriptHelper to include your JavaScript file.
  • Call the function you just created from a page, control, or masterpage.

Excluding JavaScript Files

While you should have everything you need to include JavaScript, you must sometimes exclude JavaScript. For example, when working with third-party control libraries that may have exotic ways of including JavaScript, the only way to prevent a certain JavaScript file from being included twice may be to have your code avoid including it (and let the third-party library include the JavaScript for you). This can be accomplished with one more helper function. Before we get to that, however, let's demonstrate a scenario where this technique will come in handy. Say your third-party control includes jQuery. This user control, "InlineGreeting.ascx", will serve as just such a control:
<%@ Control Language="C#" %>

<%-- This is a bad way to do things, but we can luckily overcome this obstacle. --%>
<script type="text/javascript" 
 src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.5.1.js">
</script>
<script type="text/javascript">
    $(document).ready(function() {
        $("#lblGreeting").text("Hello");
    });
</script>
<p>
    <label id="lblGreeting"></label>
</p>
Now suppose we have another control, "Hello.ascx", that uses that same jQuery file:
<%@ Control Language="C#" AutoEventWireup="true"
 CodeBehind="Hello.ascx.cs" Inherits="ParchmentPurveyor.Hello" %>

<script type="text/javascript">
    $(document).ready(GreetUser);
</script>
The code behind for "Hello.ascx" will include jQuery, as well as our JavaScript to greet the user:
protected override void OnPreRender(EventArgs e)
{
    base.OnPreRender(e);
    JavaScriptLibrary.JavaScriptHelper.Include_GreetUser(Page.ClientScript);
    JavaScriptLibrary.JavaScriptHelper.Include_jQuery(Page);
}
Now, if we were to include both of our user controls on the "Default.aspx" page, jQuery would get included twice (once by the third-party control and once by our JavaScript library). In order to avoid that, we will add two functions,ExcludeJavaScript() and Exclude_jQuery(), to our JavaScriptHelper class:
private const string NAME_DUMMY_FILE = "JavaScriptLibrary.JavaScript.DummyFile.js";

/// <summary>
/// Excludes jQuery.js from the page.
/// </summary>
/// <param name="manager">Accessible via Page.ClientScript.</param>
public static void Exclude_jQuery(ClientScriptManager manager)
{
    ExcludeJavaScript(manager, NAME_JQUERY);
}

/// <summary>
/// Registers a dummy script to prevent the inclusion of the real JavaScript.
/// </summary>
/// <param name="manager">Accessible via Page.ClientScript.</param>
/// <param name="key">The name used to uniquely identify the JavaScript file.</param>
private static void ExcludeJavaScript(ClientScriptManager manager, string key)
{
    var type = typeof(JavaScriptLibrary.JavaScriptHelper);
    var url = manager.GetWebResourceUrl(type, NAME_DUMMY_FILE);
    manager.RegisterStartupScript(type, key, string.Empty);
    manager.RegisterClientScriptInclude(type, key, url);
}
Notice we have defined a new constant, NAME_DUMMY_FILE. The above functions assume we have added an empty JavaScript file to our "JavaScript" folder and embedded it according to the above instructions. This empty dummy JavaScript file will be included in place of any JavaScript files we want to be excluded. All we need to do in order to prevent our library from including jQuery is to call Exclude_jQuery() from the Page_Load() of "Default.aspx":
// Page load occurs before pre-render (the ideal place to exclude JavaScript).
protected void Page_Load(object sender, EventArgs e)
{
    // We have some third-party control that includes jQuery in a weird way,
    // so we will avoid including it again.
    JavaScriptLibrary.JavaScriptHelper.Exclude_jQuery(Page.ClientScript);
}
Now all we need to do is modify "Default.aspx" to include "InlineHello.ascx" and "Hello.ascx" and we are done:
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs"
    Inherits="ParchmentPurveyor.Default" %>
<%@ Register Src="~/Hello.ascx" TagPrefix="greet" TagName="Hello" %>
<%@ Register Src="~/InlineGreeting.ascx" TagPrefix="greet" TagName="InlineHello" %>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Parchment Purveyor</title>
    <script type="text/javascript">
        // We are commenting this out while we use the jQuery version.
        // window.onload = function () { GreetUser(); };
    </script>
</head>
<body>
    <form id="form1" runat="server">
        <h1>Parchment Purveyor</h1>
        <p>Paper for printers, painting, publication,
            paper planes, and plenty of other plebeian projects!</p>
        <%  // This gets called during the render stage.
            JavaScriptLibrary.JavaScriptHelper.Include_GreetUser
    (Page.ClientScript, true); %>
        <%-- An inline greeting (pretend this comes from a 
    third-party control library. --%>
        <greet:InlineHello runat="server" />
        <%-- Our jQuery greeting. --%>
        <greet:Hello runat="server" />
    </form>
</body>
</html>
Now that we have made sure to call Exclude_jQuery() before Include_jQuery(), we have prevented our JavaScript library from including "jQuery.js". That way, jQuery is only included once by our mock third-party control. Most of the time, this situation should be avoidable. However, for when it is not avoidable, this technique should tidy up our HTML output nicely.

A Note For VB.NET Users

When making the VB.NET version of the code, most everything was the same as the C# version, aside from syntax differences. However, there was one important gotcha you should keep in mind. In the C# version of the code, you'll note that all the paths to the JavaScript files start with "JavaScriptLibrary.JavaScript.". However, in the VB.NET version of the code, all the paths start with only "JavaScriptLibrary." (i.e., VB.NET seems to ignore the "JavaScript" folder all of the JavaScript files are in). That requires VB.NET users to make just a few changes:
<Assembly: WebResource("JavaScriptLibrary.ShowMessage.js", "application/x-javascript")>
<Assembly: WebResource("JavaScriptLibrary.GreetUser.js", "application/x-javascript")>
<Assembly: WebResource("JavaScriptLibrary.DummyFile.js", "application/x-javascript")>

Private Const NAME_SHOW_MESSAGE As String = "JavaScriptLibrary.ShowMessage.js"
Private Const NAME_GREET_USER As String = "JavaScriptLibrary.GreetUser.js"
Private Const NAME_DUMMY_FILE As String = "JavaScriptLibrary.DummyFile.js"
Aside from that, I found no other differences when making this code work in VB.NET. If you would like to try it yourself, the VB.NET version of the code can be downloaded using the link at the top of the article.

What Did You Gain?

After all this work with the same apparent HTML output, you might be asking yourself, "what did I really gain by adding all this extra code?" Well, here are a few solutions presented by this approach:
  • Inline JS - You have reduced page bloat by avoiding putting your JavaScript library inline in the page.
  • Deploying JS - You do not need to include the ".js" files when you deploy your web application. Deploying the DLL will be enough.
  • Bad References - Even if you change the path of your application, you will not have to worry about changing your JavaScript paths.
  • Dependencies - Dependencies are managed automatically. If you included "GreetUser.js", "ShowMessage.js" will automatically be included.
  • Unused JS - No JavaScript is included on the page unless you call the function to include it. This will avoid having unused JavaScript on the page (potentially speeding up load times for users).
  • HTTP / HTTPS - The code outputs script tags that do not include the protocol, so the protocol should be the same as the current page (i.e., HTTP or HTTPS).
  • Refactoring - If you want to use a different version of a script, you only need to modify it in one place. This could be useful, for example, if you decide to switch to a CDN version of jQuery rather than hosting it yourself. It could also be useful for upgrading to a new version of jQuery.
  • Redundancy - No matter how many times you call one of the include functions, the script tags will only be included on the page once.