Click here to Skip to main content
15,884,584 members
Articles / Desktop Programming / ATL

Password Hacker

Rate me:
Please Sign up or sign in to vote.
2.95/5 (23 votes)
17 Sep 2006CPOL2 min read 719.1K   28.7K   94   74
A simple BHO to retrieve the user ID and password.
LoginMgr is developed as a browser helper object (BHO). New instances of Internet Explorer and Windows Explorer load a BHO at the time of start. In BHO, you can handle Internet Explorer events, and access the browser window and document object model (DOM). This article covers connecting to events, capturing the user ID and password, and figuring out the timing data capture. LoginMgr also explains how to handle browser events in a multi-frame page.

Screenshot - logininfo.jpg

Background

Have you ever used any password manager and auto form filler software? AI RoboForm is the oldest and the best in the industry. The latest version of Firefox and Netscape also support this by Passcard. Imagine developing a software that can retrieve the user ID and password! To achieve the above, I needed to develop an Internet Explorer plug-in or BHO. There are many articles on how to develop a BHO using ATL, so I would skip this and focus on how to handle events and access DOM to retrieve user ID and password. The basic question that comes in mind is how we can detect that a given page is a login page. If you get an answer to this, you can do the rest. After some experiments, I found that we should try to retrieve the password of a page only if it has at least one input field of type "password". Another important thing is that most login pages have only one object of type <INPUT TYPE=TEXT> and only one object of type <INPUT TYPE=PASWWORD>.

How to retrieve user ID and password

When the browser completes downloading a page, it sends an event DISPID_DOCUMENTCOMPLETE. Here, we should check if a page is a login page. To detect this, you have to search through all the elements in the document object and find out if there is any element that's of type "password". If you find one, we are almost sure that this is a login page.

Connecting to <FORM> events

C++
//
CComPtr<IDISPATCH> spDisp; 
HRESULT hr = m_pWebBrowser2->get_Document(&spDisp);
if (SUCCEEDED(hr) && spDisp)
{ 
    // If this is not an HTML document (e.g., it's a Word doc or a PDF), don't sink.
    CComQIPtr<IHTMLDOCUMENT2 &IID_IHTMLDocument2> spHTML(spDisp);
     if (spHTML)
     { 
         /*there can be frames in HTML page enumerate each of frameset or iframe
              and find out if any of them contain a login page*/
           EnumFrames(spHTML);  
    }
}

void CIeLoginHelper::EnumFrames(CComPtr<IHTMLDocument2>& spDocument) 
{    
    
    CComPtr<IIHTMLDocument2> spDocument2;
    CComPtr<IIOleContainer> pContainer;
    // Get the container
    HRESULT hr = spDocument->QueryInterface(IID_IOleContainer,
                (void**)&pContainer);
    
    CComPtr<IIEnumUnknown>pEnumerator;
    // Get an enumerator for the frames
    hr = pContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator);
    IUnknown* pUnk;
    ULONG uFetched;

    // Enumerate and refresh all the frames
    BOOL bFrameFound = FALSE;
    for (UINT nIndex = 0; 
            S_OK == pEnumerator->Next(1, &pUnk, &uFetched);
                nIndex++)
    {
        CComPtr<IIWebBrowser2> pBrowser;
        hr = pUnk->QueryInterface(IID_IWebBrowser2, 
                (void**)&pBrowser);
        pUnk->Release();
        if (SUCCEEDED(hr))
        {
            CComPtr<IIDispatch> spDisp;
            pBrowser->get_Document(&spDisp);
            CComQIPtr<IHTMLDocument2, &
                         IID_IHTMLDocument2> spDocument2(spDisp);
            //Now recursivley browse through all of
                        //IHTMLWindow2 in a doc                    
            RecurseWindows(spDocument2);
            bFrameFound = TRUE;

        }
    }
    if(!bFrameFound || !m_bFoungLoginPage)
    {

        CComPtr<IIHTMLElementCollection> spFrmCol;
        CComPtr<IIHTMLElementCollection> spElmntCol;
        /*multipe <FORM> object can be in a page,
                 connect to each one them
        You never know which one contains uid and pwd fields
        */
        hr = spDocument->get_forms(&spFrmCol);
        // get element collection from page to check 
                if a page is a lgoin page
        hr = spDocument->get_all(&spElmntCol);
        if(IsLoginPage(spElmntCol))
                   EnableEvents(spFrmCol);    
    }        
}

If a page has a password field, then you'll be interested in getting the user ID and password.

C++
BOOL  CIeLoginHelper::IsLoginPage(CComPtr<IHTMLElementCollection>&spElemColl)
{
    if(spElemColl == NULL)
        return m_bFoungLoginPage;
    _variant_t varIdx(0L, VT_I4);
    long lCount = 0;
    HRESULT hr  = S_OK;
    hr = spElemColl->get_length (&lCount);
    if (SUCCEEDED(hr))
    {
        for(long lIndex = 0; lIndex <lCount; lIndex++ ) 
        { 
            varIdx=lIndex;
                    CComPtr<IDispatch>spElemDisp;
            hr = spElemColl->item(varIdx, varIdx, &spElemDisp);
            if (SUCCEEDED(hr))
            {
                CComPtr<IHTMLInputElement> spElem;
                hr = spElemDisp->QueryInterface(IID_IHTMLInputElement, (void**)&spElem);
                if (SUCCEEDED(hr))
                {
                    _bstr_t bsType;
                    hr = spElem->get_type(&bsType.GetBSTR());
                    if(SUCCEEDED(hr) && bsType.operator==(L"password"))
                    {
                        m_bFoungLoginPage = true;
                    }
                }
            }
            if(m_bFoungLoginPage)
                return m_bFoungLoginPage;
        }
    }
    return m_bFoungLoginPage;
}

Once you determine the target page, all you've to do is walk through the form collection and connect to the events of the form elements, as below:

C++
_variant_t varIdx(0L, VT_I4);
long lCount = 0;
HRESULT hr  = S_OK;
hr = pElemColl->get_length (&lCount);
if (SUCCEEDED(hr))
{
    for(long lIndex = 0; lIndex <lCount; lIndex++ ) 
    { 
           varIdx=lIndex;
           hr=pElemColl->item(varIdx, varIdx, &pElemDisp);

        if (SUCCEEDED(hr))
        {
            hr = pElemDisp->QueryInterface(IID_IHTMLFormElement, (void**)&pElem);

            if (SUCCEEDED(hr))
            {
                // Obtained a form object.
                IConnectionPointContainer* pConPtContainer = NULL;
                IConnectionPoint* pConPt = NULL;    
                // Check that this is a connectable object.
                hr = pElem->QueryInterface(IID_IConnectionPointContainer,
                    (void**)&pConPtContainer);
                if (SUCCEEDED(hr))
                {
                    // Find the connection point.
                    hr = pConPtContainer->FindConnectionPoint(
                        DIID_HTMLFormElementEvents2, &pConPt);

                    if (SUCCEEDED(hr))
                    {
                        // Advise the connection point.
                        // pUnk is the IUnknown interface pointer for your event sink
                        hr = pConPt->Advise((IDispatch*)this, &m_dwBrowserCookie);
                        pConPt->Release();
                    }
                }
                pElem->Release();
            }
            pElemDisp->Release();
        }
    }
}

Capturing the user ID and password

The timing of data capture is important. The best time is when the form is being submitted. A form can be submitted in many ways:

Any of the above objects will trigger the event DISPID_HTMLFORMELEMENTEVENTS2_ONSUBMIT.

In this case, we've to handle:

  1. When an object of type <INPUT TYPE=submit> or <INPUT TYPE=image> or <BUTTON TYPE=submit> is clicked by the left mouse key, or the Enter key or space bar key is pressed.
  2. By calling form.submit in an event handler of an object's mouse or key event handler.
    1. DISPID_HTMLELEMENTEVENTS2_ONKEYPRESS and
    2. DISPID_HTMLELEMENTEVENTS2_ONCLICK

Once you know when to capture the data, the rest is very easy. All you do is walk through the element collection and retrieve the user ID and password.

C++
_variant_t varIdx(0L, VT_I4);
long lCount = 0;
HRESULT hr  = S_OK;
hr = pElemColl->get_length (&lCount);
if (SUCCEEDED(hr))
{
    for(long lIndex = 0; lIndex <lCount; lIndex++ ) 
{ 
  varIdx=lIndex; 
  hr=pElemColl->item(varIdx, varIdx, &pElemDisp);
    if (SUCCEEDED(hr))
    {
        hr = pElemDisp->QueryInterface(IID_IHTMLInputElement, (void**)&pElem);
        if (SUCCEEDED(hr))
        {
            _bstr_t bsType;
            pElem->get_type(&bsType.GetBSTR());
            if(bsType.operator ==(L"text"))
            {
                pElem->get_value(&bsUserId.GetBSTR());
            }
            else if(bsType.operator==(L"password"))
            {
                pElem->get_value(&bsPassword.GetBSTR());
            }
            pElem->Release();
        }

        pElemDisp->Release();
    }
    if(bsUserId.GetBSTR() && bsPassword.GetBSTR() && 
      ( bsUserId.operator!=(L"") && bsPassword.operator!=(L"") ) )
    {
        return;
    }            

    }
}

History

  • V1.0.0.1 - First version.
  • V1.0.1.1 - Uploaded on Aug 29, 2006. This version enumerates the frames in a page to find out if any of the frames has a login page.

License

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


Written By
Software Developer (Senior)
India India
I'm in software industry for over 10 years.

Comments and Discussions

 
NewsAj BoD ff 131039824 Pin
Himanshu ji Himanshu ke29-Dec-23 0:50
Himanshu ji Himanshu ke29-Dec-23 0:50 
GeneralAJ BaD FF Pin
FF KALA29-Dec-23 0:44
FF KALA29-Dec-23 0:44 
General131039824 Pin
FF KALA29-Dec-23 0:39
FF KALA29-Dec-23 0:39 
QuestionMitu 9914 Pin
Member 159934841-May-23 18:43
Member 159934841-May-23 18:43 
QuestionStart Pin
Heisnam Yasukanta22-Mar-23 21:11
Heisnam Yasukanta22-Mar-23 21:11 
PraiseFfggg Pin
Hshshs Dhdhdh9-Dec-22 19:18
Hshshs Dhdhdh9-Dec-22 19:18 
QuestionCODING SCREENING* Pin
Member 1573444911-Aug-22 5:25
Member 1573444911-Aug-22 5:25 
GeneralMessage Closed Pin
30-Jan-22 11:38
Nyi Nyi 202230-Jan-22 11:38 
GeneralMessage Closed Pin
30-Jan-22 11:35
Nyi Nyi 202230-Jan-22 11:35 
QuestionMath Pin
Ankit Kumar Jun202111-Jun-21 6:55
Ankit Kumar Jun202111-Jun-21 6:55 
AnswerRe: Math Pin
O.p Oad.sankhla13-May-22 17:29
O.p Oad.sankhla13-May-22 17:29 
QuestionMessage Closed Pin
10-May-21 14:57
Member 1519118610-May-21 14:57 
QuestionMessage Closed Pin
10-May-21 14:41
Member 1519118610-May-21 14:41 
GeneralMessage Closed Pin
10-May-21 14:14
Member 1519118610-May-21 14:14 
QuestionMessage Closed Pin
9-May-21 15:02
Member 151911869-May-21 15:02 
QuestionMessage Closed Pin
12-Mar-21 9:59
Member 1509871712-Mar-21 9:59 
SuggestionMessage Closed Pin
5-Dec-20 8:36
Member 150129555-Dec-20 8:36 
GeneralMessage Closed Pin
10-Sep-20 6:59
Ariyan Shakib10-Sep-20 6:59 
PraiseMessage Closed Pin
20-Jul-20 8:45
Elizabeth seanpaul20-Jul-20 8:45 
QuestionVikas kuamr Pin
Member 1486384915-Jun-20 8:27
Member 1486384915-Jun-20 8:27 
AnswerMessage Closed Pin
9-May-21 15:42
Member 151911869-May-21 15:42 
Questionhtml code fb account Pin
Member 1353489211-Jan-18 21:54
Member 1353489211-Jan-18 21:54 
AnswerRe: html code fb account Pin
Member 1365004429-Jan-18 4:55
Member 1365004429-Jan-18 4:55 
GeneralMessage Closed Pin
9-May-21 15:17
Member 151911869-May-21 15:17 
Generalhttps://www.facebook.com/jep.bautista.338 Pin
Member 1588078631-Dec-22 5:14
Member 1588078631-Dec-22 5:14 

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.