I never noticed the Marshal.GetDelegateForFunctionPointer() function in the .NET Framework 2.0 until Devin Jenson posted about using it to run native assembly code from C#. This was a wonderfully timed post for me as I was just putting together the finishing touches on the code for my how to detect virtual machine execution. What Marshal.GetDelegateForFunctionPointer() enables is certainly impressive. One thing that Devin pointed out in his post was the need for VirtualAllocEx() and VirtualProtectEx() calls to ensure the code executed was not in a Data Execution Protection block. Since I needed to make those calls anyway to port my C/C++ code, I decided to post how to do it here: class MemoryManager
{
const uint MEM_COMMIT = 0x1000;
const uint MEM_RESERVE = 0x2000;
const uint MEM_DECOMMIT = 0x4000;
const uint PAGE_EXECUTE_READWRITE = 0x40; [DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll")]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint dwFreeType); public static bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize)
{
return VirtualFreeEx(hProcess, lpAddress, dwSize, MEM_DECOMMIT);
} public static bool VirtualFreeEx(IntPtr lpAddress, UIntPtr dwSize)
{
return VirtualFreeEx(GetCurrentProcess(), lpAddress, dwSize, MEM_DECOMMIT);
} [DllImport("kernel32", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError = true)]
static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); public static IntPtr AllocExecutionBlock(int size)
{
return AllocExecutionBlock(size, GetCurrentProcess());
} public static IntPtr AllocExecutionBlock(int size, IntPtr hProcess)
{
IntPtr codeBytesPtr;
codeBytesPtr = VirtualAllocEx(
hProcess, IntPtr.Zero,
(UIntPtr)size,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (codeBytesPtr == IntPtr.Zero)
{
throw new System.ComponentModel.Win32Exception();
} uint lpflOldProtect;
if (!VirtualProtectEx(
hProcess, codeBytesPtr,
(UIntPtr)size,
PAGE_EXECUTE_READWRITE, out lpflOldProtect))
{
throw new System.ComponentModel.Win32Exception();
} return codeBytesPtr;
}
}Read more: Mark Michaelis' Weblog
{
const uint MEM_COMMIT = 0x1000;
const uint MEM_RESERVE = 0x2000;
const uint MEM_DECOMMIT = 0x4000;
const uint PAGE_EXECUTE_READWRITE = 0x40; [DllImport("kernel32.dll")]
public static extern IntPtr GetCurrentProcess(); [DllImport("kernel32.dll")]
static extern bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint dwFreeType); public static bool VirtualFreeEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize)
{
return VirtualFreeEx(hProcess, lpAddress, dwSize, MEM_DECOMMIT);
} public static bool VirtualFreeEx(IntPtr lpAddress, UIntPtr dwSize)
{
return VirtualFreeEx(GetCurrentProcess(), lpAddress, dwSize, MEM_DECOMMIT);
} [DllImport("kernel32", SetLastError = true)]
static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flAllocationType, uint flProtect); [DllImport("kernel32.dll", SetLastError = true)]
static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress,
UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect); public static IntPtr AllocExecutionBlock(int size)
{
return AllocExecutionBlock(size, GetCurrentProcess());
} public static IntPtr AllocExecutionBlock(int size, IntPtr hProcess)
{
IntPtr codeBytesPtr;
codeBytesPtr = VirtualAllocEx(
hProcess, IntPtr.Zero,
(UIntPtr)size,
MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE); if (codeBytesPtr == IntPtr.Zero)
{
throw new System.ComponentModel.Win32Exception();
} uint lpflOldProtect;
if (!VirtualProtectEx(
hProcess, codeBytesPtr,
(UIntPtr)size,
PAGE_EXECUTE_READWRITE, out lpflOldProtect))
{
throw new System.ComponentModel.Win32Exception();
} return codeBytesPtr;
}
}Read more: Mark Michaelis' Weblog
0 comments:
Post a Comment