Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

what is the correct way to write byte array into unmanaged memory?

I faced a problem when I tried to write into virtual memory in C# program, I allocated the memory using VirtuAlloc function, and then write 10 bytes array into the memory using Marshal.Copy function, but when I tried to read 10 bytes from the same address, it gives me other bytes.

I tried this code to write array into allocated memory, but when I try to read the bytes from the address I wrote byte to, it gives me other bytes, take a look at the code:

byte[] arr = {1,2,3,4,5,6,7,8,9,10};

Console.WriteLine("arr: ");
for (int i = 0; i < arr.Length; i++){ 
    Console.Write("0x{0:X2} , ", arr[i]);
}
Console.WriteLine("");

UInt32  codeAddr = VirtualAlloc(0, (UInt32)arr.Length, MEM_COMMIT, PAGE_READWRITE);
Console.WriteLine("Code Address: 0x{0:X8}",codeAddr);

Marshal.Copy(arr, 0, (IntPtr) (codeAddr), arr.Length);

Console.WriteLine("arr at 0x{0:X8}: ",codeAddr);  
byte value=0;
for (int i = 0; i < arr.Length; i++){
    value = Marshal.ReadByte(codeAddr, i);
    Console.Write("0x{0:X2} , ", value);
}
Console.WriteLine("");
  

the output is


C:\Users\thm\Desktop>koko.exe 
arr:
0x01 , 0x02 , 0x03 , 0x04 , 0x05 , 0x06 , 0x07 , 0x08 , 0x09 , 0x0A ,
Code Address: 0x00770000
arr at 0x00770000:
0x00 , 0x00 , 0x77 , 0x00 , 0x0A , 0xD5 , 0x0A , 0x00 , 0xB7 , 0x46 ,             

but I think it must print 0x01 ..... 0xA twice, why it did not read the written bytes in that address

like image 733
Amr Alasmer Avatar asked Dec 07 '25 08:12

Amr Alasmer


2 Answers

I reproduced the error and I think it's due to how you have defined the extern VirtualAlloc - to return UInt32 and not the system native pointer size IntPtr.

UInt32 codeAddr = VirtualAlloc(0, (UInt32)arr.Length, MEM_COMMIT, PAGE_READWRITE);

if you change it to return IntPtr, it will work.

[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr VirtualAlloc(int lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
like image 100
Ivan Petrov Avatar answered Dec 09 '25 20:12

Ivan Petrov


I would just use Marshal.AllocHGlobal to allocate the memory. At least unless you need the extra control VirtualAlloc gives you.

try{
  var codeAddr = Marshal.AllocHGlobal(arr.Length);
  ...
}
finally{
  Marshal.FreeHGlobal(codeAddr );
}
like image 35
JonasH Avatar answered Dec 09 '25 21:12

JonasH