level 13
Windows8的DEP似乎经过改进,用LocalAlloc也就是System.Runtime.InteropServices.Marshal.AllocHGlobal分配的内存被标记为可读可写不可执行的,Byte()也一样。AllocCoTaskMem分配的内存是只读的。在之前的windows里,即使打开了DEP,AllocHGlobal分配的内存也是可执行的。最坑的是,Windows8环境中,用NtSetInformationProcess似乎不能完全禁止DEP。解决这个问题需要改变分配内存的方式。用VirtualAlloc或VirtualAllocEx就能得到可读写可执行的内存区域。
VirtualAlloc(0, Size, MEM_RESERVE Or MEM_COMMIT, PAGE_EXECUTE_READWRITE)
理论知识是StackOverflow网站提供的。
--来自相机+平板电脑+手机融合成的的Lumia 1520
2014年08月31日 13点08分
1
level 13
亲测成功了。
不想复制内存也可以考虑使用VirtualProtect
Private Declare Function VirtualProtect Lib "kernel32" (lpAddress As IntPtr,
dwSize As Int32,
flNewProtect As Int32,
ByRef lpflOldProtect As Int32) As Integer
Private Delegate Function Ret1Arg(arg1 As UInteger) As UInteger
***
*** 执行机器码,能使用一个参数,有一个返回值
***
*** 机器码数组
*** 第一个参数
***
***
Function Invoke(asmByteData As Byte(), param1 As UInteger) As UInteger
Dim startAddress As IntPtr = UnsafeAddrOfPinnedArrayElement(asmByteData, 0)
VirtualProtect(startAddress ,asmByteData.Length ,&H40,0) *让那块内存可读写可执行。如果要翻译成c
#版,注意把0改成new int() ,因为c#
对ref的参数要求不是常量。
Dim delType As Type = GetType(Ret1Arg)
Dim methodPtr As FieldInfo = delType.GetField("_methodPtr", BindingFlags.NonPublic Or BindingFlags.Instance)
Dim del As New Ret1Arg(Function(arg1 As UInteger)
Return 0
End Function)
methodPtr.SetValue(del, startAddress) *偷梁换柱,强行用反射把函数指针的地址改成我们的asm字节码
Return del(param1)
End Function
2014年08月31日 13点08分
2
百度真会河蟹,看看那些星号
2014年08月31日 14点08分