You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
449 lines
13 KiB
449 lines
13 KiB
#include <common.h>
|
|
|
|
extern BOOL g_QuietMode;
|
|
extern WCHAR g_TempString[];
|
|
extern WCHAR g_ErrorString[];
|
|
extern WCHAR g_FailureLocation[];
|
|
|
|
extern BOOL g_RemoteOperation;
|
|
extern WCHAR g_RemoteComputerName[];
|
|
extern BOOL g_CheckNT4Also;
|
|
|
|
|
|
|
|
VOID
|
|
DisplayMessage(
|
|
WCHAR *MessageText)
|
|
{
|
|
if (!g_QuietMode) {
|
|
wprintf(L"%s", MessageText);
|
|
}
|
|
}
|
|
|
|
WCHAR*
|
|
GetErrorString(
|
|
DWORD dwErrorCode)
|
|
{
|
|
LPVOID lpMsgBuf=NULL;
|
|
ZeroMemory(g_ErrorString, MAX_STRING * sizeof(WCHAR));
|
|
|
|
FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER |
|
|
FORMAT_MESSAGE_FROM_SYSTEM |
|
|
FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
dwErrorCode,
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR) &lpMsgBuf,
|
|
0,
|
|
NULL);
|
|
|
|
// Free the bufferoa
|
|
if (lpMsgBuf != NULL) {
|
|
wcscpy(g_ErrorString, lpMsgBuf);
|
|
LocalFree(lpMsgBuf);
|
|
}
|
|
return g_ErrorString;
|
|
}
|
|
|
|
|
|
|
|
//+---------------------------------------------------------------------------------------------------------
|
|
//
|
|
// Registry munging routines
|
|
//
|
|
//+---------------------------------------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
GetRegValueSZ(
|
|
WCHAR *ValueName,
|
|
WCHAR *RegValue)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
HKEY hKey=NULL;
|
|
DWORD dwMaxValueData = (MAX_STRING * sizeof(WCHAR)); // Longest Value data
|
|
HANDLE hHeap=NULL;
|
|
BYTE *bData=NULL;
|
|
DWORD cbData;
|
|
DWORD dwType;
|
|
|
|
// ZeroMemory(RegValue, MAX_STRING * sizeof(WCHAR));
|
|
|
|
// get a handle to the local or remote computer
|
|
// (as specified by our global flag)
|
|
dwRetCode = GetRegistryHandle(&hKey, KEY_READ);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
goto cleanup;
|
|
}
|
|
|
|
// create a heap
|
|
hHeap = HeapCreate(0, 0, 0);
|
|
if (hHeap == NULL) {
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
wsprintf(g_FailureLocation, L"GetRegValueSZ: HeapCreate: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
// allocate some space on the heap for our regvalue we'll read in
|
|
bData = (BYTE*)HeapAlloc(hHeap, 0, dwMaxValueData);
|
|
if (bData == NULL) {
|
|
dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
|
|
wsprintf(g_FailureLocation, L"GetRegValueSZ: HeapAlloc: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
cbData = dwMaxValueData;
|
|
|
|
// read the regkey using the handle we open above
|
|
dwRetCode = RegQueryValueEx(
|
|
hKey,
|
|
ValueName,
|
|
NULL,
|
|
&dwType,
|
|
bData,
|
|
&cbData);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"GetRegValueSZ: RegQueryValueEx: %s", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
// if it's not a type reg_sz, then something's wrong, so
|
|
// report the error, which will cause us to stop.
|
|
if (dwType != REG_SZ) {
|
|
dwRetCode = ERROR_BADKEY;
|
|
wsprintf(g_FailureLocation, L"GetRegValueSZ: RegQueryValueEx: %s: %s\n", ValueName, GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
// copy the buffer to the registry value
|
|
wcsncpy(RegValue, (WCHAR *)bData, cbData * sizeof(WCHAR));
|
|
|
|
cleanup:
|
|
if (bData != NULL) {
|
|
ZeroMemory(bData, sizeof(bData));
|
|
if (hHeap != NULL) {
|
|
HeapFree(hHeap, 0, bData);
|
|
HeapDestroy(hHeap);
|
|
}
|
|
}
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
ClearRegPassword()
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
HKEY hKey=NULL;
|
|
|
|
dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = RegDeleteValue(hKey, L"DefaultPassword");
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"ClearRegPassword: RegDeleteValue: %s\n", GetErrorString(dwRetCode));
|
|
// DisplayMessage(g_TempString);
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
SetRegValueSZ(
|
|
WCHAR *ValueName,
|
|
WCHAR *ValueData)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
HKEY hKey=NULL;
|
|
|
|
dwRetCode = GetRegistryHandle(&hKey, KEY_WRITE);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
goto cleanup;
|
|
}
|
|
|
|
dwRetCode = RegSetValueEx(
|
|
hKey,
|
|
ValueName,
|
|
0,
|
|
REG_SZ,
|
|
(LPSTR) ValueData,
|
|
wcslen(ValueData)*sizeof(WCHAR));
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"SetRegValueSZ: RegSetValueEx: %s: %s\n", ValueName, GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
if (hKey != NULL) {
|
|
RegCloseKey(hKey);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetRegistryHandle(
|
|
HKEY *phKey,
|
|
REGSAM samDesired)
|
|
{
|
|
HKEY RemoteRegistryHandle=NULL;
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
//
|
|
// If not PRIVATE mode, ignore the access requested passed in and
|
|
// request all access, even though we don't need it. This will force the
|
|
// caller to need to be admin to use this tool. We don't want someone using
|
|
// this tool to view the autologon passwords of all machines across the domain
|
|
// as a normal domain user...
|
|
//
|
|
#ifndef PRIVATE_VERSION
|
|
samDesired = KEY_ALL_ACCESS;
|
|
#endif
|
|
//
|
|
// If we're connecting against a remote computer
|
|
//
|
|
if (g_RemoteOperation) {
|
|
// open a handle to the remote registry
|
|
dwRetCode = RegConnectRegistry(
|
|
g_RemoteComputerName,
|
|
HKEY_LOCAL_MACHINE,
|
|
&RemoteRegistryHandle);
|
|
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"GetRegistryHandle: RegConnectRegistry: %s: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
// open the WINLOGON key on the remote machine
|
|
dwRetCode = RegOpenKeyEx(
|
|
RemoteRegistryHandle,
|
|
WINLOGON_REGKEY,
|
|
0,
|
|
samDesired,
|
|
phKey);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"GetRegistryHandle: RegOpenKeyEx: %s: %s\n", g_RemoteComputerName, GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
} else {
|
|
// open the WINLOGON key on the local machine
|
|
dwRetCode = RegOpenKeyEx(
|
|
HKEY_LOCAL_MACHINE,
|
|
WINLOGON_REGKEY,
|
|
0,
|
|
samDesired,
|
|
phKey);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
wsprintf(g_FailureLocation, L"GetRegistryHandle: RegOpenKeyEx: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (RemoteRegistryHandle != NULL) {
|
|
RegCloseKey(RemoteRegistryHandle);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
//+---------------------------------------------------------------------------------------------------------
|
|
//
|
|
// LSASecret munging routines
|
|
//
|
|
//+---------------------------------------------------------------------------------------------------------
|
|
|
|
DWORD
|
|
GetPolicyHandle(LSA_HANDLE *LsaPolicyHandle)
|
|
{
|
|
LSA_OBJECT_ATTRIBUTES ObjectAttributes;
|
|
NTSTATUS ntsResult;
|
|
LSA_UNICODE_STRING TargetMachine;
|
|
USHORT TargetMachineLength;
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
|
|
// Object attributes are reserved, so initialize to zeroes.
|
|
ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
|
|
|
|
if (g_RemoteOperation) {
|
|
//Initialize an LSA_UNICODE_STRING
|
|
TargetMachineLength = (USHORT)wcslen(g_RemoteComputerName);
|
|
TargetMachine.Buffer = g_RemoteComputerName;
|
|
TargetMachine.Length = TargetMachineLength * sizeof(WCHAR);
|
|
TargetMachine.MaximumLength = (TargetMachineLength+1) * sizeof(WCHAR);
|
|
|
|
// Get a handle to the Policy object.
|
|
ntsResult = LsaOpenPolicy(
|
|
&TargetMachine, //local machine
|
|
&ObjectAttributes,
|
|
POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
|
|
LsaPolicyHandle);
|
|
|
|
} else {
|
|
// Get a handle to the Policy object.
|
|
ntsResult = LsaOpenPolicy(
|
|
NULL, //local machine
|
|
&ObjectAttributes,
|
|
POLICY_CREATE_SECRET | POLICY_GET_PRIVATE_INFORMATION,
|
|
LsaPolicyHandle);
|
|
}
|
|
|
|
if (ntsResult != STATUS_SUCCESS)
|
|
{
|
|
// An error occurred. Display it as a win32 error code.
|
|
dwRetCode = LsaNtStatusToWinError(ntsResult);
|
|
wsprintf(g_FailureLocation, L"GetPolicyHandle: LsaOpenPolicy: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
cleanup:
|
|
return dwRetCode;
|
|
|
|
}
|
|
|
|
DWORD
|
|
SetSecret(
|
|
WCHAR *Password,
|
|
BOOL bClearSecret)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
NTSTATUS ntsResult;
|
|
USHORT SecretNameLength, SecretDataLength;
|
|
LSA_HANDLE LsaPolicyHandle=NULL;
|
|
LSA_UNICODE_STRING lusSecretName, lusSecretData;
|
|
|
|
//Initialize an LSA_UNICODE_STRING
|
|
SecretNameLength = (USHORT)wcslen(L"DefaultPassword");
|
|
lusSecretName.Buffer = L"DefaultPassword";
|
|
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
|
|
lusSecretName.MaximumLength = (SecretNameLength+1) * sizeof(WCHAR);
|
|
|
|
dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
goto cleanup;
|
|
}
|
|
|
|
// if bClearSecret is set, then delete the secret
|
|
// otherwise set the secret to Password
|
|
if (bClearSecret) {
|
|
ntsResult = LsaStorePrivateData(
|
|
LsaPolicyHandle,
|
|
&lusSecretName,
|
|
NULL);
|
|
if (ntsResult != STATUS_SUCCESS) {
|
|
dwRetCode = LsaNtStatusToWinError(ntsResult);
|
|
wsprintf(g_FailureLocation, L"SetSecret: LsaStorePrivateData: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
|
|
} else {
|
|
//Initialize the Password LSA_UNICODE_STRING
|
|
SecretDataLength = (USHORT)wcslen(Password);
|
|
lusSecretData.Buffer = Password;
|
|
lusSecretData.Length = SecretDataLength * sizeof(WCHAR);
|
|
lusSecretData.MaximumLength = (SecretDataLength+1) * sizeof(WCHAR);
|
|
|
|
ntsResult = LsaStorePrivateData(
|
|
LsaPolicyHandle,
|
|
&lusSecretName,
|
|
&lusSecretData);
|
|
if (ntsResult != STATUS_SUCCESS) {
|
|
dwRetCode = LsaNtStatusToWinError(ntsResult);
|
|
wsprintf(g_FailureLocation, L"SetSecret: LsaStorePrivateData: %s\n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
cleanup:
|
|
if (LsaPolicyHandle != NULL) {
|
|
LsaClose(LsaPolicyHandle);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
DWORD
|
|
GetSecret(
|
|
WCHAR *Password)
|
|
{
|
|
DWORD dwRetCode = ERROR_SUCCESS;
|
|
NTSTATUS ntsResult;
|
|
USHORT SecretNameLength;
|
|
LSA_HANDLE LsaPolicyHandle=NULL;
|
|
LSA_UNICODE_STRING lusSecretName;
|
|
LSA_UNICODE_STRING *PrivateData=NULL;
|
|
|
|
//Initialize an LSA_UNICODE_STRING
|
|
SecretNameLength = (USHORT)wcslen(L"DefaultPassword");
|
|
lusSecretName.Buffer = L"DefaultPassword";
|
|
lusSecretName.Length = SecretNameLength * sizeof(WCHAR);
|
|
lusSecretName.MaximumLength= (SecretNameLength+1) * sizeof(WCHAR);
|
|
|
|
dwRetCode = GetPolicyHandle(&LsaPolicyHandle);
|
|
if (dwRetCode != ERROR_SUCCESS) {
|
|
goto cleanup;
|
|
}
|
|
|
|
ntsResult = LsaRetrievePrivateData(
|
|
LsaPolicyHandle,
|
|
&lusSecretName,
|
|
&PrivateData);
|
|
|
|
if (ntsResult != STATUS_SUCCESS) {
|
|
if (ntsResult == STATUS_OBJECT_NAME_NOT_FOUND) {
|
|
return ntsResult;
|
|
} else {
|
|
dwRetCode = LsaNtStatusToWinError(ntsResult);
|
|
wsprintf(g_FailureLocation, L"GetSecret: LsaRetrievePrivateData: %s \n", GetErrorString(dwRetCode));
|
|
goto cleanup;
|
|
}
|
|
}
|
|
|
|
// copy the buffer data to Password
|
|
wcsncpy(Password, PrivateData->Buffer, (PrivateData->Length)/sizeof(WCHAR));
|
|
|
|
cleanup:
|
|
if (PrivateData != NULL) {
|
|
ZeroMemory(PrivateData->Buffer, PrivateData->Length);
|
|
LsaFreeMemory(PrivateData);
|
|
}
|
|
if (LsaPolicyHandle != NULL) {
|
|
LsaClose(LsaPolicyHandle);
|
|
}
|
|
return dwRetCode;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
GetMajorNTVersion(
|
|
WCHAR *Server)
|
|
{
|
|
SERVER_INFO_101* pInf;
|
|
DWORD ver = 0;
|
|
|
|
if(!NetServerGetInfo(Server, 101, (BYTE**)&pInf))
|
|
{
|
|
if(pInf->sv101_platform_id == PLATFORM_ID_NT) {
|
|
ver = pInf->sv101_version_major;
|
|
} else {
|
|
ver = 0;
|
|
}
|
|
NetApiBufferFree(pInf);
|
|
} else {
|
|
ver = 0;
|
|
}
|
|
|
|
return ver;
|
|
}
|