Reputation: 61
I am translating codes from C++ to my VB.NET application. This is the c++ codes:
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];
As you see, it defines a function in stack. How can I simulate it in VB.NET?
Note: You can write C# codes, It is no problem.
Edit:
I wrote a class under the light of your suggestions.
<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
When I execute this, "Func_Init.Invoke(0, 0, Nothing)" line gives me this error:
System.AccessViolationException
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
Edit2:
I added first part of the assembly codes in Bytes variant:
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
...
Upvotes: 1
Views: 1684
Reputation: 134125
That code is allocating memory, copying data to the allocated memory, and then making a function pointer that references it. Presumably the next step is to execute that code.
Whereas you can allocate the memory in .NET, and copy data to it, you won't be able to transfer control to that block of memory.
For information on calling VirtualAlloc
from .NET, see pinvoke.net: VirtualAlloc.
To copy data to that allocated block, you'll need to call some form of Marshal.Copy.
If for some unknown reason you do want to execute the code in that block of memory, you'll have to call an unmanaged function (written in C or C++, for example), pass it the address returned by VirtualAlloc
, and have it execute the code.
(From comments)
If for some reason you really want to execute the code in that block of memory, you call Marshal.GetDelegateForFunctionPointer, passing it the address of that memory block. You can then call that function through the delegate.
The delegate type, by the way, would be something like:
delegate int test_t (uint32 type, IntPtr data, uint32 length);
I'm not sure how you'd specify the calling convention, and there are several ways you could marshal the data. You could pin an array and pass the pointer, use an unsafe pointer and pass a byte*
, or potentially declare the parameter as a byte[]
and marshal the data (although I'm not sure how you'd specify the marshaling). Perhaps somebody else has the answer to that.
You defined your delegate as:
Public Delegate Sub Init(
ByVal Value As UInt32,
ByVal Param1 As UInt32,
ByVal Param2 As IntPtr)
That doesn't match the C definition. I think Param1
should be IntPtr
and Param2
should be UInt32
.
Also, you don't say if this is 32-bit or 64-bit code. If you're running a 64-bit app and the code you're executing (whatever is in the Bytes
) is 32-bit, then it's not going to work.
I don't know what's in the Bytes
, so I can't even guess what might be causing your access violation. You are passing it a null pointer, though, so that could be a problem. You'll have to use the assembly level debugger if you want to debug that.
Upvotes: 5