Geeks With Blogs
.NET Corner Jeans, .NET and Physics (eka The Quantum Boy)

Remember the awesome AI RoboForm. Its the smartest of all web form fillers exist on earth. In case you haven't used it you can found it here. From password memorization (I'm extremely shaky about trusting any third party software expecially those deals with password, CCs etc.), to secure transfer of user data profile to removable devices by Pass2Go RoboForm has it all. Although its seems easy until I myself went on creating some proof of concept equivalent to this.
To achieve anything closer to this I need to create something called plugin. You must be saying a - 2yr-old kid also know about plugins. What's your point? To be exact I need to create something called BHOs or browser helper objects. These are some browser specific extensibility modules for doing things that the core browser engine not supposed to do. But this same thing can open up a whole new dimension to virus writers and hackers. You know its easy to sit into the lap of Internet Explorer and watch your credit card number and CCV passing by. At certain point of time(most probably around 5.5 release) Microsoft stopped the support for writing IE plugins but the model came back in the name of BHOs. As a part of SP2 patchset of XP, a BHO control manager option has been added to IE. My BHO has to be listed there in order to justify itself as a BHO!


The first thing you should do to write a BHO in managed language is to recreate the C++/COM interface signature of IObjectWithSite in C#.

[ComVisible(true),
 InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
 Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352") ]
 public interface IObjectWithSite
 {
  [PreserveSig]
  int SetSite ([MarshalAs(UnmanagedType.IUnknown)]object site);
  
  [PreserveSig]
  int GetSite (ref Guid guid, out IntPtr ppvSite);
 }

 Now I'm going to implement this interface. To supply the GUID for this class I called up guidgen.exe which could easily be accessed from Tools >> Create GUID


My class implementing the IObjectWithSite interface is following. Now as the same GUID has to be registered with windows registry I made the declaration of it as const string(just like static but accessible from attribute)

[ComVisible(true),
 ClassInterface(ClassInterfaceType.None),
 Guid(SiteWatcherBHO.BHO_GUID)]
 public class SiteWatcherBHO : IObjectWithSite
 {
     public const string BHO_GUID = "FFF9DE52-E5A5-4217-B938-DFF5EA95B4CD"; // << Your GUID goes here    

     //SetSite(), GetSite() impl...
 }

Before implementing meat of our BHO lets set the framework of its registration. While registering the BHO we have to create a subkey at
SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\ with name same as of the generated GUID tagged around the class implementing IObjectWithSite. To simplify the registering process of COM modules(BHOs fall into this category) written as a .NET module Microsoft has provided an utility called RegAsm. One of the interesting switches associated with RegAsm is /codebase. Upon providing this with the commandline, RegAsm automatically searches for a public static method in the assembly which is tagged with the ComRegisterFunction attribute. The benefit is tremendous. You can do any kind of registration work inside the function. As some COM modules require the creation of some special key at some special location this technique proves to be very useful. But if required you can go online, update your online database, call webservice ..anything inside this special method and the fun part is that all this is being done under the cosy corner of .NET. But to be good citizen and play fair you shold pair up your registration function and should provide a static method tagged with ComUnregisterFunction attribute. Reason is simple when your uninstaller calls to unregister the module, depending upon your scenario you should partially or totally undo what you have done in the registration function.

public class SiteWatcherBHO : IObjectWithSite
   {
      [ComRegisterFunction]
      internal static void RegisterFunction(Type typeToRegister) {}

      [ComUnregisterFunction]
      internal static void UnregisterFunction(Type typeToRegister) {}
   }

Below I will show the code I used in my BHO class

[ComRegisterFunction]
  public static void RegisterBHO(Type t)
  {
   try
   {
    Microsoft.Win32.Registry.LocalMachine.CreateSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Browser Helper Objects\{" + SiteWatcherBHO.BHO_GUID + "}");
   }
   catch(Exception e)
   {
#ifdef DEBUG

    System.Windows.Forms.MessageBox.Show(e.ToString());
#endif
   }
  }

See the const declaration of the GUID comes handy here. Another important point is the presence of preprocessor directives. Now in the production release of my CCNumberCollector BHO I'm not supposed to show any messages. Not even a log. Just devour the entire exception like what has been shown here. "Leave no trace" is The mottow for all "underground" guys. Now GetSite() and SetSite() both will be called during the creation and termination of the object we are implementing here(means our BHO object) but each time with a different argument for the site parameter. For SetSite() the site will be non-null while creation and null while termination. Now lets fix the job of our BHO. In this sample BHO I will fillup the username and password of my yahoo mail account and auto-login into it. Saying this I need an appropriate place to do all the fillup stuff. DocumentComplete event is an ideal for such scenario. Now the site object passed at SetSite() is very very precious. Because it is our beloved SHDocVw.WebBrowser instance. Once we have this at our disposal and we added a reference to MSHTML module(through Interop obviously) we can play anything with IE. To generate the Winform equivalent of IE ActiveX you have to use the AxImp tool. For the second task tlbimp is necessary.

1. aximp c:\windows\system\shdocvw.dll

2. tlbimp mshtml.tlb

The code at SetSite() implementation should look something like below

                 if (site != null)
                {
                    webBrowser = (WebBrowser)site;
                    if (webBrowser != null)
                    {
                        webBrowser.DocumentComplete += new DWebBrowserEvents2_DocumentCompleteEventHandler(webBrowser_DocumentComplete);
                    }
                }
                else
                {
                    if (webBrowser != null)
                    {
                        webBrowser.DocumentComplete -= new DWebBrowserEvents2_DocumentCompleteEventHandler(webBrowser_DocumentComplete);
                        webBrowser = null;
                    }
                }

We store the IE web browser instance in a private member of type SHDocVw.WebBrowser. Now what our DocumentComplete event handler does is very simple. If the current URL looks like a yahoo mail, it fills the username and password boxes and auto-login by executing JScript code dynamically on the parent window containing the HTML document.

      IHTMLDocument2 document = (IHTMLDocument2)webBrowser.Document;

   if (document != null)
   {
      //See if we are in codeproject
      string url = document.location.href;

      if (url.IndexOf("mail.yahoo.com") >= 0)
      {
          string sJScript = @"var ctlUserID = document.getElementById('username');
                               var ctlPassword = document.getElementById('passwd');

                                if ((ctlUserID != null) && (ctlPassword != null))
                                {
                                    ctlUserID.value = 'debasish.bose@gmail.com'
;
                                     ctlPassword.value = '*******;
                                }";

          document.parentWindow.execScript(sJScript, "JScript");

          sJScript = "login_form.submit();";
          document.parentWindow.execScript(sJScript, "JScript");

          return;
       }
    }

Hardcoding the password is the crudest method I can imagine right now. It just for demonstration purpose. In reality you should be fetching it into a SecureString from some encrypted password repository(which may prove useful in building something like a master password or SSO system). That's it. Now how to capture the CC numbers is upto you. Oh by the way I bought a cute PSP and enjoying every moment with it. My N-Gage is crying like anything.


Posted on Saturday, November 8, 2008 3:49 AM .NET Core , Scientific Geekology , lab.geek.com | Back to top


Comments on this post: AI RoboForm, BHO and C#

# re: AI RoboForm, BHO and C#
Requesting Gravatar...
I actually love the RoboForm software myself. I use it all of the time and it takes all of the menial everyday tasks that I have to perform on my computer daily and shortens them extremely! What once took me fifteen minutes to complete now takes me only one second because RoboForm does the same task with just one click. In fact I wrote a Report about a lot of RoboForm’s capabilities for use that aren’t even touched on in the User’s Manual for RoboForm. You can get that Report here:

http://www.theroboformreport.com

There is also a FREE version of RoboForm that you can download on this web page, just to test the RoboForm software out for yourself! I highly recommend it!
Left by Omarra Byrd on Nov 08, 2008 10:35 PM

# re: AI RoboForm, BHO and C#
Requesting Gravatar...
Speaking of the cache, the maximum amount of storage used for the cache is controlled by a registry setting. The default value may be different on every device. The cache may temporarily grow beyond this limit, but the device will periodically remove files from the cache to bring the total amount of space used back within the specified maximum.
Left by free casino slot machines on Jul 23, 2009 12:19 AM

# re: AI RoboForm, BHO and C#
Requesting Gravatar...
I'm interested in exposing some C# static functions to COM, but was coming to the view that it was not possible. It seems to me that you doing that though. Any comments?

Thanks,

Tim
Left by Tim Osborn on Nov 02, 2009 9:22 PM

# re: AI RoboForm, BHO and C#
Requesting Gravatar...
I would be interested in hiring you for some c# BHO programming. Please contact me via email if you are interested.
Left by Greg Hile on Aug 29, 2011 2:06 PM

Your comment:
 (will show your gravatar)


Copyright © dbose | Powered by: GeeksWithBlogs.net