我正在将代码从C++转换为我的VB.NET应用程序。这是c++代码:

typedef int (__stdcall  *init_t)(uint32_t value,uint32_t param1,uint32_t* param2);
static init_t fnInit;
...
...
memory = (uint8_t*)VirtualAlloc(NULL,5000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
memset(memory,5000,0);
memmove(memory,data,datalen);
fnInit = (init_t )&memory[0];

如您所见,它在堆栈中定义了一个函数。如何在VB.NET中模拟它?

注意:您可以编写C#代码,这没问题。

编辑:

我根据您的建议写了一个类。
        <Flags> _
    Public Enum AllocationType As UInteger
        COMMIT = &H1000
        RESERVE = &H2000
        RESET = &H80000
        LARGE_PAGES = &H20000000
        PHYSICAL = &H400000
        TOP_DOWN = &H100000
        WRITE_WATCH = &H200000
    End Enum

    <Flags> _
    Public Enum MemoryProtection As UInteger
        EXECUTE = &H10
        EXECUTE_READ = &H20
        EXECUTE_READWRITE = &H40
        EXECUTE_WRITECOPY = &H80
        NOACCESS = &H1
        [READONLY] = &H2
        READWRITE = &H4
        WRITECOPY = &H8
        GUARD_Modifierflag = &H100
        NOCACHE_Modifierflag = &H200
        WRITECOMBINE_Modifierflag = &H400
    End Enum
    <DllImport("kernel32.dll", SetLastError:=True)> _
    Private Shared Function VirtualAlloc(lpAddress As IntPtr, dwSize As UIntPtr, flAllocationType As AllocationType, flProtect As MemoryProtection) As IntPtr
    End Function
    <DllImport("msvcrt.dll", EntryPoint:="memset", CallingConvention:=CallingConvention.Cdecl, SetLastError:=False)> _
    Public Shared Function MemSet(dest As IntPtr, c As Integer, count As IntPtr) As IntPtr
    End Function
    <DllImport("msvcrt.dll", SetLastError:=False)> _
    Private Shared Function memmove(dest As IntPtr, src As IntPtr, count As Integer) As IntPtr
    End Function

    <UnmanagedFunctionPointer(CallingConvention.StdCall)> _
    Public Delegate Sub Init(ByVal Value As UInt32, ByVal Param1 As UInt32, ByVal Param2 As IntPtr)

    Dim Func_Init As Init

   Sub New(ByRef Bytes() As Byte)
        Dim OffSetInit As Int32 = &H0 'This is correct
        Dim MemoryPtr As IntPtr
        MemoryPtr = VirtualAlloc(Nothing, 5000, AllocationType.COMMIT, MemoryProtection.EXECUTE_READWRITE)
        MemSet(MemoryPtr, 0, 5000)
        Marshal.Copy(Bytes, 0, MemoryPtr, Bytes.Length)
        Dim InitPtr As IntPtr = MemoryPtr + OffSetInit
        Func_Init = CType(Marshal.GetDelegateForFunctionPointer(InitPtr, GetType(Init)), Init)
        Func_Init.Invoke(0, 0, Nothing)
    End Sub

当我执行此操作时,“Func_Init.Invoke(0,0,Nothing)”行给了我这个错误:
System.AccessViolationException
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

编辑2:

我在Bytes变体中添加了汇编代码的第一部分:
seg000:00000000     ;
seg000:00000000     ; +-------------------------------------------------------------------------+
seg000:00000000     ; |   This file has been generated by The Interactive Disassembler (IDA)    |
seg000:00000000     ; |           Copyright (c) 2011 Hex-Rays, <[email protected]>           |
seg000:00000000     ; |                      License info: B3-432E-F558-21                      |
seg000:00000000     ; |                             Ilfak Guilfanov                             |
seg000:00000000     ; +-------------------------------------------------------------------------+
seg000:00000000     ;
seg000:00000000     ; Input MD5   : 55D6B96FEF969A18F927BC5A7A21FAEE
seg000:00000000     ; Input CRC32 : 9A6D4B33
seg000:00000000
seg000:00000000     ; File Name   : C:\****************.dll
seg000:00000000     ; Format      : Binary file
seg000:00000000     ; Base Address: 0000h Range: 0000h - 4174h Loaded length: 4174h
seg000:00000000
seg000:00000000                     include uni.inc ; see unicode subdir of ida for info on unicode
seg000:00000000
seg000:00000000                     .686p
seg000:00000000                     .mmx
seg000:00000000                     .model flat
seg000:00000000
seg000:00000000     ; ===========================================================================
seg000:00000000
seg000:00000000     ; Segment type: Pure code
seg000:00000000     seg000          segment byte public 'CODE' use32
seg000:00000000                     assume cs:seg000
seg000:00000000                     assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:00000000
seg000:00000000     ; =============== S U B R O U T I N E =======================================
seg000:00000000
seg000:00000000     ; Attributes: bp-based frame
seg000:00000000
seg000:00000000     sub_0           proc near
seg000:00000000
seg000:00000000     var_4           = dword ptr -4
seg000:00000000     arg_0           = dword ptr  8
seg000:00000000     arg_4           = dword ptr  0Ch
seg000:00000000     arg_8           = dword ptr  10h
seg000:00000000
...

最佳答案

该代码正在分配内存,将数据复制到已分配的内存,然后创建引用该内存的函数指针。大概下一步就是执行该代码。

尽管您可以在.NET中分配内存并将其复制到其中,但您将无法将控制权转移到该内存块。

有关从.NET调用VirtualAlloc的信息,请参见pinvoke.net: VirtualAlloc

要将数据复制到分配的块,您需要调用某种形式的Marshal.Copy

如果出于某种未知原因您确实想在该内存块中执行代码,则必须调用一个非托管函数(例如,用C或C++编写),将其传递给VirtualAlloc返回的地址,并使其执行编码。

(摘自评论)

如果出于某种原因您确实要在该内存块中执行代码,请调用Marshal.GetDelegateForFunctionPointer,将其传递给该内存块的地址。然后,您可以通过委托(delegate)调用该函数。

委托(delegate)类型,顺便说一句:

delegate int test_t (uint32 type, IntPtr data, uint32 length);

我不确定如何指定调用约定,并且有几种方法可以封送数据。您可以固定数组并传递指针,使用不安全的指针并传递byte*,或者可能将参数声明为byte[]并封送数据(尽管我不确定如何指定封送处理)。也许其他人对此有答案。

更新资料

您将委托(delegate)定义为:
Public Delegate Sub Init(
    ByVal Value As UInt32,
    ByVal Param1 As UInt32,
    ByVal Param2 As IntPtr)

那不符合C的定义。我认为Param1应该是IntPtrParam2应该是UInt32

另外,您不会说这是32位还是64位代码。如果您运行的是64位应用程序,并且正在执行的代码(无论Bytes是什么)都是32位的,那么它将无法正常工作。

我不知道Bytes中包含什么,所以我什至无法猜测可能导致您的访问冲突的原因。但是,您正在传递给它一个空指针,所以可能是一个问题。如果要调试程序集级调试器,则必须使用它。

关于c# - VirtualAlloc和StdCall,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17976722/

10-11 14:37