From: Paul Gofman <pgofman@codeweavers.com> --- dlls/ntdll/rtl.c | 46 +++++++++++++++--------------- dlls/ntdll/tests/rtl.c | 64 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 22 deletions(-) diff --git a/dlls/ntdll/rtl.c b/dlls/ntdll/rtl.c index b63829aff12..a2b438b1418 100644 --- a/dlls/ntdll/rtl.c +++ b/dlls/ntdll/rtl.c @@ -1022,45 +1022,47 @@ ULONG WINAPI RtlRandomEx( ULONG *seed ) } /*********************************************************************** - * get_pointer_obfuscator (internal) + * get_process_cookie (internal) */ -static DWORD_PTR get_pointer_obfuscator( void ) +static ULONG get_process_cookie(void) { - static DWORD_PTR pointer_obfuscator; + static ULONG process_cookie; - if (!pointer_obfuscator) + if (!process_cookie) { - ULONG seed = NtGetTickCount(); - ULONG_PTR rand; + ULONG cookie; - /* generate a random value for the obfuscator */ - rand = RtlUniform( &seed ); - - /* handle 64bit pointers */ - rand ^= (ULONG_PTR)RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8); - - /* set the high bits so dereferencing obfuscated pointers will (usually) crash */ - rand |= (ULONG_PTR)0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8); - - InterlockedCompareExchangePointer( (void**) &pointer_obfuscator, (void*) rand, NULL ); + NtQueryInformationProcess( GetCurrentProcess(), ProcessCookie, &cookie, sizeof(cookie), NULL ); + InterlockedCompareExchange( (LONG volatile *)&process_cookie, cookie, 0 ); } - - return pointer_obfuscator; + return process_cookie; } +#define BIT_COUNT_IN_POINTER (sizeof(void *) * 8) + /************************************************************************* * RtlEncodePointer [NTDLL.@] */ PVOID WINAPI RtlEncodePointer( PVOID ptr ) { - DWORD_PTR ptrval = (DWORD_PTR) ptr; - return (PVOID)(ptrval ^ get_pointer_obfuscator()); + ULONG cookie = get_process_cookie(); + ULONG rotate = cookie % BIT_COUNT_IN_POINTER; + ULONG_PTR ptrval = (ULONG_PTR)ptr ^ cookie; + + return (void *)((ptrval >> rotate) | (ptrval << ((BIT_COUNT_IN_POINTER - rotate) % BIT_COUNT_IN_POINTER))); } +/************************************************************************* + * RtlDecodePointer [NTDLL.@] + */ PVOID WINAPI RtlDecodePointer( PVOID ptr ) { - DWORD_PTR ptrval = (DWORD_PTR) ptr; - return (PVOID)(ptrval ^ get_pointer_obfuscator()); + ULONG cookie = get_process_cookie(); + ULONG rotate = cookie % BIT_COUNT_IN_POINTER; + ULONG_PTR ptrval = (ULONG_PTR)ptr; + + ptrval = (ptrval << rotate) | (ptrval >> ((BIT_COUNT_IN_POINTER - rotate) % BIT_COUNT_IN_POINTER)); + return (void *)(ptrval ^ cookie); } /****************************************************************************** diff --git a/dlls/ntdll/tests/rtl.c b/dlls/ntdll/tests/rtl.c index f5db5cdc6e2..421d7e6afbe 100644 --- a/dlls/ntdll/tests/rtl.c +++ b/dlls/ntdll/tests/rtl.c @@ -5476,6 +5476,69 @@ static void test_RtlDeriveCapabilitySidsFromName(void) free( group_sid ); } +static ULONG_PTR rotate_bits_right( ULONG_PTR v, ULONG count ) +{ + static const unsigned int bits = sizeof(v) * 8; + + count %= bits; + return (v >> count) | (v << ((bits - count) % bits)); +} + +static ULONG_PTR rotate_bits_left( ULONG_PTR v, ULONG count ) +{ + static const unsigned int bits = sizeof(v) * 8; + + count %= bits; + return (v << count) | (v >> ((bits - count) % bits)); +} + +static ULONG process_cookie; + +static void *encode_pointer( void *ptr ) +{ + DWORD_PTR ptrval = (DWORD_PTR)ptr; + return (void *)rotate_bits_right( ptrval ^ process_cookie, process_cookie ); +} + +static void *decode_pointer( void *ptr ) +{ + DWORD_PTR ptrval = (DWORD_PTR)ptr; + return (void *)(rotate_bits_left( ptrval, process_cookie ) ^ process_cookie ); +} + +static void test_pointer_encoding(void) +{ + void *v, *expected; + + if (NtQueryInformationProcess( GetCurrentProcess(), ProcessCookie, &process_cookie, sizeof(process_cookie), NULL )) + { + win_skip( "Could not get process cookie, skipping tests.\n" ); + return; + } + ok( process_cookie, "got 0.\n" ); + + v = RtlEncodePointer( NULL ); + expected = encode_pointer( NULL ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); + v = RtlDecodePointer( v ); + expected = decode_pointer( expected ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); + + v = RtlEncodePointer( (void *)(ULONG_PTR)1 ); + expected = encode_pointer( (void *)(ULONG_PTR)1 ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); + v = RtlDecodePointer( v ); + expected = decode_pointer( expected ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); + + v = RtlEncodePointer( (void *)(ULONG_PTR)0xdeadbeeffeedcafe ); + expected = encode_pointer( (void *)(ULONG_PTR)0xdeadbeeffeedcafe ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); + v = RtlDecodePointer( v ); + expected = decode_pointer( expected ); + ok( v == expected, "got %p, expected %p.\n", v, expected ); +} + START_TEST(rtl) { InitFunctionPtrs(); @@ -5546,4 +5609,5 @@ START_TEST(rtl) test_RtlGetElementGenericTable(); test_RtlCreateServiceSid(); test_RtlDeriveCapabilitySidsFromName(); + test_pointer_encoding(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/9926