Click here to Skip to main content
15,881,281 members
Articles / Desktop Programming / Win32

Password Field Unhider (and some C++ utility classes)

Rate me:
Please Sign up or sign in to vote.
4.88/5 (10 votes)
9 Apr 2009CPOL13 min read 53.9K   1.5K   46   11
Utility to unmask password edit controls and INPUT fields, plus some useful C++ classes used to implement it.

Password Unhider in action

Contents

Introduction

I have had a longstanding itch - I finally scratched it. This small utility is the result, and I'm posting it here for a couple of reasons. First, maybe you have the same itch, and this is a solution. And second, while writing it, I used several simple utility classes I keep in my toolbox and you might find them useful too.

What is this nagging itch? It is the darn password edit controls that show asterisks or circles instead of the password you're typing. Oh yes, this is a "security" feature. Some bad guy might be looking over your shoulder to steal your passwords. Except, that of the 4 computers I use on a daily basis, nobody is ever, I mean, ever looking over my shoulder. They're on my desk in my home! But, I use strong passwords with punctuation marks and digits and all that good stuff—sometimes I can't really tell if I typed the password correctly.

So, this simple utility lives in the tray - oops, I mean the Taskbar Notification Area, and whenever I have a password field blocking my view, I can simply click on its icon and the password field will be changed to a normal text field. Problem solved!

This is really a quite vanilla old-style Win32 program. Still, I have used a few utility classes you might find useful yourself. I have a class that encapsulates sending a message (buffer of bytes) from one Windows program to another via WM_COPYDATA, a general message pump, and a nice little work item dispatcher suitable for running work items in your message loop's idle time. All of them are small and simple, and you can read the code in a few minutes to figure out what they do and if they're suitable for your needs. If you find one useful, go ahead and use it!

How Password Fields are Unmasked

The PasswordUnhider uses two different techniques to unhide (unmask) password fields.

First, some password fields are standard edit controls in an ordinary Win32 program, that have a password mask character set—either the control was created with the ES_PASSWORD style, or it was sent an EM_SETPASSWORDCHAR notification with a non-zero password character. The utility searches for these edit controls and send them an EM_SETPASSWORDCHAR notification with a zero password character.

C++
// Set the password character on an edit control - which is in another process
bool SetPasswordChar(HWND hWnd, wchar_t c)
{
    // Try SendMessage first
    ::SendMessage(hWnd, EM_SETPASSWORDCHAR, c, 0);
    DWORD err = ::GetLastError();
    if (err != 0)
    {
        // PostMessage can succeed where SendMessage failed.
        // (I'm not sure what the security model is that explains this.)
        BOOL b = ::PostMessage(hWnd, EM_SETPASSWORDCHAR, c, 0);
        if (!b)
        {
            err = ::GetLastError();
            // Well, it didn't work
            return false;
        }
    }
    ::InvalidateRect(hWnd, NULL, TRUE);
    return true;
}

To find these controls, the utility enumerates the desktop windows (::EnumDesktopWindows API), and then for each desktop window which is an application, it enumerates all child windows looking for password controls (using the ::EnumChildWindows API).

To determine if a window is a password control—that is, an edit control with a password hiding character set—the utility sends the window an EM_GETPASSWORDCHAR message and sees what kind of answer it gets. Only edit controls—or things that act like edit controls—will answer this notification (with maybe some exceptions). I can't look at the class name or window procedure because the application may be using edit controls that are superclassed or subclassed but still behave like password fields.

C++
// Determine if a window is an edit control of some kind
bool IsPasswordEditControl(HWND hWnd)
{
    if (!::IsWindow(hWnd))
        return false;

    // Make sure the window class isn't on our list of non-edit controls
    // (that answer message EM_GETPASSWORDCHAR)
    wchar_t szClass[128];
    int n = ::GetClassName(hWnd, szClass, ARRAYSIZE(szClass));
    for (unsigned int i = 0; i < s_notEditControlClasses.size(); i++)
        if (s_notEditControlClasses[i] == szClass)
            return false;

    // Check for edit control by checking to see if it understands
    // EM_GETPASSWORDCHAR (and if the password char is set!)
    DWORD msgResult = 0;
    LRESULT r = ::SendMessageTimeout(hWnd, EM_GETPASSWORDCHAR, 0, 0, 
      SMTO_ABORTIFHUNG | SMTO_NORMAL, MSG_TIMEOUT, &msgResult);

    return (r != 0) && (msgResult != 0);
}

(I did find that a window with the class name "Acrobat IEHelper Object" returns a non-zero answer for EM_GETPASSWORDCHAR—the exception mentioned above—so I also use a little array of exceptional class names to filter out these false positives. Right now, "Acrobat IEHelper Object" is the only class name in that array.)

Second, some password fields are INPUT elements in web pages. In IE, these are not implemented with Win32 edit controls, so a different technique is used.

First, I find all of the browser (IE) windows by using the ShellWindows COM object, which is a collection of all the browser windows. From each of those windows (represented as a COM object, not a window handle), the HTML document can be retrieved, and from each HTML document, the collection of all INPUT elements can be retrieved. Then, each INPUT element can be checked to see if it has an attribute "type" with the value "password".

Once a password type INPUT element is found, it is necessary to change the type to "text". Unfortunately, for security reasons, you can't just change the attribute value. Instead, the utility gets the outer HTML for the INPUT element, does a text substitution of "type=text" for "type=password", creates a new INPUT element that is the same as the original except for this attribute, and patches it into the tree in place of the original INPUT element.

C++
// Begin the replacement by getting the outer HTML.
if (SUCCEEDED(hr))
{
    hr = pElement->get_outerHTML(&bstrOuterHTML);
}

// The string "type=password" ought to be in there somewhere ...
if (SUCCEEDED(hr))
{
    outer = bstrOuterHTML;
    wstring outerLower = MakeLower(outer);
    iFind = Find(outerLower, wstring(L"type=password"));
    hr = BOOL_TO_HR(iFind >= 0);
}

// ... so remove it.
if (SUCCEEDED(hr))
{
    outer.erase(iFind, _tcslen(L"type=password"));
    outer.insert(iFind, L"type=text");
    bstrNewElement = CComBSTR(outer.c_str());
    hr = PTR_NON_NULL(pDoc2 = pDoc3_);
}

// Create a new HTML element from the modified outer HTML
if (SUCCEEDED(hr))
{
    hr = SUCCEEDED_AND_PTR_NON_NULL(pDoc2->createElement(bstrNewElement, 
                                    &pNewElement), pNewElement);
}

// And now hook up our new HTML (INPUT) element replacing the original
// INPUT element.
if (SUCCEEDED(hr))
{
    hr = SUCCEEDED_AND_PTR_NON_NULL(pElement->get_parentElement(&pParent), pParent);
}
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pParentDOM = pParent);
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pElementDOM = pElement);
hr = SUCCEEDED_AND_PTR_NON_NULL(hr, pNewElementDOM = pNewElement);

if (SUCCEEDED(hr))
{
    hr = pParentDOM->replaceChild(pNewElementDOM, pElementDOM, &pReplaceDOM);
}

(Unfortunately, when you do this, whatever text has been typed into that input element is lost. So: click the icon before typing your password into an HTML field.)

Splitting Up the Work

The original program did everything in one process: it ran the tray icon and, when commanded, searched for and changed password fields. I knew, even before I wrote the program, that it would take some time to search all the windows on the desktop looking for password fields, and also some time to search all browser windows looking for INPUT elements. So, I wanted the user to have some feedback while this search was taking place. I wanted to blink the tray icon while this process was happening.

I didn't want to mess with multiple threads for such a simple utility, so I found my trusty idle-time work-item dispatcher and used it to split the password unhiding process into a lot of little work items. Looking at each window would be its own work item, as would looking at each INPUT element. In this way, I thought I could run the work items during the application's idle time, and the system tray class would then be able to nicely and smoothly animate the tray icon via Windows timer messages.

But, it turned out the icon animation wasn't smooth at all. Some of the operations took quite a bit of time, for example, getting the ShellWindows collection, and then processing each INPUT element. It was understandable, because those operations were manipulating the web page's DOM cross-process.

So, I restructured the program so it runs in two processes now. The original process that the user starts puts up the tray icon and manages it, and that's it. When the user clicks to unhide password fields, the program launches a copy of itself in a new process, with command line parameters to tell it what to do, and to tell it how to communicate back to the original process.

The second process sends messages back to the original process for each password field that it unmasks. That way, the original process can put up notification balloons as feedback to the user.

(The work item stuff is all still there, even though the second process doesn't really need it, because it has no UI that it needs to keep responsive. It was working, and there was no reason to rip it out.)

(By the way, I know that it is a waste of resources to keep a process running a system tray icon, consuming a couple of megabytes of private data, and so on, but I don't care. I want those password fields unmasked on demand, and I'm willing to pay the price. It's not like this is some random utility some device manufacturer (mouse, or trackball, or video card) installed on my machine and decided to keep running all the time just in case some day I wanted to change the resolution on my screen—which I never do.)

Useful C++ Classes

CMessagePump—An application main message pump

CMessagePump is a class that implements an application's main message pump. It runs until WM_QUIT is received.

It is parameterizable as follows:

  • It will handle multiple accelerator tables.
  • It will handle a modeless dialog (for keyboard handling).
  • It will test for and perform work when no messages are available ("idle work").
  • It will callout for messages sent to the thread, rather than to a window.

Here is an example showing how to create a message pump, parameterize it, and then set it into operation:

C++
// Create the message pump
auto_ptr<CMessagePump> s_msgPump(new CMessagePump(hInstance));

// Set up accelerator table, and hook up
// the work item dispatcher to run in the idle time
s_msgPump->AddAccelerators(::LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PASSWORD)))
          .SetIdleWorkTest(pdispatcher, &CWorkItemDispatcher::HaveWork)
          .SetIdleWorkFunction(pdispatcher, &CWorkItemDispatcher::DoWork);

// Pump messages, don't return until WM_QUIT
ret = s_msgPump->DoMessagePump();

CWorkItemDispatcher—An easy-to-use work item dispatcher, suitable for idle-time processing

CWorkItemDispatcher implements a queue of work items, executing one when requested.

Before getting into how to use it, one question is surely in your mind, so I'll answer it first: Eh, why the heck does the world need another work item dispatcher?

Well, it doesn't really. But, nevertheless, I like this one. It is very simple, so there is very little chance it can get in your way and misbehave. It is very easy to use, so work items can be built as classes if you need state, or you can just use any object you have lying around by implementing a suitable 0- or 1-parameter method on it, or you can use anything you can stuff into a std::tr1::function—which gives you a lot of choice, and maximizes the chance that you don't have to go out of your way to create work items. Yet, simple as it is, it does implement priorities, and it also implements delayed work items that fire at a future time.

And, it integrates smoothly with CMessagePump (or with any other message pump you have) to make a smoothly running Win32 application.

So, how to use it? First, let's talk about work items. There is an abstract class, IWorkItem, from which all work items are derived.

C++
class IWorkItem
{
    public:

        IWorkItem() {}
        virtual ~IWorkItem() {}

        // This is where you actually do the work of your work item.
        // The dispatcher is provided so that you can enqueue further
        // work items. You can even enqueue yourself again.
        virtual void DoWork(CWorkItemDispatcher* dispatcher) = 0;
};

Well, that's pretty standard. You derive from IWorkItem, implement DoWork() (and a constructor and destructor if you need to), and you're ready to go.

Alternatively, you can just provide a function to run. A class CWorkItemFactory provides a bunch of static functions that create work items from your function or function-like thing.

C++
class CWorkItemFactory
{
public:
    // Work functions that take no parameters
    static std::auto_ptr<IWorkItem> New(void (*)());
    static std::auto_ptr<IWorkItem> New(std::tr1::function<void()>);
    template<class T> static std::auto_ptr<IWorkItem> New(T&, void(T::*)());

    // Work functions that take 1 parameter (typically, some kind of cookie)
    template<class TP> static std::auto_ptr<IWorkItem> New(void (*)(TP), TP);
    template<class TP> static std::auto_ptr<IWorkItem> New(std::tr1::function<void(TP)>, TP);
    template<class T, class TP> static std::auto_ptr<IWorkItem> New(T&, void(T::*)(TP), TP);
    ...

The six New functions come in two flavors: those which take a 0-parameter function, and those which take a 1-parameter function, and a parameter object to supply to it (when the work item is run).

Each of the two flavors has three varieties: one which takes a simple function, one which takes a std::tr1::function, and one which takes an object and a method on that object.

So that covers a lot of possibilities on how to easily create a work item from some function or method you have lying around.

Enqueuing a work item is very easy. The dispatcher provides an AddWork() method which takes a work item and a priority. When you enqueue the work item, the dispatcher takes over ownership of it. There is also an AddDelayedWork() method which takes, in addition, a delay in milliseconds. The work item will be held in a separate queue until (at least) that many milliseconds have elapsed, and then it will be transferred to the regular queue (where it will be executed in priority order).

Finally, how is the work item dispatcher created and used? A factory method, CWorkItemDispatcher::StandardWorkItemDispatcherFactory(), will return a dispatcher. The dispatcher has two useful methods for running work items:

C++
// Returns true if there are any work items in the queue, or if
// there are any delayed work items even if their timers haven't
// expired.
virtual bool HaveWork() = 0;

// Performs (at most) one unit of work (and moves delayed work items
// to the work queue if they're ready to go)
virtual void DoWork() = 0;

These simple methods are just right for hooking up to a message pump, or in the main loop of a thread.

The work item dispatcher can be parameterized in two ways. First, you can choose whether or not you need to protect its work item queues with a lock or not. If you have a single threaded program, you don't need a lock. If you are going to enqueue work items from different threads, you need a lock. (All work items must be consumed from a single thread; that is, DoWork() should always be called from the same thread.)

The other way to parameterize the work item dispatcher is to control how it can "kick" its controller—typically, the message pump—when it has new work items ready to run. The issue is that the message pump might want to go into a wait state when there is no work for it to do. Then, some other thread might add a work item, or the time might have arrived for a delayed message to run. The message pump must be awakened. You can control what Windows message is used to kick the message pump, and what window or thread the message should be sent to.

CCopyIPC—A one-way message transfer between processes, using WM_COPYDATA

CCopyIPC will copy a message—a buffer of bytes—from one process to another, via the Windows WM_COPYDATA facility. Obviously, this means that the receiving process must be running a message loop.

The sender and the receiver both instantiate a CCopyIPC object.

All the sender needs to do is call CCopyIPC::Send with a buffer of bytes, or an object, and the handle of the window to which to send the message. The window handle is passed out-of-band. For the PasswordUnhider, I put it on the command line of the process that is launched to process the password fields.

C++
class CCopyIPC
{
    public:
        ...
        // Send a buffer of bytes to the receiver
        result_t Send(HWND hWndReceiver, uint nBytes, const char* bytes);

        // Send an object to the receiver
        template<class T>
        result_t Send(HWND hWndReceiver, const T& data);
        ...

The receiver has a little more work. It has to handle the WM_COPYDATA message in the message loop of the target window. CCopyIPC supplies a suitable procedure that can be called with the wparam and lparam when the WM_COPYDATA message is received.

C++
// Message handler for receiver
LRESULT DoWMCopyData(WPARAM wParam, LPARAM lParam);

The receiver also has to supply a callback function to be called when the data comes in. The nice thing is that CCopyIPC lets you supply the callback function in several forms.

First, the callback can get either a buffer of bytes, or an object. Second, the callback can be either a simple function, a function object, or a method.

C++
    ...
    // Callbacks for received data - as a buffer of bytes
    // (the first parameter is the HWND of the sender)

    CCopyIPC& SetDataCallback(void (*)(HWND, uint, const char*));

    CCopyIPC& SetDataCallback(std::tr1::function<void(HWND, uint, const char*)>);

    template<class T>
    CCopyIPC& SetDataCallback(T& t, void (T::*)(HWND, uint, const char*));

    // Callbacks for received data - as a particular self-contained struct

    template<class TD>
    CCopyIPC& SetDataCallback(void (*)(HWND, const TD&));

    template<class TD>
    CCopyIPC& SetDataCallback(std::tr1::function<void(HWND, const TD&)>);

    template<class T, class TD>
    CCopyIPC& SetDataCallback(T& t, void (T::*)(HWND, const TD&));
    ...
};

Points of Interest

I am currently satisfied with my click-to-unhide approach. Another option would be to continually monitor the system and go ahead and unhide password fields as they are created. It would seem more convenient for the user.

This approach would use Windows hooks for ordinary Win32 applications, for example, the CBT hook. Or a DLL injection approach could be used, for example, with Detours. For IE windows, you could use a BHO.

Unfortunately, solutions like this could create stability problems, and possibly performance issues as well. I decided that, for now, I didn't need the convenience of a 0-click solution.

One issue that came up is that in most cases, when sending EM_SETPASSWORDCHAR to a window (in another process), SendMessage would fail with ERROR_ACCESS_DENIED, but PostMessage would work. I'm not sure why this happens. If anyone could enlighten me in the comments, I would appreciate it.

Limitations

This is just a simple utility that I wrote to meet my needs. I hope it meets your needs, but if it doesn't, ... I'm sorry.

In particular:

  • I didn't test with Firefox or any other browser besides IE. In fact, I only tested with IE7.
  • I only tested on Windows XP. Windows Vista has UIPI (User Interface Privilege Isolation) which may interfere with sending, between processes, the messages that change the password fields. And, the manipulation of HTML documents in another process might not work either, for that reason or other similar reasons.
  • It probably won't work with password dialogs popped up by the OS itself—though I haven't tried it.

In all cases, I'd be interested to hear about the problem, and really interested to hear how you fixed it!

Those of you wishing to compile the utility yourself, or to use the utility classes I've described: I make use of TR1 facilities like function, mem_fn, bind, and tuple. This means, you need, at a minimum, Visual Studio 2008 SP1. Alternatively, you could use Boost's TR1 implementation (though I haven't tried it).

Dependencies and Acknowledgements

The system tray icon is managed by the excellent CSystemTray class, written by Chris Maunder and described in his excellent article Adding Icons to the System Tray.

Article Revision History

  • Apr 9, 2009: Original article.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Bakin's Bits
United States United States
I've been programming for 35 years and I'm still learning new things. My major interests recently are programming models and methods for concurrency, applications of functional programming, and doing interesting things with Mathematica.

Comments and Discussions

 
GeneralWindows Live Messenger Pin
sajmon7212-Jun-11 14:03
sajmon7212-Jun-11 14:03 
QuestionHow to run on VS2005 or Turbo C++, Also getting error in conversion.. Pin
rediff1234yahoo28-Apr-09 23:13
rediff1234yahoo28-Apr-09 23:13 
AnswerRe: How to run on VS2005 or Turbo C++, Also getting error in conversion.. Pin
davidbakin2-May-09 17:47
davidbakin2-May-09 17:47 
GeneralUnable to run the application and source Pin
sirch fsarso27-Apr-09 22:16
sirch fsarso27-Apr-09 22:16 
AnswerRe: Unable to run the application and source Pin
davidbakin2-May-09 17:37
davidbakin2-May-09 17:37 
QuestionHow to get grid or list view or excell's cell's content? Pin
crystalice543296125-Apr-09 4:42
crystalice543296125-Apr-09 4:42 
AnswerRe: How to get grid or list view or excell's cell's content? Pin
davidbakin2-May-09 17:46
davidbakin2-May-09 17:46 
GeneralRe: How to get grid or list view or excell's cell's content? Pin
crystalice54329612-May-09 18:42
crystalice54329612-May-09 18:42 
AnswerRe: How to get grid or list view or excell's cell's content? Pin
davidbakin2-May-09 19:37
davidbakin2-May-09 19:37 
GeneralRe: How to get grid or list view or excell's cell's content? Pin
crystalice54329612-May-09 19:40
crystalice54329612-May-09 19:40 
GeneralExcellent! Pin
PIEBALDconsult9-Apr-09 16:29
mvePIEBALDconsult9-Apr-09 16:29 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.