A long time ago, I compiled an article titled C # calling unmanaged programs. net Program embedded in the asm assembly code for a simple discussion, now there is time to sort out.
The last method in C # Call an unmanaged program is to construct data that conforms to the assembly code (machine code) format and execute the data as executable code. Windows provides the DEP (Data Execution Prevention Data Execution Protection) mechanism, that is, Windows will try to prevent programs from running executable code in non-executable memory areas. If DEP is enabled, the execution of the last method in "C # Call an unmanaged program" fails. If DEP is disabled, the code is successfully executed in Windows XP SP2, however, due to enhanced security, Vista/Win7 may fail to execute the code.
Isn't it necessary to enable DEP and Vista/Win7 by embedding assembly code? The answer is shown in the following analysis.
If we mark the memory area for saving the assembly code as executable, the above method may be available.
Win API VirtualAlloc has parameters. You can specify the new memory allocation permission.
Call VirtualFree to release the memory.
Follow these steps to modify the last method in "C # Call an unmanaged program" as follows (the reason for the length is simplified):/* modify the record
Qu Bin
> Basic functions
[!] Optimization tomorrow
Qu Bin
[E] optimized
[N] added the NativeCodeHelper class for ease of use
Week
Modify the compatibility and run it in DEP and Vista/Win7.
*/
Namespace NShellNativeCode
{
Using System;
Using System. Runtime. InteropServices;
Delegate int AddProc (int p1, int p2 );
Class Program
{
Static void Main (string [] args)
{
Byte [] codeBytes = {
0x8B, 0x44, 0x24, 0x08 // mov eax, [esp + 08 h]
, 0x8B, 0x4C, 0x24, 0x04 // mov ecx, [esp + 04 h]
, 0x03, 0xC1 // add eax, ecx
, 0xC3 // ret
};
/*
The byte array above is the local code of the following function;
Int add (int x, int y ){
Return x + y;
}
*/
IntPtr handle = IntPtr. Zero;
Handle =VirtualAlloc(
IntPtr. Zero,
CodeBytes. Length,
MEM_COMMIT | MEM_RESERVE,
PAGE_EXECUTE_READWRITE );
Try
{
Marshal. Copy (codeBytes, 0, handle, codeBytes. Length );
AddProc add
= Marshal. GetDelegateForFunctionPointer (handle, typeof (AddProc) as AddProc;
Int r = add (1976, 1 );
Console. WriteLine ("Local Code return: {0}", r );
}
Finally
{
VirtualFree(Handle, 0, MEM_RELEASE );
}
Console. ReadLine ();
}
// Windows API
[DllImport ("Kernel32.dll", EntryPoint = "VirtualAlloc")]
Public static extern IntPtr VirtualAlloc (IntPtr address, int size, uint allocType, uint protect );
[DllImport ("Kernel32.dll", EntryPoint = "VirtualFree")]
Public static extern bool VirtualFree (IntPtr address, int size, uint freeType );
// Flags
Const uint MEM_COMMIT = 0x1000;
Const uint MEM_RESERVE = 0x2000;
Const uint PAGE_EXECUTE_READWRITE = 0x40;
Const uint MEM_RELEASE = 0x8000;
}
}
It turns out that this method of embedding assembly code can run on DEP and Vista/Win7.
Windows 7 (X86) enables the DEP environment to pass the test.
Note: The codeBytes array contains X86 assembly code. To run the code in X64, You need to modify the code!