[PATCH 2/2] ntdll/tests: Add tests for RtlEncode(System)Pointer.

Myah Caron qsniyg at protonmail.com
Thu Oct 8 07:36:02 CDT 2020


Signed-off-by: Myah Caron <qsniyg at protonmail.com>
---
I'm sending this in without an implementation in case there's anything I need to change, as the implementation
would mostly be a copy+paste job I believe (with the exception of implementing both process/usd cookies).

It turns out that newer Windows versions rotate the cookie and the pointer right by an amount specified by the
first 31/63 bits before XORing them.

Unfortunately I couldn't find any mention of how this algorithm worked on google, so I had to spend some time
to figure it out.

If you're curious, here's the file I created to test how the the algorithm worked (sorry for the mess):
https://github.com/qsniyg/wine_dll_load_test/blob/master/encodeptr.c

 dlls/ntdll/tests/rtl.c | 83 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 83 insertions(+)

diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c
index 7a62670ea05..416264bac0f 100644
--- a/dlls/ntdll/tests/rtl.c
+++ b/dlls/ntdll/tests/rtl.c
@@ -82,6 +82,11 @@ static NTSTATUS  (WINAPI *pRtlInitializeCriticalSectionEx)(CRITICAL_SECTION *, U
 static NTSTATUS  (WINAPI *pLdrEnumerateLoadedModules)(void *, void *, void *);
 static NTSTATUS  (WINAPI *pLdrRegisterDllNotification)(ULONG, PLDR_DLL_NOTIFICATION_FUNCTION, void *, void **);
 static NTSTATUS  (WINAPI *pLdrUnregisterDllNotification)(void *);
+static VOID*     (WINAPI *pRtlEncodePointer)(void *);
+static VOID*     (WINAPI *pRtlDecodePointer)(void *);
+static VOID*     (WINAPI *pRtlEncodeSystemPointer)(void *);
+static VOID*     (WINAPI *pRtlDecodeSystemPointer)(void *);
+static NTSTATUS  (WINAPI *pNtQueryInformationProcess)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

 static HMODULE hkernel32 = 0;
 static BOOL      (WINAPI *pIsWow64Process)(HANDLE, PBOOL);
@@ -122,6 +127,11 @@ static void InitFunctionPtrs(void)
         pLdrEnumerateLoadedModules = (void *)GetProcAddress(hntdll, "LdrEnumerateLoadedModules");
         pLdrRegisterDllNotification = (void *)GetProcAddress(hntdll, "LdrRegisterDllNotification");
         pLdrUnregisterDllNotification = (void *)GetProcAddress(hntdll, "LdrUnregisterDllNotification");
+        pRtlEncodePointer = (void *)GetProcAddress(hntdll, "RtlEncodePointer");
+        pRtlDecodePointer = (void *)GetProcAddress(hntdll, "RtlDecodePointer");
+        pRtlEncodeSystemPointer = (void *)GetProcAddress(hntdll, "RtlEncodeSystemPointer");
+        pRtlDecodeSystemPointer = (void *)GetProcAddress(hntdll, "RtlDecodeSystemPointer");
+        pNtQueryInformationProcess = (void *)GetProcAddress(hntdll, "NtQueryInformationProcess");
     }
     hkernel32 = LoadLibraryA("kernel32.dll");
     ok(hkernel32 != 0, "LoadLibrary failed\n");
@@ -3483,6 +3493,78 @@ static void test_LdrRegisterDllNotification(void)
     pLdrUnregisterDllNotification(cookie);
 }

+static void* our_encode_pointer(void* addr, ULONG cookie)
+{
+    int shift_amount;
+    uintptr_t rot_addr;
+    uintptr_t rot_cookie;
+
+#ifdef _WIN64
+    shift_amount = cookie & 63;
+#define ROTR _rotr64
+#else
+    shift_amount = cookie & 31;
+#define ROTR _rotr
+#endif
+
+    rot_addr = ROTR((uintptr_t)addr, shift_amount);
+    rot_cookie = ROTR((uintptr_t)cookie, shift_amount);
+
+    return (void*)(rot_addr ^ rot_cookie);
+}
+
+static void test_RtlEncodePointer(void)
+{
+    void *addr = (void*)0xdeadbeef0123abcd;
+    void *encoded, *encoded1, *decoded;
+    void *our_encoded;
+    ULONG process_cookie = 0xdeadbeef;
+    ULONG system_cookie = *(ULONG*)(0x7ffe0000 + 0x330); /* user_shared_data.Cookie */
+    NTSTATUS status;
+
+    if (!pRtlEncodePointer || !pRtlDecodePointer)
+    {
+        win_skip("RtlEn/DecodePointer not available\n");
+        return;
+    }
+
+    encoded = pRtlEncodePointer(addr);
+    ok(encoded != addr, "got %p\n", encoded);
+
+    decoded = pRtlDecodePointer(encoded);
+    ok(decoded == addr, "got %p\n", decoded);
+
+    if (!pNtQueryInformationProcess)
+    {
+        win_skip("NtQueryInformationProcess not available\n");
+    }
+    else
+    {
+        status = pNtQueryInformationProcess(GetCurrentProcess(), ProcessCookie, &process_cookie, sizeof(process_cookie), NULL);
+        ok(status == S_OK, "got %08x\n", status);
+        ok(process_cookie != 0xdeadbeef, "got %08x\n", process_cookie);
+
+        our_encoded = our_encode_pointer(addr, process_cookie);
+        todo_wine ok(encoded == our_encoded || broken(encoded == (void*)((uintptr_t)addr ^ (uintptr_t)process_cookie)), "got %p (ours %p)\n", encoded, our_encoded);
+    }
+
+    if (!pRtlEncodeSystemPointer || !pRtlDecodeSystemPointer)
+    {
+        win_skip("RtlEn/DecodeSystemPointer not available\n");
+        return;
+    }
+
+    encoded1 = pRtlEncodeSystemPointer(addr);
+    ok(encoded != addr, "got %p\n", encoded);
+    todo_wine ok(encoded1 != encoded, "got %p\n", encoded1);
+
+    decoded = pRtlDecodeSystemPointer(encoded1);
+    ok(decoded == addr, "got %p\n", decoded);
+
+    our_encoded = our_encode_pointer(addr, system_cookie);
+    todo_wine ok(encoded1 == our_encoded || broken(encoded1 == (void*)((uintptr_t)addr ^ (uintptr_t)system_cookie)), "got %p (ours %p)\n", encoded1, our_encoded);
+}
+
 START_TEST(rtl)
 {
     InitFunctionPtrs();
@@ -3523,4 +3605,5 @@ START_TEST(rtl)
     test_LdrEnumerateLoadedModules();
     test_RtlMakeSelfRelativeSD();
     test_LdrRegisterDllNotification();
+    test_RtlEncodePointer();
 }
--
2.28.0





More information about the wine-devel mailing list