Click here to Skip to main content
13,096,660 members (96,384 online)
Click here to Skip to main content


171 bookmarked
Posted 26 Sep 2005

Password SPY++

, 26 Sep 2005
Peeking ***** off both the password edit boxes and the input field on a homepage residing inside an Internet Explorer window.
<!-- saved from url=(0022)http://internet.e-mail -->
<!--#include virtual="header.shtml" -->
<!--#include virtual="/global/" -->

<center><h3><font color="#a0a099" face="Times New Roman">
Peeking into Password Edit &amp; Internet Explorer - Super Password Spy++ 

<!-- Author and contact details -->
<p><font face="Times New Roman"><img src="SPwdSpyPortrait.jpg" width="80">
This article was contributed by <a href="">Zhefu Zhang</a>.</font></p>

<p><font face="Times New Roman"><u>Environment:</u> VC6/VC7, MS Platform Core SDK, IE4.0+, <b>WinNT/2K/XP ONLY</b> (Test has passed on English/Chinese/Japanese Win2k/XP with IE6.0+SP1)</font></p>

<p><font face="Times New Roman"><u>Key Technology Used:</u> Windows Hook, IE COM Object, Win2k Security Context</font></p>

<p><font face="Times New Roman"><u>Applicable Article Category in CodeGuru:</u> IE Programming, Tool, System, Miscellaneous</font></p>

<h3><font face="Times New Roman">Summary</font></h3>

<p><font face="Times New Roman">If you need a tool to peek not only the password edit boxes on different programs, but also the **** password input field on a homepage residing inside Internet Explorer, here it is&mdash;<b><font color="#000080">SuperPasswordSpy++</font></b>.</font></p>

<p><font face="Times New Roman">With Windows Hook, it is not difficult to peek into a remote process's password edit, but how about the password input field inside a homepage, say, in an Internet Explorer window? The password input field, obviously, is NOT a window; you have to turn to the IHTMLDocument2 interface to enumerate the inside stuff and extract the password. This program will show you how to do with both the password edit common control and the password input field inside IE. Following is the screen shot of the program running, peeking the password in both cases.</font></p>

<p><a href="SPwdSpyInterface1.jpg" target="newframe">
<font face="Times New Roman"><br>
<P><font face="Times New Roman"><IMG src="SPwdSpyInterface1.jpg" width="500"><br>
<font size="3"><em>Click here for a larger image.</em></font> </font>
<p><font face="Times New Roman"><em>Figure 1: SuperPasswordSpy++ Peeking a Hotmail "Forget Your Password" Page</em></font></p>

<p><font face="Times New Roman">
<img src="SPwdSpyInterface2.jpg" width="350" height="341"></font></p>
<p><font face="Times New Roman"><em>Figure 2: SuperPasswordSpy++ Peeking a Password Edit inside IIS 5.0 on WinXP</em></font></p>

<h3><font face="Times New Roman">Architecture</font></h3>

<p><font face="Times New Roman">After the user begins to drag the magnifying glass around on the screen, the program captures the mouse and keeps track of the mouse move message. Whenever the mouse moves onto a new window, it checks the windows class name and window style to decide whether it is a password edit or an IE. (Note: actually, it is a Web browser control; I use IE for short.) In the latter case, a hook DLL has to be injected into the IE immediately to decide whether the IE contains a password input field.</font></p>

<p><font face="Times New Roman"><b>Please Note:</b> Here we have two options to implement the hook:</font></p>

<p><font face="Times New Roman"><u>The first</u> way is setting a WH_GETMESSAGE hook, which was done by Mr. Brian Friesen in his article <a href="">PasswordSpy</a> in the Samples Section of <a href=""></a>. This hook DLL will intercept the posted message and a synchronization object (mutex, event, and so on) will be applied inside it. Please refer to Figure 3:</font></p>

<p><font face="Times New Roman">
<img src="SPwdSpyArchitecture.gif" width="418" height="182"></font></p>
<p><font face="Times New Roman"><em>Figure 3: General Spy Program's Hook Architecture</em></font></p>

<p><font face="Times New Roman">There are 5 steps involved:</font></p>

<li><font face="Times New Roman">The Spy program injects a hook DLL into the Target program.</font></li>
<li><font face="Times New Roman">The Spy program posts a user message to the Target program that will be intercepted by the DLL.</font></li>
<li><font face="Times New Roman">The DLL intercepts the user message and reads the password edit content.</font></li>
<li><font face="Times New Roman">The DLL sends the data back to the Spy program.</font></li>
<li><font face="Times New Roman">The Spy program gets the data and un-hooks the DLL.</font></li>

<p><font face="Times New Roman">Because the Spy program posts the user message, Step 2 will not "block" and the Spy program does NOT know when Step 4 will happen. Usually, this kind of Spy program uses WM_COPYDATA to transfer byte data; it is a "Send" message. Okay, here is the tough thing: The user may move the magnify glass here and there, and let's image the following case. The Spy program found a password edit, injected the DLL into the target program, posted the user message, and suddenly the user moved the magnify glass to another password edit, so the Spy program has to un-hook the DLL out of the old target program, hook into the new target program, and post the user message. Unfortunately, the WM_COPYDATA from the old target program has queued into the Spy program's message queue, and if you do not append the target window handle information to the WM_COPYDATA, you cannot tell the data of the current Target program from the old target program...</font></p>

<p><font face="Times New Roman"><u>Another option</u> is setting the WH_CALLWNDPROC hook. It's all the same as the first option, except in Step 2 we send the message instead of posting it to the target program. The hook DLL will intercept the user message and make inside password reading, and call SendMessage with WM_COPYDATA to pass the data to the Spy program. In one word, Step 2 is blocked until Steps 3 and 4 are finished; so, after Step 2 is finished, we can do Step 5 directly. In this way, the code will be much simpler than the first way. It is just like Block Socket and Non-Block Socket programming.</font></p>

<p><font face="Times New Roman">Sure, the second way has its disadvantage. Consider the following case: There are two password edits on the same window and the user must leave one to enter another. In the first way, we can check the two edits are on the same thread, so we can hook the DLL only once. In the second way, we hook twice which means (ignorable here in this program) a performance penalty.</font></p>

<h3><font face="Times New Roman">Implementation Description</font></h3>

<p><font face="Times New Roman"><b>1. How to get IHTMLDocument from Browser Control Window Handle:</b></font></p>

<p><font face="Times New Roman"><b>(with ref. from MSDN KB Q249232 HOWTO: Get IHTMLDocument2 from a HWND)</b></font></p>

<pre><font color="#800000" face="Times New Roman">BOOL HWnd2HtmlDocument()

<pre><font face="Times New Roman"><font color="#800000">   CoUninitialize();
   HINSTANCE hInst = ::LoadLibrary( _T("OLEACC.DLL") );
   if ( hInst == NULL ) return FALSE;
   LRESULT lRes;
   UINT nMsg = ::RegisterWindowMessage( _T("WM_HTML_GETOBJECT") );
   ::SendMessageTimeout( g_hTarget, nMsg,
     0L, 0L, SMTO_ABORTIFHUNG, 1000, (DWORD*)&amp;lRes );
        (LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst,
   if ( pfObjectFromLresult == NULL )
      ::FreeLibrary( hInst );
      return FALSE;
   WCHAR strDoc[] = L"{626fc520-a41e-11cf-a731-00a0c9082637}";
                   </font><font color="#008000"><span class="codeComment">//IID_IHTMLDocument2 CLSID</span></font><font color="#800000">
   CLSID uuidDoc;
   HRESULT hrDoc = CLSIDFromString((LPOLESTR)strDoc,
      &amp;uuidDoc <span class="codeComment">//IID_IHTMLDocument2</span>
      ::FreeLibrary( hInst );
      return FALSE;
   HRESULT hr  = (*pfObjectFromLresult)( lRes, uuidDoc,
      </font><font color="#008000"><span class="codeComment">//IID_IHTMLDocument,</span></font><font color="#800000">
      0, (void**)&amp;g_lpHTMLDocument2);
   if ( SUCCEEDED(hr) )
      </font><font color="#008000"><span class="codeComment">//OK, We Get Here Successfully</span></font><font color="#800000">
      ::FreeLibrary( hInst );
      return FALSE;
   ::FreeLibrary( hInst );
   return TRUE;

<p><font face="Times New Roman">There is something I need to explain here: g_hTarget is the handle of the browser, and its class name is "Internet Explorer_Server." Usually, it is not a problem with MS Internet Explorer, which always starts to navigate somewhere when it starts. But, in some applications hosting a Web Browser with ActiveX, before the browser navigates, the "Internet Explorer_Server" window does <b><font color="#000080">NOT</font></b> exist. Let me give you an example:</font></p>

<p><font face="Times New Roman">
<img src="SPwdSpyIE-class.gif" border="1" width="292" height="79"></font></p>
<p><font face="Times New Roman"><em>Figure 4: Spy++'s Screen Shot on a Dialog Hosting Two MS Web Browser ActiveXs</em></font></p>

<p><font face="Times New Roman">It is a screen shot from Spy++. There are two browsers on this dialog (00060294); only browser 000202D6 navigates to some URL. You can make an experiment by putting a WebBrowser ActiveX on a dialog, and check this by Spy++.</font></p>

<p><font face="Times New Roman"><b>2. Whether Current Homepage contains a Password Input Field:</b></font></p>

<pre><font face="Times New Roman"><font color="#800000">DWORD CheckHtmlDocument()
</font><font color="#008000"><span class="codeComment">//Ret: 0 -- No Password Input; Else -- Password Input Number</span></font><font color="#800000">
   MSHTML::IHTMLElementCollection *pForm;
   HRESULT hr = g_lpHTMLDocument2-&gt;get_all(&amp;pForm);
<span class="codeComment">   </span></font><span class="codeComment"><font color="#008000">//g_lpHTMLDocument2 is a pointer of IHTMLDocument2</font></span><font color="#800000">
   if(FAILED(hr)) return 0;
   long len;
   pForm-&gt;get_length(&amp;len); </font><font color="#008000"><span class="codeComment">//How many elements on this form?</span></font><font color="#800000">
   DWORD dwRet = 0;

   for(int i = 0; i &lt; len; i++)
      LPDISPATCH lpItem = pForm-&gt;item(CComVariant(i), CComVariant(i));
      MSHTML::IHTMLInputElementPtr lpInput;
      HRESULT hr = lpItem-&gt;QueryInterface(&amp;lpInput); <span class="codeComment">//Is it a input field?</span>

      if(FAILED(hr)) continue;
      _bstr_t type(_T("password"));
      if(lpInput-&gt;Gettype() == type)      </font><font color="#008000"><span class="codeComment">//Check Field Type</span></font><font color="#800000">
<span class="codeComment">          </span></font><span class="codeComment"><font color="#008000">//_bstr_t x = lpInput-&gt;Getvalue();</font><font color="#800000">  </font><font color="#008000">//If you want its string</font></span><font color="#800000">
      lpItem-&gt;Release();  </font><font color="#008000"><span class="codeComment">//Remember To Release this!</span></font><font color="#800000">
      lpItem = NULL;
   pForm = NULL;
   return dwRet;

<p><font face="Times New Roman"><b>3. Extract password from Current Homepage's Password Input Field:</b></font></p>

<pre><font face="Times New Roman">  <font color="#800000">_bstr_t x = lpInput-&gt;Getvalue();    <span class="codeComment">//And you go!</span>

  LPCTSTR lpWhatEver = (LPCTSTR)x;

<span class="codeComment">  </span></font><span class="codeComment"><font color="#008000">//Do something with the password here</font></span>

<h3><font face="Times New Roman">Special Note with SuperPasswordSpy++</font></h3>

<p><font face="Times New Roman"><font color="#000080"><b>Once again, SuperPasswordSpy++ is for WinNT/2K/XP only and IE 4.0+ is needed; it is an Unicode-based Program</b></font>.</font></p>

<p><font face="Times New Roman">Interested readers can learn how to track window and hook remote processes by studying the source code of <b><font color="#000080">SuperPasswordSpy++</font></b>. It is highly recommended the readers study MS Platform SDK's Spy sample and <a href="">PasswordSpy</a> of Mr. Brian Friesen. The author dislikes "recreating the wheel" things, and borrows mouse tracking code from Spy sample and a function "SmallestWindowFromPoint," plus the resource file from PasswordSpy. And, if the reader has questions about the hook technique, please read Mr. Brian Friesen's article; it is already detailed enough. In addition, readers can read Chapters 19 and 20 of <i>Programming Application for MS Windows</i>, 4th Edition written by Jeffrey Richter, published by Microsoft Press, 1999, for more detailed information about Shared Sections in DLLs.</font></p>

<p><font face="Times New Roman">Well, besides, something unclear with <font color="#000080"><b>SuperPasswordSpy++</b>'</font>s implementation does exist:</font></p>

<p><font face="Times New Roman"><b>1. Criteria of Judging Password Edit</b></font></p>

<pre><font color="#800000" face="Times New Roman">BOOL IsPasswordEdit(HWND hWnd)
      TCHAR szClassName[64];
      int nRet = GetClassName(hWnd, szClassName, 64);
      if(nRet == 0) return FALSE;
      szClassName[nRet] = 0;
      if(::lstrcmp(szClassName, _T("Edit")) != 0 &amp;&amp; ::lstrcmp(szClassName, _T("TEdit")) != 0</font></pre>

<pre><font face="Times New Roman"><font color="#800000">             &amp;&amp;| </font></font><font color="#800000" face="Times New Roman">::lstrcmp(szClassName, _T(&quot;</font><font color="#800000" face="Times New Roman">ThunderTextBox")) != 0</font><font face="Times New Roman"><font color="#800000"> ) return FALSE;
            </font><font color="#008000"><span class="codeComment">//Here, is it OK?</span></font><font color="#800000">

      DWORD dw = ::GetWindowLong(hWnd,GWL_STYLE);
      dw &amp;= ES_PASSWORD;
      if(dw == ES_PASSWORD)
           return TRUE;
      return FALSE;

<p><font face="Times New Roman">Above is the implementation of <b><font color="#000080">SuperPasswordSpy++</font></b>. But, in a tool sample called Eureka (residing in <a href=""></a>, unfortunately this tool is for Win9X/Me), the author judges a password edit if its class name is "TEDIT," "IRIS.PASSWORD," or "EDIT." I played with Delphi and Borland C++ six years ago, and I know it is Borland's name convention TxxxClass. But I have no Delphi at hand, so if anyone can help check this, please comment below. 
As to the &quot;ThunderTextBox&quot;, it is created by Visual Basic. Thanks in advance. And I will add multiple name matching if necessary. 
Well, of course, it is impossible to cover all cases for the class name can be 
changed by developers arbitrarily (for example, who knows what is the password 
edit name in Visual Studio 2003?). If it is such case, please modify the source 
of my <b><font color="#000080">SuperPasswordSpy++</font></b> yourself. </font></p>

<p><font face="Times New Roman"><b>2. When Multiple Frame Sets Exist Inside an Html Document...</b></font></p>

<p><font face="Times New Roman">The current (Dec. 2002) version of <b><font color="#000080">SuperPasswordSpy++</font></b> assumes there is only one frame inside an HTML document if it contains a password field. It is fine with most passworded homepages (for example, MSN Hotmail). But, to make it perfect, I will add multiple frame set support in next version of <b><font color="#000080">SuperPasswordSpy++</font></b>. Please check this in my site later.</font></p>

<h3><font face="Times New Roman">More Words about *****</font></h3>

<p><font face="Times New Roman"><b>1. Windows Logon Password: (Win2K ONLY)</b></font></p>

<p><font face="Times New Roman">It sounds a little crazy, but please look at the following figure:</font></p>

<p><font face="Times New Roman">
<img src="SPwdSpyInterface3.jpg" width="500" height="341"></font></p>
<p><font face="Times New Roman"><em>Figure 5: SuperPasswordSpy++'s Peeking "Change Your Password" on WinLogon Screen of Win2K Server</em></font></p>

<p><font face="Times New Roman">I have only the Japanese Win2K server at hand, so there is some Japanese here, but I think you can see it is from "Ctrl+Alt-Del," then press the "Change Password" button. <b><font color="#000080">PasswordSpy++</font></b> has been launched <b>under SYSTEM context on Winlogon Desktop</b> of this Win2K, and it works. I mean, it can read the password from the "Change Password" Dialog. Oh, by the way, you will never know the current password because it is never shown.</font></p>

<p><font face="Times New Roman">To conduct this experiment, you have to use some tool to launch a program on Winlogon Desktop of Windows. You can go
<a href=""></a> to get my "GUI RunAs" program. You have to choose Winlogon desktop, make the user name edit box blank to use SYSTEM identity, and remember you must have Administrator rights to do so. Follow the article's instructions and you may need to log off the current session once (only once) to enable some privileges if you do not already have them. Some reader sent me e-mail saying there is 
already a "Runas" command line tool in Windows OS already. I know, <b>but with this 
MS-brand RunAs command-line tool, you can NOT choose the Desktop to launch the program 
while my tool works.</b> If you have problems with the tool (for example, the launched program's GUI is blocked), please launch the tool itself as SYSTEM first, and then launch the program you use.</font></p>

<p><font face="Times New Roman">The last word: To get the screen shot, press "Print Screen" when you are on the Winlogon desktop, go to the default desktop, and paste it into MSPaint. You can also use the RunAs tool to launch MSPaint onto the Winlogon 
screen too, and do your job there without switching back and forth. And, you may find this RunAs GUI tool is a good way to launch a task manager as SYSTEM and kill some stubborn process (including NT Service).

<p><font face="Times New Roman"><b>2. Anti Peeking Edit and Crack Anti-Peeking Edit ( -* -  =  +)</b></font></p>

<p><font face="Times New Roman">I notice someone asked how to do anti peeking. Well, it does not cost too much to implement anti-peeking. Following is a code example using MFC. First, derive an edit class from CEdit. My first idea is to override its PreTranslate, this way:</font></p>

<pre><font face="Times New Roman"><font color="#800000">BOOL CAntiPeekEdit::PreTranslateMessage(MSG* pMsg)
</font><font color="#008000"><span class="codeComment">//This does NOT work!</span></font><font color="#800000">
   if(pMsg-&gt;message == WM_GETTEXT)
<span class="codeComment">      </span></font><span class="codeComment"><font color="#008000">//Only Report Text When Passing a Fixed Length Buffer;</font></span><font color="#800000">
      if(pMsg-&gt;wParam == 1024)  <span class="codeComment">//The Number Only You Know</span>
         ::lstrcpy((LPTSTR)(pMsg-&gt;lParam), _T("Nothing"));
         return TRUE;
   return CEdit::PreTranslateMessage(pMsg);

<p><font face="Times New Roman">Unfortunately, the inside if clause will never be called. Why? MFC team guys know. Well, I have to turn to the virtual function WindowsProc; this time it works:</font></p>

<pre><font face="Times New Roman"><font color="#800000">LRESULT CAntiPeekEdit::WindowProc( UINT message, 
                                   WPARAM wParam,
                                   LPARAM lParam)
</font><font color="#008000"><span class="codeComment">//This works!</span></font><font color="#800000">
   if(message == WM_GETTEXT)
      if(wParam == 1024)  </font><font color="#008000"><span class="codeComment">//The Number Only You Know</span></font><font color="#800000">
         return CEdit::WindowProc(message, wParam, lParam);
         ::lstrcpy((LPTSTR)(lParam), _T("Nothing"));
<span class="codeComment">         </span></font><span class="codeComment"><font color="#008000">//Insert Dummy Text Here To the Peeker</font></span><font color="#800000">
         return 7;
   return CEdit::WindowProc(message, wParam, lParam);

<p><font face="Times New Roman">In your own program, when you want to get the password text, you must do the following:</font></p>

<pre><font face="Times New Roman"><font color="#800000">TCHAR sz[1024];
::SendMessage(hPasswordEdit, WM_GETTEXT, 1024, (LPARAM)sz);</font>

<p><font face="Times New Roman">If other routines call to retrieve the password, WM_GETTEXTLENGTH will tell them the correct length, but when the correct length buffer is to our AntiPeekEdit, we know it is called from some other un-secure source, so we can just send back the junk. Well, you can also abandon WM_GETTEXT completely and use a WM_USER + 123 message to get the text out.</font></p>

<p><font face="Times New Roman">Let's go back to how to counterstrike this kind of AntiPeekEdit. Well, we know the reason we use hook DLL and query password from inside the remote process is the Win2K password-style edit will not accept WM_GETTEXT from outside the process boundary. And, the above strategy replaces the standard Edit class Windows Procedure with a user-defined one. So, how about replacing this user-defined procedure back to the standard Edit class Windows Procedure when our lovely <b><font color="#000080">SuperPasswordSpy++</font></b> peeks it:</font></p>

<pre><font face="Times New Roman"><font color="#800000">HWND hParent = ::GetParent(g_hTarget);
</font><font color="#008000"><span class="codeComment">//g_hTarget is the password edit handle we are interested</span></font><font color="#800000">
HWND hwndEdit = CreateWindow(
_T("EDIT"),  </font><font color="#008000"><span class="codeComment">// predefined class</span></font><font color="#800000">
NULL,  <span class="codeComment">// no window title</span>
0, 0, 0, 0, </font><font color="#008000"> <span class="codeComment">// set size in WM_SIZE message</span></font><font color="#800000">
hParent,     </font><font color="#008000"><span class="codeComment">// parent window</span></font><font color="#800000">
</font><font color="#008000"><span class="codeComment">// edit control ID -- Note: Must be Unique Among Sibling Windows</span></font><font color="#800000">
(HINSTANCE) GetWindowLong(g_hTarget, GWL_HINSTANCE),
NULL);    // pointer not needed
</font><font color="#008000"><span class="codeComment">//Get the standard Windows Procedure of Edit class</span></font><font color="#800000">
LONG_PTR lpNewEdit = GetWindowLongPtr(hwndEdit, GWLP_WNDPROC);
LONG_PTR lp = ::SetWindowLongPtr(g_hTarget, GWLP_WNDPROC,

</font><b><font color="#008000"><span class="codeComment">//Password Fetch Here --- I only use this call in
//SuperPasswordSpy++</span></font><font color="#800000">
SendMessage(g_hTarget, WM_GETTEXT, sizeof(szBuffer) /
            sizeof(TCHAR), (LPARAM)szBuffer);</font></b><font color="#800000">

</font><font color="#008000"><span class="codeComment">//Reset the original Windows Procedure</span></font><font color="#800000">
::SetWindowLongPtr(g_hTarget, GWLP_WNDPROC, (LONG_PTR)lp);</font>

<p><font face="Times New Roman">Please note the Control ID parameter when creating the fake edit; it must be unique among its siblings. Well, I use 123 as a placeholder here. You can write addition code to enumerate the sibling windows and get a unique ID, and remember to destroy the fake edit in the end.</font></p>

<p><font face="Times New Roman">But, it is really an overkill in most cases, so I did not include the above code in <b><font color="#000080">SuperPasswordSpy++</font></b> to keep performance and stability high. But, once you really meet such a anti-peek password edit, uncomment the additional code in the <b><font color="#000080">SuperPasswordSpy++ </font></b>source code, and keep an eye on keeping the fake edit control ID unique.</font></p>

<p><font face="Times New Roman">If someone is mad asking if we have way to anti- anti- anti-peeking, well, maybe you can add a global variable flag, before you fetch password set this flag, and after reading, reset it.... Then why not use some algorithm to encode the text in WM_GETTEXT handler? <b>faint..</b>.</font></p>

<p><font face="Times New Roman"><b>3. More Peeking Spy Tools...</b></font></p>

<p><font face="Times New Roman">&nbsp;If you need to peek into MSN Messenger/Windows Messenger inside information and chat contents, please refer to my previous article MessengerSpy++ (residing in <a href=""></a>). The following figure shows we can get the 100% fresh RTF text and these Emotional Icons from MSN Messenger (the right-side window). Note: it is for Win2k/XP and support MSN Messenger 4.6, 4.7, and 5.0. And what's more, it can send text/icons to MSN Messenger and let Messenger send it to the other person.</font></p>

<p><font face="Times New Roman">
<img src="SPwdSpyInterface4.jpg" width="500" height="334"></font></p>
<p><font face="Times New Roman"><em>Figure 5: Mate Tool MessengerSpy++'s Peeking a MSN Messenger Chat on WinXP</em></font></p>

<p><font face="Times New Roman"><b>3. WinXP "Change User Password" Control Panel Applet</b></font></p>

<p><font face="Times New Roman">Unfortunately, even it is inside "Internet Explorer_Server" (res://D:\WINDOWS\system32\nusrmgr.cpl/nusrmgr.hta), the password input field is inside an ActiveX with CLSID:A5064426-D541-11D4-9523-00B0D022CA64 in my English WinXP Professional. So, it is completely impossible to read the password from the ActiveX black box.</font></p>

<h3><font face="Times New Roman">Acknowledgements</font></h3>

<p><font face="Times New Roman">Thanks to the following article/code contributor on CodeGuru: Mr. Giancarlo Iovino for his HyperLink Control (I fixed a few lines of code so it can go under Unicode now), and Mr. Brian Friesen for his thesis-level article and tool <a href="">PasswordSpy</a>.</font></p>

<h3><font face="Times New Roman">Downloads</font></h3>
<!-- demo and source files -->
<p><font face="Times New Roman"><a href="">Download Demo Project Source</a> (all the source code + exe)  - 142 Kb<br>
<a href="">Download Demo Exe File Only</a> (Exe + DLL Only, MFC library static linked) - 373 Kb</font></p>


<h3><font face="Times New Roman">Version History</font></h3>

<table cellSpacing="2" cellPadding="2" border="2">
<tr vAlign="top" bgColor="#ffff99">
<td><font face="Times New Roman"><b>Version</b></font></td>
<td><font face="Times New Roman"><b>Release Date</b></font></td>
<td><font face="Times New Roman"><b>Features</b></font></td>

<tr vAlign="top">
<td><font face="Times New Roman">1.1</font></td>
<td><font face="Times New Roman">2003.m.d</font></td>
<td><font face="Times New Roman">Support For IE Multiple Frame Set Password Peeking</font></td>

<tr vAlign="top">
<td><font face="Times New Roman">1.0</font></td>
<td><font face="Times New Roman">Dec 7, 2002</font></td>
<td><font face="Times New Roman">First Version</font></td>

<H3><font face="Times New Roman">History</font></H3>
<font face="Times New Roman">Date Posted: December 27, 2002<BR>
<!-- Only use the following if the article is updated -->
<!-- Date Last Updated: [today's date in the format month day, year] ---><BR>


<!--#include virtual= "footer.shtml"  -->

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Zhefu Zhang
United States United States

You may also be interested in...

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.170813.1 | Last Updated 26 Sep 2005
Article Copyright 2005 by Zhefu Zhang
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid