Windows Server 2003 (NT 5.2.3790.0) build guide
EncodePointer / DecodePointer functions for KERNEL32.DLL in Windows XP/2003
These functions are used by Windows Applications to make memory pointers more secure.
The EncodePointer / DecodePointer code used originally comes from Wine: https://github.com/rpodgorny/wine/blob/master/libs/port/interlocked.c https://github.com/wine-mirror/wine/blob/master/dlls/ntdll/rtl.c
Here is a essay about these functions: https://devblogs.microsoft.com/oldnewthing/20201113-00/?p=104447
These functions are implemented in NTDLL.DLL, and redirected to NTDLL.DLL in KERNEL32.DLL
Requirements
A x86 version of Windows 2003 / XP SP1 with source code available: see build-win2k3
Ability to execute executables built for newer versions than Windows XP SP2 / Windows Server 2003 RTM (NT 5.2).
Changes
- create the following
\base\ntdll\_obfuscated_pointers.c
file:
#include "ldrp.h"
#include <ntos.h>
static DWORD_PTR pointer_obfuscator;
/***********************************************************************
* rotl_ptr (internal)
*/
#ifdef _WIN64
#define ROT_BITS 64
#else
#define ROT_BITS 32
#endif
static DWORD_PTR rotl_ptr( DWORD_PTR num, int shift )
{
shift &= ROT_BITS - 1;
return (num << shift) | (num >> (ROT_BITS-shift));
}
/***********************************************************************
* rotr_ptr (internal)
*/
static DWORD_PTR rotr_ptr( DWORD_PTR num, int shift )
{
shift &= ROT_BITS - 1;
return (num >> shift) | (num << (ROT_BITS-shift));
}
static DWORD_PTR get_pointer_obfuscator( void )
{
if (!pointer_obfuscator)
{
ULONG seed = NtGetTickCount();
ULONG_PTR rand;
/* generate a random value for the obfuscator */
rand = RtlUniform( &seed );
/* handle 64bit pointers */
rand ^= RtlUniform( &seed ) << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
/* set the high bits so dereferencing obfuscated pointers will (usually) crash */
rand |= 0xc0000000 << ((sizeof (DWORD_PTR) - sizeof (ULONG))*8);
InterlockedCompareExchangePointer( (void**) &pointer_obfuscator, (void*) rand, NULL );
}
return pointer_obfuscator;
}
/*************************************************************************
* RtlEncodePointer [NTDLL.@]
*/
PVOID
RtlEncodePointer(
IN PVOID Ptr
)
{
DWORD_PTR ptrval = (DWORD_PTR) Ptr;
DWORD_PTR cookie = get_pointer_obfuscator();
/* http://blogs.msdn.com/b/michael_howard/archive/2006/08/16/702707.aspx */
ptrval = (ptrval ^ cookie);
return (PVOID)rotr_ptr(ptrval, cookie);
}
PVOID
RtlDecodePointer(
PVOID Ptr
)
{
DWORD_PTR ptrval = (DWORD_PTR) Ptr;
DWORD_PTR cookie = get_pointer_obfuscator();
ptrval = rotl_ptr(ptrval, cookie);
return (PVOID)(ptrval ^ cookie);
}
- In
\base\ntdll\ntdlldef.src
: add these two lines
DecodePointer
EncodePointer
- In
\base\ntdll\daytona\sources
&\base\ntdll\wow6432\sources
add toSOURCES
macro:
..\_obfuscated_pointers.c \
- Run
bcz
in\base\ntdll
- In
\base\win32\client\kernel32.src
add these two lines
DecodePointer = NTDLL.RtlDecodePointer
EncodePointer = NTDLL.RtlEncodePointer
- Run
bcz
in\base\win32\client
- Overwrite the created
\base\ntdll\daytona\obj\i386\NTDLL.DLL
in theC:\WINDOWS\SYSTEM32
folder of your Windows XP installation. - Overwrite the created
\base\win32\client\daytona\obj\i386\KERNEL32.DLL
in theC:\WINDOWS\SYSTEM32
folder of your Windows XP installation.