diff --git a/Build/WinPriv-hash.txt b/Build/WinPriv-hash.txt index 786f491..93c8841 100644 --- a/Build/WinPriv-hash.txt +++ b/Build/WinPriv-hash.txt @@ -1,30 +1,30 @@ Algorithm Hash Path --------- ---- ---- -SHA256 1F3D88165DE705F833C080F7BAD3EC8013854EE5BA1DD5CA86152104F0014F82 x64\WinPriv.exe -SHA256 E22303994A24F0B7C74426E3223CB114E6F885FCCCE451188E65F71132AC60AA x64\WinPrivCmd.exe -SHA256 F07FD74C808DF528149B978F6C2EDEF16F2D993F9DFD70AD8EEF6C9B97398291 x86\WinPriv.exe -SHA256 2F382647FF587B7C70BE9C73FDA25AF7CA5DE149C55877D2FBE1CB8BD1A4C6B8 x86\WinPrivCmd.exe -SHA256 34AE925B652BFA03A36BFD728C0EC9C429C60A5C0E5C21F4351798C3DB0EC865 WinPriv.zip +SHA256 447B8774DA7E9B83EDED50C2EA5C64C0973669D543FC51DAC03B07F3BF5644BD x64\WinPriv.exe +SHA256 1EE798FFBD84142B46B209D569EA30210930B994C1F9173328A08187E9C3C36C x64\WinPrivCmd.exe +SHA256 6EAB565F15B8D140A7BB690D26E4EE4AA8B792E7D288B1CC10CA0E41BE81D63D x86\WinPriv.exe +SHA256 F4BF456304DD40488B4DF4FAA395F942BC809ECCD9BB73B51461EE02F740EACC x86\WinPrivCmd.exe +SHA256 8D05DD4B4A2F5CAD17DDC3862CA757AF53CF8728CA0996EE3B57D6E9C4E67833 WinPriv.zip Algorithm Hash Path --------- ---- ---- -SHA1 A8EB525CEDF7AE340E178DA07ABADA9A735197A3 x64\WinPriv.exe -SHA1 B85A571643186788662F6C6FE04F4A458F5C42B7 x64\WinPrivCmd.exe -SHA1 6691DCA6E3691AC777A4224DF7E11BB60114AFC1 x86\WinPriv.exe -SHA1 8A4DBB4700D7B712EB319C350E06A423FAB320FE x86\WinPrivCmd.exe -SHA1 BA0B0BD31DBCEA8D00016305B95C233EB11358E2 WinPriv.zip +SHA1 81F9ECB11140D275C6C75D3AB16179524145FE27 x64\WinPriv.exe +SHA1 4514E1FF080F8A727080750217A465A29C34C720 x64\WinPrivCmd.exe +SHA1 2CDDC34CC839D2D7408243F8AD9C04D5D90E8F5F x86\WinPriv.exe +SHA1 9AFFC6F7BC311B4B3E7A3934C72CE64845DD19D0 x86\WinPrivCmd.exe +SHA1 361FCB0645B22A260C2C36931AF1BF6EF661DF8A WinPriv.zip Algorithm Hash Path --------- ---- ---- -MD5 438A11FEF70928ECC17BFCF8E2155CE2 x64\WinPriv.exe -MD5 04B3CD0192FA339AA3D8E8FDE1F3C3D6 x64\WinPrivCmd.exe -MD5 91E669F6CD5236D7565447F755E78A48 x86\WinPriv.exe -MD5 1758F6A17B569F76B4E6F4AE3F1D113F x86\WinPrivCmd.exe -MD5 225D18F69E1252A4E9F07B2B557E0785 WinPriv.zip +MD5 BDEE609386160B8B402801785B775863 x64\WinPriv.exe +MD5 150C87455D0037BAC4955C1C54F40335 x64\WinPrivCmd.exe +MD5 C6862E5B65950D9326AD59D16A4CA0FB x86\WinPriv.exe +MD5 2BD2E18E8EC664484BC4265006D5736C x86\WinPrivCmd.exe +MD5 6B3BF0A247FE34BC5EE58707CEB0340D WinPriv.zip diff --git a/Build/WinPriv.zip b/Build/WinPriv.zip index f089e8c..ea0c48a 100644 Binary files a/Build/WinPriv.zip and b/Build/WinPriv.zip differ diff --git a/Build/x64/WinPriv.exe b/Build/x64/WinPriv.exe index c04a596..7b38b12 100644 Binary files a/Build/x64/WinPriv.exe and b/Build/x64/WinPriv.exe differ diff --git a/Build/x64/WinPrivCmd.exe b/Build/x64/WinPrivCmd.exe index 02f9439..faa2c23 100644 Binary files a/Build/x64/WinPrivCmd.exe and b/Build/x64/WinPrivCmd.exe differ diff --git a/Build/x86/WinPriv.exe b/Build/x86/WinPriv.exe index a9fbbff..ed7ce93 100644 Binary files a/Build/x86/WinPriv.exe and b/Build/x86/WinPriv.exe differ diff --git a/Build/x86/WinPrivCmd.exe b/Build/x86/WinPrivCmd.exe index 0f65ad2..4490af2 100644 Binary files a/Build/x86/WinPrivCmd.exe and b/Build/x86/WinPrivCmd.exe differ diff --git a/WinPriv/WinPrivResource.rc b/WinPriv/WinPrivResource.rc index 3fbb523..32b4fda 100644 Binary files a/WinPriv/WinPrivResource.rc and b/WinPriv/WinPrivResource.rc differ diff --git a/WinPrivLibrary/WinPrivLibraryDetours.cpp b/WinPrivLibrary/WinPrivLibraryDetours.cpp index d4ed617..e34bba6 100644 --- a/WinPrivLibrary/WinPrivLibraryDetours.cpp +++ b/WinPrivLibrary/WinPrivLibraryDetours.cpp @@ -24,6 +24,8 @@ #include "WinPrivShared.h" #include "WinPrivLibrary.h" +#define sizereq(x,y) (offsetof(x,y) + sizeof(((x*) NULL)->y)) +#define align(x,y) ((((uintptr_t) (x)) + (((y)/CHAR_BIT)-1)) & ~(((y)/CHAR_BIT)-1)) // ___ ___ __ __ ___ // |__ | | |__ / \ |__) |__ |\ | // | | |___ |___ \__/ | |___ | \| @@ -125,25 +127,32 @@ EXTERN_C NTSTATUS WINAPI DetourNtQueryValueKey(_In_ HANDLE KeyHandle, if (tInterceptInfo->RegKeyName.Length == NULL) break; // fetch value name - LPWSTR sValueName = sParams[1]; + LPWSTR sValueName = sParams[iParam + 1]; tInterceptInfo->RegValueName = { (USHORT)wcslen(sValueName) * sizeof(WCHAR), (USHORT)wcslen(sValueName) * sizeof(WCHAR), _wcsdup(sValueName) }; // match the aesthetic types to the typed enumerations - LPWSTR sType = sParams[2]; + LPWSTR sType = sParams[iParam + 2]; if (_wcsicmp(sType, L"REG_DWORD") == 0) tInterceptInfo->RegValueType = REG_DWORD; + else if (_wcsicmp(sType, L"REG_QWORD") == 0) tInterceptInfo->RegValueType = REG_QWORD; else if (_wcsicmp(sType, L"REG_SZ") == 0) tInterceptInfo->RegValueType = REG_SZ; else if (_wcsicmp(sType, L"REG_BLOCK") == 0) tInterceptInfo->RegValueType = -1; else break; // decode the value string to a data blob - LPWSTR sData = sParams[3]; + LPWSTR sData = sParams[iParam + 3]; if (tInterceptInfo->RegValueType == REG_DWORD) { tInterceptInfo->RegValueData = (DWORD *)malloc(sizeof(DWORD)); - swscanf(sData, L"%lu", (DWORD *)tInterceptInfo->RegValueData); + swscanf(sData, L"%li", (DWORD *)tInterceptInfo->RegValueData); tInterceptInfo->RegValueDataSize = sizeof(DWORD); } + else if (tInterceptInfo->RegValueType == REG_QWORD) + { + tInterceptInfo->RegValueData = (unsigned __int64 *)malloc(sizeof(unsigned __int64)); + swscanf(sData, L"%lli", (unsigned __int64 *)tInterceptInfo->RegValueData); + tInterceptInfo->RegValueDataSize = sizeof(unsigned __int64); + } else if (tInterceptInfo->RegValueType == REG_SZ) { tInterceptInfo->RegValueData = sData; @@ -179,7 +188,7 @@ EXTERN_C NTSTATUS WINAPI DetourNtQueryValueKey(_In_ HANDLE KeyHandle, // allocate space for name and lookup NTSTATUS iStatus = -1; PKEY_NAME_INFORMATION pNameInfo = (PKEY_NAME_INFORMATION)malloc(iKeyNameSize); - if (pNameInfo != NULL && NtQueryKey(KeyHandle, KeyNameInformation, pNameInfo, + if (pNameInfo != NULL && NtQueryKey(KeyHandle, KeyNameInformation, pNameInfo, iKeyNameSize, &iKeyNameSize) == STATUS_SUCCESS) { // convert to unicode string structure for quick comparisons @@ -204,50 +213,78 @@ EXTERN_C NTSTATUS WINAPI DetourNtQueryValueKey(_In_ HANDLE KeyHandle, if (KeyValueInformationClass == KeyValueFullInformation || KeyValueInformationClass == KeyValueFullInformationAlign64) { - // calculated required size and return if not large enough - *ResultLength = offsetof(KEY_VALUE_FULL_INFORMATION, Name) + - tRegOverrideInfo->RegKeyName.Length + tRegOverrideInfo->RegValueDataSize; - if (*ResultLength > Length) + const UINT_PTR alignment = (KeyValueInformationClass == KeyValueFullInformation) ? 32 : 64; + iStatus = Length >= sizeof(ULONG) ? STATUS_BUFFER_OVERFLOW : STATUS_BUFFER_TOO_SMALL; + *ResultLength = (ULONG)align(offsetof(KEY_VALUE_FULL_INFORMATION, Name) + + tRegOverrideInfo->RegValueName.Length + tRegOverrideInfo->RegValueDataSize, alignment); + + PKEY_VALUE_FULL_INFORMATION tKeyInfo = (PKEY_VALUE_FULL_INFORMATION)KeyValueInformation; + + if (sizereq(KEY_VALUE_FULL_INFORMATION, TitleIndex) <= Length) + { + tKeyInfo->TitleIndex = 0; + } + if (sizereq(KEY_VALUE_FULL_INFORMATION, Type) <= Length) { - iStatus = STATUS_BUFFER_TOO_SMALL; - break; + tKeyInfo->Type = tRegOverrideInfo->RegValueType; + } + if (sizereq(KEY_VALUE_FULL_INFORMATION, NameLength) <= Length) + { + tKeyInfo->NameLength = tRegOverrideInfo->RegValueName.Length; + } + if (sizereq(KEY_VALUE_FULL_INFORMATION, DataLength) <= Length) + { + tKeyInfo->DataLength = tRegOverrideInfo->RegValueDataSize; } - // populate type and name information - PKEY_VALUE_FULL_INFORMATION tKeyInfo = (PKEY_VALUE_FULL_INFORMATION)KeyValueInformation; - tKeyInfo->TitleIndex = 0; - tKeyInfo->Type = tRegOverrideInfo->RegValueType; - tKeyInfo->NameLength = tRegOverrideInfo->RegKeyName.Length; - memcpy(tKeyInfo->Name, tRegOverrideInfo->RegValueName.Buffer, tRegOverrideInfo->RegKeyName.Length); - - // populate data - tKeyInfo->DataLength = tRegOverrideInfo->RegValueDataSize; - tKeyInfo->DataOffset = (ULONG)((LPBYTE)&tKeyInfo->Name - (LPBYTE)tKeyInfo) + tKeyInfo->NameLength; - LPVOID pData = (DWORD *)((LPBYTE)KeyValueInformation + tKeyInfo->DataOffset); - memcpy(pData, tRegOverrideInfo->RegValueData, tKeyInfo->DataLength); - iStatus = STATUS_SUCCESS; + // copy name payload + const ULONG iNameRequiredSize = (ULONG)offsetof(KEY_VALUE_FULL_INFORMATION, Name) + tKeyInfo->NameLength; + if (iNameRequiredSize <= Length) + { + memcpy(tKeyInfo->Name, tRegOverrideInfo->RegValueName.Buffer, tKeyInfo->NameLength); + } + + // copy data payload + const ULONG iDataRequiredSize = (ULONG)align(iNameRequiredSize + tKeyInfo->DataLength, alignment); + if (iDataRequiredSize <= Length) + { + tKeyInfo->DataOffset = (ULONG)align(iNameRequiredSize, alignment); + LPVOID pData = (LPVOID)align(((LPBYTE)KeyValueInformation + tKeyInfo->DataOffset), alignment); + memcpy(pData, tRegOverrideInfo->RegValueData, tKeyInfo->DataLength); + iStatus = STATUS_SUCCESS; + } } else if (KeyValueInformationClass == KeyValuePartialInformation || KeyValueInformationClass == KeyValuePartialInformationAlign64) { - // calculated required size and return if not large enough - *ResultLength = offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data) + - tRegOverrideInfo->RegValueDataSize; - if (*ResultLength > Length) - { - iStatus = STATUS_BUFFER_TOO_SMALL; - break; - } + // calculate required size and set default status + const UINT_PTR alignment = (KeyValueInformationClass == KeyValuePartialInformation) ? 32 : 64; + iStatus = Length >= sizeof(ULONG) ? STATUS_BUFFER_OVERFLOW : STATUS_BUFFER_TOO_SMALL; + *ResultLength = (ULONG)align(offsetof(KEY_VALUE_PARTIAL_INFORMATION, Data) + + tRegOverrideInfo->RegValueDataSize, alignment); - // populate type information PKEY_VALUE_PARTIAL_INFORMATION tKeyInfo = (PKEY_VALUE_PARTIAL_INFORMATION)KeyValueInformation; - tKeyInfo->TitleIndex = 0; - tKeyInfo->Type = tRegOverrideInfo->RegValueType; - // populate data - tKeyInfo->DataLength = tRegOverrideInfo->RegValueDataSize; - memcpy(tKeyInfo->Data, tRegOverrideInfo->RegValueData, tKeyInfo->DataLength); - iStatus = STATUS_SUCCESS; + if (sizereq(KEY_VALUE_PARTIAL_INFORMATION, TitleIndex) <= Length) + { + tKeyInfo->TitleIndex = 0; + } + if (sizereq(KEY_VALUE_PARTIAL_INFORMATION, Type) <= Length) + { + tKeyInfo->Type = tRegOverrideInfo->RegValueType; + } + if (sizereq(KEY_VALUE_PARTIAL_INFORMATION, DataLength) <= Length) + { + tKeyInfo->DataLength = tRegOverrideInfo->RegValueDataSize; + } + + // copy data payload + if (*ResultLength <= Length) + { + memcpy((PVOID)align(tKeyInfo->Data, alignment), + tRegOverrideInfo->RegValueData, tKeyInfo->DataLength); + iStatus = STATUS_SUCCESS; + } } } } @@ -278,7 +315,7 @@ EXTERN_C NTSTATUS WINAPI DetourNtEnumerateValueKey(_In_ HANDLE KeyHandle, _In_ U NTSTATUS iStatus = TrueNtEnumerateValueKey(KeyHandle, Index, KeyValueInformationClass, KeyValueInformation, Length, ResultLength); - if (iStatus == STATUS_SUCCESS && KeyValueInformation != NULL && + if (iStatus == STATUS_SUCCESS && KeyValueInformation != NULL && (KeyValueInformationClass == KeyValueFullInformation || KeyValueInformationClass == KeyValueFullInformationAlign64)) { @@ -397,7 +434,7 @@ void UpdateIpAddress(_In_ LPCWSTR sName, _Inout_ LPSOCKADDR tSockToUpdate) { static INT iHostOverrideParams = 0; static LPWSTR * sHostOverride = CommandLineToArgvW(_wgetenv(WINPRIV_EV_HOST_OVERRIDE), &iHostOverrideParams); - wprintf(L"\n\nLookup: %s\n\n", sName); + // parse the parameters to create the intercept list for (int iParam = 0; iParam < iHostOverrideParams; iParam += 2) {