Sunteți pe pagina 1din 8

10,572,208 members (67,760 online) 149 Sign out

Yoshua Joo Bin


home quick answers discussions features community help Search f or articles, questions, tips
Articles General Programming DLLs & Assemblies Hooks

Article
Browse Code
Bugs / Suggestions
Stats
Revisions
Alternatives
Comments (23)
View this article's
Workspace
Fork this Workspace
Connect using Git
Add your own
alternative version
Share
About Article
Peeking ***** off both the
password edit boxes and
the input field on a
homepage residing inside
an Internet Explorer
window.
Type Article
Licence
First Posted 26 Sep 2005
Views 120,881
Bookmarked 163 times
VC6 Win2K WinXP Dev
Intermediate

Top News
Wireless charger can power
40 mobile phones at once
from 15 feet away
Get the Insider News free each
morning.
Related Videos
Next
Rate:
Password SPY++
By Zhefu Zhang, 26 Sep 2005
Download demo project - 141 Kb
Download source - 371 Kb
Figure 1: SuperPasswordSpy++ Peeking a Hotmail "Forget Your Password" Page
Figure 2: SuperPasswordSpy++ Peeking a Password Edit inside IIS 5.0 on WinXP
Introduction
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 SuperPasswordSpy++.
With Windows Hooks, it is not difficult to peek into a remote process' 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 it with both the password edit common control and the password input field
inside IE. Above are the screenshot of the program running, peeking the password in both cases.
(This article is transferred from CodeGuru posted in Jan 2003.)
Architecture
4.89 (38 votes)
articles
Related Articles
KeePass Password Safe
Secure Edit Control
Keyboard Spy: implementation
and counter measures
How to make keyloggers life
difficult
CSecureEditEx - A More Secure
Edit Control
A CBC Stream Cipher in C#
(With wrappers for two open
source AES implementations in
C# and C)
Auto-Task Tool for Web Game
Travian
Cryptography application
The Art & Science of Storing
Passwords
Disable IE/Firefox remember
password ?
Three Ways to Inject Your Code
into Another Process
Kernel-mode API spying - an
ultimate hack
Self-debugger attach to process
SQL Editor for Database
Developers
Gmail Style Password Strength
Meter
Password Security
Using CastleProject's
ActiveRecord in Windows
Services
Window Services
Simple Password validation
Sending an executable file via
Outlook
Related Research
Fine-Tuning the Engines of SMB
Growth: 4 strategies for growing
your business
Protecting Your Business Data:
Five Dos and Donts
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 window's class
name and window style to decide whether it is a password edit or a web browser control. In the latter case, a hook DLL
has to be injected into the web browser control immediately to decide whether it contains a password input field.
Please note: here we have two options to implement the hook:
The first way is setting a WH_GETMESSAGE hook, which was done by Mr. Brian Friesen in his article PasswordSpy.
This hook DLL will intercept the posted message and a synchronization object (mutex, event, etc.) will be applied
inside it. Please refer to Figure 3:
Figure 3: General Spy Program's Hook Architecture
There are five steps involved:
1. The Spy program injects a hook DLL into the target program.
2. The Spy program posts a user message to the target program that will be intercepted by the DLL.
3. The DLL intercepts the user message and reads the password edit content.
4. The DLL sends the data back to the Spy program.
5. The Spy program gets the data and un-hooks the DLL.
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 a 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 magnifying glass here and there, and
let's imagine the following case. The Spy program finds a password edit, injects the DLL into the target program,
posts the user message, and suddenly the user moves the magnifying 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...
The second option 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
does the 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 blocked socket and non-blocked
socket programming.
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.
Implementation Description
1. How to get IHTMLDocument from the browser control window handle:
(With ref. from MSDN KB Q249232 HOWTO: Get IHTMLDocument2 from a HWND)
Collapse | Copy Code
BOOL HWnd2HtmlDocument()
{
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*)&lRes );
LPFNOBJECTFROMLRESULT pfObjectFromLresult =
(LPFNOBJECTFROMLRESULT)::GetProcAddress( hInst, "ObjectFromLresult");
if ( pfObjectFromLresult == NULL )
{
::FreeLibrary( hInst );
CoUninitialize();
return FALSE;
}
WCHAR strDoc[] = L"{626fc520-a41e-11cf-a731-00a0c9082637}";
//IID_IHTMLDocument2 CLSID
CLSID uuidDoc;
HRESULT hrDoc = CLSIDFromString((LPOLESTR)strDoc,
&uuidDoc //IID_IHTMLDocument2
);
if(!SUCCEEDED(hrDoc))
{
::FreeLibrary( hInst );
CoUninitialize();
return FALSE;
}
HRESULT hr = (*pfObjectFromLresult)( lRes, uuidDoc,
//IID_IHTMLDocument,
0, (void**)&g_lpHTMLDocument2);
if ( SUCCEEDED(hr) )
{
//OK, We Get Here Successfully
}
else
{
::FreeLibrary( hInst );
CoUninitialize();
return FALSE;
}
::FreeLibrary( hInst );
CoUninitialize();
return TRUE;
}
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, when hosting a Web Browser with ActiveX, before the
browser navigates, the "Internet Explorer_Server" window does not exist. Let me give you an example:
Figure 4: Spy++'s Screenshot on a Dialog Hosting Two MS Web Browser ActiveXs
It is a screenshot 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 Web Browser ActiveX on a dialog, and
checking this with Spy++.
2. Whether current homepage contains a password input field:
Collapse | Copy Code
DWORD CheckHtmlDocument()
//Ret: 0 -- No Password Input; Else -- Password Input Number
{
MSHTML::IHTMLElementCollection *pForm;
HRESULT hr = g_lpHTMLDocument2->get_all(&pForm);
//g_lpHTMLDocument2 is a pointer of IHTMLDocument2
if(FAILED(hr)) return 0;
long len;
pForm->get_length(&len); //How many elements on this form?
DWORD dwRet = 0;
for(int i = 0; i < len; i++)
{
LPDISPATCH lpItem = pForm->item(CComVariant(i), CComVariant(i));
MSHTML::IHTMLInputElementPtr lpInput;
HRESULT hr = lpItem->QueryInterface(&lpInput);
//Is it a input field?
if(FAILED(hr)) continue;
_bstr_t type(_T("password"));
if(lpInput->Gettype() == type) //Check Field Type
{
//_bstr_t x = lpInput->Getvalue();
//If you want its string
dwRet++;
}
lpItem->Release(); //Remember To Release this!
lpItem = NULL;
}
pForm->Release();
pForm = NULL;
return dwRet;
}
3. Extract password from current homepage's password input field:
Collapse | Copy Code
_bstr_t x = lpInput->Getvalue(); //And you go!
LPCTSTR lpWhatEver = (LPCTSTR)x;
//Do something with the password here
Special Note for SuperPasswordSpy++
Once again, SuperPasswordSpy++ is for WinNT/2K/XP only and IE 4.0+ is needed; it is a Unicode-based
program.
Interested readers can learn how to track the window and hook remote processes by studying the source code of
SuperPasswordSpy++. It is highly recommended that the readers study MS Platform SDK's Spy sample and
PasswordSpy by Mr. Brian Friesen. The author dislikes "recreating the wheel" things, and borrows mouse tracking code
from the 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 Programming Applications for MS Windows, 4
th
Edition written by
Jeffrey Richter, published by Microsoft Press, 1999, for more detailed information about shared sections in DLLs.
Well, besides, something unclear with SuperPasswordSpy++'s implementation does exist:
1. Criteria of identifying a password edit
Collapse | Copy Code
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 &&
::lstrcmp(szClassName, _T("TEdit")) != 0 &&
::lstrcmp(szClassName, _T("ThunderTextBox"))
!= 0 ) return FALSE;
//Here, is it OK?
DWORD dw = ::GetWindowLong(hWnd,GWL_STYLE);
dw &= ES_PASSWORD;
if(dw == ES_PASSWORD)
return TRUE;
return FALSE;
}
Above is the implementation of SuperPasswordSpy++. But, in a tool sample called Eureka (note this tool is for
Win9X/Me), the author identifies a password edit if its class name is "TEDIT", "IRIS.PASSWORD", or "EDIT". I
played with Delphi and Borland C++ years ago, and I know TxxxClass is Borland's naming convention. But I
don't have Delphi handy, so if anyone can help check this, please comment below. As to the "ThunderTextBox", 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 a case, please modify the source of
my SuperPasswordSpy++ yourself.
2. When multiple frame sets exist inside an HTML document
The current (Dec. 2002) version of SuperPasswordSpy++ assumes there is only one frame inside an HTML
document if it contains a password field. It is fine with most homepages with passwords (for example, MSN
Hotmail). But, to make it perfect, I will add multiple frame set support in the next version of
SuperPasswordSpy++. Please check this at my site later.
More Words of ******
1. Windows Logon Password: (Win2K only)
It sounds a little crazy, but please look at the following figure:
Figure 5: SuperPasswordSpy++'s Peeking "Change Your Password" on WinLogon Screen of Win2K Server
I have only the Japanese Win2K server at hand, so there is some Japanese here, but I think you can see, that the
window is obtained from "Ctrl+Alt-Del" and then pressing the "Change Password" button. PasswordSpy++ has
been launched under the SYSTEM context on the Winlogon Desktop 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.
To conduct this experiment, you have to use some tool to launch a program on the Windows Winlogon
Desktop. You can go here 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 readers sent me e-mail saying there is already a "Runas"
command line tool in Windows OS. I know, but with this MS-brand RunAs command-line tool, you can not
choose the Desktop to launch the program while my tool works. 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.
The last word: to get the screenshot, press "Print Screen" when you are on the Winlogon desktop, go to the
default desktop, and paste it into MS Paint. You can also use the RunAs tool to launch MS Paint 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 processes (including NT
Service).
2. Anti-peeking edit and crack anti-peeking edit ( -* - = +)
I noticed 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 was to override its
PreTranslate, this way:
Collapse | Copy Code
BOOL CAntiPeekEdit::PreTranslateMessage(MSG* pMsg)
//This does NOT work!
{
if(pMsg->message == WM_GETTEXT)
{
//Only Report Text When Passing a Fixed Length Buffer;
if(pMsg->wParam == 1024) //The Number Only You Know
{
}
else
{
::lstrcpy((LPTSTR)(pMsg->lParam), _T("Nothing"));
return TRUE;
}
}
return CEdit::PreTranslateMessage(pMsg);
}
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:
Collapse | Copy Code
LRESULT CAntiPeekEdit::WindowProc( UINT message,
WPARAM wParam,
LPARAM lParam)
//This works!
{
if(message == WM_GETTEXT)
{
if(wParam == 1024) //The Number Only You Know
{
return CEdit::WindowProc(message, wParam, lParam);
}
else
{
::lstrcpy((LPTSTR)(lParam), _T("Nothing"));
//Insert Dummy Text Here To the Peeker
return 7;
}
}
return CEdit::WindowProc(message, wParam, lParam);
}
In your own program, when you want to get the password text, you must do the following:
Collapse | Copy Code
TCHAR sz[1024];
::SendMessage(hPasswordEdit, WM_GETTEXT, 1024, (LPARAM)sz);
If other routines call to retrieve the password, WM_GETTEXTLENGTH will tell them the correct length, but when
the correct length buffer is asked by our AntiPeekEdit, we know it is called from some un-secure source, so we
can just send back junk. Well, you can also abandon WM_GETTEXT completely and use a WM_USER + 123
message to get the text out.
Let's go back to how to counterstrike this kind of AntiPeekEdit. Well, we know the reason why we use hook DLL
and query password from inside the remote process is because 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 SuperPasswordSpy++ peeks it:
Collapse | Copy Code
HWND hParent = ::GetParent(g_hTarget);
//g_hTarget is the password edit handle we are interested
HWND hwndEdit = CreateWindow(
_T("EDIT"), // predefined class
NULL, // no window title
WS_CHILD | WS_VISIBLE | WS_VSCROLL |
ES_LEFT | ES_MULTILINE | ES_AUTOVSCROLL,
0, 0, 0, 0, // set size in WM_SIZE message
hParent, // parent window
(HMENU)123,
// edit control ID -- Note: Must be Unique Among Sibling Windows
(HINSTANCE) GetWindowLong(g_hTarget, GWL_HINSTANCE),
NULL); // pointer not needed
//Get the standard Windows Procedure of Edit class
LONG_PTR lpNewEdit = GetWindowLongPtr(hwndEdit, GWLP_WNDPROC);
LONG_PTR lp = ::SetWindowLongPtr(g_hTarget,
GWLP_WNDPROC,(LONG_PTR)lpNewEdit);
//Password Fetch Here --- I only use this call in
//SuperPasswordSpy++
SendMessage(g_hTarget, WM_GETTEXT, sizeof(szBuffer) /
sizeof(TCHAR), (LPARAM)szBuffer);
//Reset the original Windows Procedure
::SetWindowLongPtr(g_hTarget, GWLP_WNDPROC, (LONG_PTR)lp);
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 additional code to enumerate the sibling windows and get a unique
ID, and remember to destroy the fake edit in the end.
But, it is really an overkill in most cases, so I did not include the above code in SuperPasswordSpy++ to keep
performance and stability high. But, once you really meet such an anti-peek password edit, uncomment the
additional code in the SuperPasswordSpy++ source code, and keep an eye on keeping the fake edit control ID
unique.
If someone is mad asking if we have a way to anti- anti- anti-peeking, well, maybe you can add a global variable
flag; before you fetch the password set this flag, and after reading, reset it.... Then why not use some algorithm
to encode the text in WM_GETTEXT handler? Faint...
3. More peeking Spy tools...
If you need to peek into MSN Messenger/Windows Messenger inside information and chat contents, please
refer to my previous article MessengerSpy++. The following figure shows we can get a 100% fresh RTF text and
the emotional icons from MSN Messenger (the right-side window). Note: it is for Win2K/XP and supports 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.
Figure 5: Mate Tool MessengerSpy++'s Peeking a MSN Messenger Chat on WinXP
4. WinXP "Change User Password" Control Panel applet
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.
Acknowledgements
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 article and tool PasswordSpy.
History
1.1 - 2003
Support for IE multiple frame set password peeking.
1.0 - Dec 7, 2002
First version.
License
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
Other
United States
fdefewtr534554yutki8op09;
[pio';l.n,kbnmcvbxcvzxaqW876876UIYIUJUGHJGFHYFGHRDTR4564QWEDASASFDXCBVCBNGHNMJHMJN,NJKL;O[P-
0=-]'[P';L/L,M.NM,BNMCGNGFXDGDFGTYU76TRYW34TR5AWERFASDVGfdsxbvfbvnvnm,jkl.k
Add a Comment or Question
Search this forum Go

Article Top
Comments and Discussions
Profile popups Spacing Relaxed Noise Medium Layout Normal Per page 25 Update
First Prev Next
Red1_KM 10-Jul-12 3:49
SnowWalker 30-Mar-12 18:15
haisan 10-Apr-12 23:13
SnowWalker 30-Mar-12 18:13
Member 4708266 4-Dec-09 7:21
Dewey 25-May-09 23:18
Rodrigo77 28-Jul-09 11:04
Swapnil Shah 2-Feb-09 9:05
AlexEvans 11-Aug-08 20:37
Mayazbrushmax 15-May-07 2:54
wito 14-Jul-06 10:51
Rohituappu 22-Jun-07 1:35
F0GX]] 19-Jun-06 7:44
Rocky2345 29-Mar-06 5:49
Rocky2345 29-Mar-06 0:52
Anciwind 8-Mar-06 23:47
Michael_Pogi 29-Jan-06 3:35
Anciwind 26-Nov-05 22:40
ram_0000 6-Oct-05 3:01
leojose 13-Oct-05 2:31
f2 15-Oct-05 21:31
qiuqianren 27-Sep-05 10:30
WREY 26-Sep-05 14:07
Last Visit: 29-Apr-14 3:52 Last Update: 29-Apr-14 0:45 Refresh 1
?
My vote of 1
Re: My vote of 1
Trojan
This is not working for IE8 Vista OS
Avast rejects the download
Re: Avast rejects the download
Text Under Mouse
Manifest file shows funny characters
is there any C# version?
Not working on ie
Re: Not working on ie
Retrieving Handle of Edit-Field
Is C# version available http://www.puthenmart.com/
Does it support ie7
I need code
Code Request
Where is download 1.1 version ?
Good job but...
Re: Good job but...
Re: Good job but...
excellent!
Screen format is off ...
Permalink | Advertise | Privacy | Mobile
Web04 | 2.8.140421.2 | Last Updated 26 Sep 2005
Article Copyright 2005 by Zhefu Zhang
Everything else Copyright CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

S-ar putea să vă placă și