ProtectedBuffer Class

This C# class creates a buffer of memory that can be protected from modification by both managed and unmanaged code.  The buffer is protected by the Windows kernel and exposed as a memory stream.  This is experimental code and should not be used on production systems without extensive testing.

Usage

The class is easy to use.  You must pass the desired buffer length to the constructor.  The class will call the Win32 API to allocate a block of virtual memory from the heap.  You can then call Protect or Unprotect to make the buffer read-only or read-write, respectively.  The GetStream method allows you to access the buffer as an I/O stream.  The code must be compiled in unsafe mode because it works with pointers from the Win32 API.

Once protected, you cannot modify the memory even with reflections or another computer language (e.g. C++) -- unless, of course, you unprotected the memory.

Download

DownloadProtectedBuffer.zip (18kb, Visual Studio 2005 Solution)

Details (incomplete -- these notes will be finished later)

The ProtectedBuffer class allocates a block of memory from the kernal.  It then exposes that memory as an I/O Stream.  The underlying memory can be marked as read-only through a special call to the Win32 API.  This means any attempts to modify the memory will fail.  This is not a perfect security system, for a knowledgeable user could make a similar call to unprotect the memory.  However, it is a good way to ensure that a block of memory is protected from accidental modifications.

VirtualAlloc Function

This Windows kernel function (in KERNEL32.DLL) reserves a block of memory from the heap.

[DllImport("kernel32", SetLastError = true)]
private static extern IntPtr VirtualAlloc(
    IntPtr lpStartAddr,
    int size,
    uint flAllocationType,
    uint flProtect);

The lpAddress parameter specifies the starting address of the block of memory to reserve.  If zero (null), the kernel selects a starting address automatically -- effectively providing a way of dynamically allocating memory.

The starting address (lpStartAddr) indicates the starting address of the memory to reserve.  This parameter can be zero (also known as null in C/C++), in which case Windows selects a starting address automatically.  This effectively provides a way of dynamically allocating memory.

The size parameter specifies the desired size of the memory block.  The amount of reserved memory is always rounded up to the nearest page size, which is the smallest amount of memory that can be managed by the operating system.  Operating systems allocate memory in pages instead of individual bytes in order to improve performance (a smaller page size might be more convenient for developers but would require the operating system to keep track of more reservations).

VirtualFree Function

The VirtualFree function returns a reserved block of memory back to Windows.

[DllImport("kernel32", SetLastError=true)]
private static extern int VirtualFree(
    IntPtr lpAddress,
    UInt32 dwSize,
    UInt32 dwFreeType);

VirtualProtect Function

The VirtualProtect function is used to set the access rights (and other attributes) of a block of memory previously reserved with VirtualAlloc.

[DllImport("kernel32.dll", SetLastError = true)]
static extern int VirtualProtect(
    IntPtr lpAddress,
    int dwSize,
    int flNewProtect,
    ref int lpflOldProtect);

Disposable Pattern

The ProtectedBuffer class is a classic example of a .NET class that references an unmanaged resource (specifically, the handle to the block of memory returned by the Win32 API).  The class therefore implements the IDisposable pattern to ensure the buffer is unprotected and released back to the operating system when disposed.  You should call the .Dispose method as a courtesy to the garbage collector.