Fast memcpy in C# - c#

I want to write a C# method with prototype like this:
void memcpy(byte[] dst, int dstOffset, byte[] src, int srcOffset, int len);
I have 2 options for this method:
1.
void memcpy(byte[] dst, int dstOffset, byte[] src, int srcOffset, int len)
{
for (int i = 0; i < len; i++)
{
dst[dstOffset + i] = src[srcOffset + i];
}
}
2.
void memcpy(byte[] dst, int dstOffset, byte[] src, int srcOffset, int len)
{
IntPtr intPtr = getIntPtr(dst, dstOffset);
System.Runtime.InteropServices.Marshal.Copy(src, srcOffset, intPtr, len);
}
IntPtr getIntPtr(byte[] buffer, int offset)
{
IntPtr intPtr;
unsafe
{
fixed (byte* p1 = buffer)
{
byte* p2 = p1 + offset;
intPtr = (IntPtr)p2;
}
}
return intPtr;
}
Questions:
A. I guess option 2 is faster than option 1, is it right?
B. Is there another faster method?
Thanks a lot.

Option #2 is broken, since you're using the pointer after the object it points to is no longer fixed. Pointers obtained within a fixed block may only be used inside that same fixed block. And it seems like you should have used Marshal.UnsafeAddrOfPinnedArrayElement anyway (and use it only inside a fixed block pinning the array).
Have a look at Buffer.BlockCopy.

Related

C#~How to read MultiLevelPointer?

I'm struggling a bit on this part...
I want to do this in CE!(that is read the value 20 in my c# app)
However my code is not working...
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, ref IntPtr lpNumberOfBytesRead);
public int ReadInt32(IntPtr address, int[] pointers)
{
/* FOR REFERENCE ONLY! PSEUDO-CODE
ReadProcessMemory(..., ModuleBaseAddress + 0x010F418, Temporary, ..., ...); // -> 0x02A917F8
ReadProcessMemory(..., 0x02A917F8+0x48, Temporary, .....,.); // -> 0x02A9A488
[02A9A488] = 20
*/
IntPtr bytesRead = IntPtr.Zero;
byte[] _buff = new byte[sizeof(int)];
int offIndex = 0;
IntPtr finalval = address;
Console.WriteLine("[BASE] {0:x}", (int)address);
foreach(int PointerOffs in pointers)
{
ReadProcessMemory(hProcess, address, _buff, _buff.Length, ref bytesRead);
finalval += pointers[offIndex];
Console.WriteLine("[Curr ADDRESS] {0:x}", finalval);
offIndex++;
}
return BitConverter.ToInt32(_buff, 0);
}
And this is how I access the method:
int currAmmo = (int) pReader.ReadInt32((IntPtr)LocalPlayer.BaseAddress, LocalPlayer.oMGAmmo);
Console.Write("[AMMO] {0}\n", currAmmo);
Your function has enough problems to warrant a replacement, I tried to fix it but it was easier just to start fresh. By utilizing a pre increment instead of a post increment you will de-reference the first pointer before adding an offset which is ideal.
public static int ReadInt32(IntPtr hProc, IntPtr ptr, int[] offsets)
{
IntPtr addr = ptr;
var buffer = new byte[4];
for (int i = 0; i < offsets.Length; ++i)
{
ReadProcessMemory(hProc, addr, buffer, buffer.Length, out var read1);
addr = IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), offsets[i]);
}
ReadProcessMemory(hProc, addr, buffer, 4, out var read);
return BitConverter.ToInt32(buffer, 0);
}
I learned C# today just to answer this question :)

IntPtr to Callback function

I am using FFMPEG in C# and have the following function prototpe:
public static extern AVIOContext* avio_alloc_context(byte* buffer, int buffer_size, int write_flag, void* opaque, IntPtr read_packet, IntPtr write_packet, IntPtr seek);
In C/C++ this function is declared as follows:
avio_alloc_context (unsigned char *buffer, int buffer_size, int write_flag, void *opaque, int(*read_packet)(void *opaque, uint8_t *buf, int buf_size), int(*write_packet)(void *opaque, uint8_t *buf, int buf_size), int64_t(*seek)(void *opaque, int64_t offset, int whence))
In C/C++ I can do the following to call this function:
int readFunction(void* opaque, uint8_t* buf, int buf_size)
{
// Do something here
int numBytes = CalcBytes();
return numBytes;
}
int64_t seekFunction(void* opaque, int64_t offset, int whence)
{
// Do seeking here
return pos;
}
AVIOContext * avioContext = avio_alloc_context(ioBuffer, ioBufferSize, 0, (void*)(&fileStream), &readFunction, NULL, &seekFunction);
Where the readFunction and seekFunction are callback functions that are used in reading/seeking etc.
I am unsure how to copy this behaviour in the C# version of the code when it expects an IntPtr. How can I create the callback functions and pass them in the C# version?
Turns out you can do this, however it is not entirely intuitive.
First you need to create a delegate with the UnmanagedFunctionPointer and ensure the params can be passed
back from the callee to the caller after being modified using [In, Out]
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate int av_read_function_callback(IntPtr opaque, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2), In, Out] byte[] endData, int bufSize);
In the function we can then marshal this delegate as follows:
private av_read_function_callback mReadCallbackFunc;
mReadCallbackFunc = new av_read_function_callback(ReadPacket);
mAvioContext = FFmpegInvoke.avio_alloc_context(mReadBuffer, mBufferSize, 0, null, Marshal.GetFunctionPointerForDelegate(mReadCallbackFunc), IntPtr.Zero, IntPtr.Zero);
where ReadPacket looks something like
public int ReadPacket(IntPtr opaque, byte[] endData, int bufSize)
{
// Do stuff here
}
This results in the same behaviour as a function pointer in C++.

C# Scan for Memory Address Efficiently

I've written a memory editor class that can read and write memory, but what I need to do is to scan the program's memory, and find the list of memory addresses that contain the memory I'm searching for.
This is the memory editor class.
class MemoryEditor
{
public const uint DELETE = 0x00010000;
public const uint READ_CONTROL = 0x00020000;
public const uint WRITE_DAC = 0x00040000;
public const uint WRITE_OWNER = 0x00080000;
public const uint SYNCHRONIZE = 0x00100000;
public const uint END = 0xFFF;
public const uint PROCESS_ALL_ACCESS = (DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER | SYNCHRONIZE | END);
public Process targetedProcess;
[DllImport("kernel32.dll")]
public static extern int OpenProcess(uint dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesRead);
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(int hProcess, int lpBaseAddress, byte[] buffer, int size, int lpNumberOfBytesWritten);
public Process targetProcess(string name, int index = 0)
{
return (targetedProcess = Process.GetProcessesByName(name)[index]);
}
public int getHandle(Process proc, uint access = PROCESS_ALL_ACCESS)
{
return OpenProcess(access, false, proc.Id);
}
public byte[] getBytesFromString(string str)
{
return Encoding.Unicode.GetBytes(str);
}
public string getStringFromBytes(byte[] byteArr)
{
return Encoding.Unicode.GetString(byteArr);
}
public int makeHex(string str)
{
return (int.Parse(str, System.Globalization.NumberStyles.HexNumber));
}
public byte[] ReadMemory(int address, int processSize)
{
byte[] buffer = new byte[processSize];
ReadProcessMemory(getHandle(targetedProcess), address, buffer, processSize, 0);
return buffer;
}
public List<int> GetAddress(byte[] memory, int index = 0)
{
List<int> buf = new List<int>();
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
buf.Add(i);
return buf;
}
public void WriteMemory(int address, byte[] processBytes)
{
WriteProcessMemory(getHandle(targetedProcess), address, processBytes, processBytes.Length, 0);
}
public int GetObjectSize(object TestObject)
{
BinaryFormatter bf = new BinaryFormatter();
MemoryStream ms = new MemoryStream();
byte[] Array;
bf.Serialize(ms, TestObject);
Array = ms.ToArray();
return Array.Length;
}
}
And here is the function to try to find the memory addresses
public List<int> GetAddress(byte[] memory, int index = 0)
{
List<int> buf = new List<int>();
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
buf.Add(i);
return buf;
}
It lags extremely badly, and I'm only targeting notepad. When I scan memory in Cheat Engine, it finds it immediately, without any lag. My program scans from 0, to the max value of an int, but Cheat Engine does it 0 to the max value of a long, so I don't know what I'm doing wrong.
Any way I can do this efficiently?
There are several problems I see right away.
1. You're only reading one byte at a time:
ReadMemory(makeHex(i.ToString()), 1)
I'm not certain, but I would assume that a call to ReadProcessMemory requires a system call to execute, and doing this for every byte is certainly going to be one source of slowdown. Instead, you should read some size of "block" and then scan through that block in your process. (Doing one page at a time may be the most efficient.)
2. Why in the world are you doing all of the conversions back-and-forth to strings?!
public int makeHex(string str)
{
return (int.Parse(str, System.Globalization.NumberStyles.HexNumber));
}
....
for (int i = 0; i < int.MaxValue; i++)
if (ReadMemory(makeHex(i.ToString()), 1) == memory)
Every iteration of that loop, you're converting i to a string (the default, decimal - not hex), and then immediately passing it to makeHex which parses it (as hex, always) back to an integer. What's the point of this? Just pass the integer! These conversions can be very expensive.
<pedantic>By the way, the name "makeHex" doesn't make sense - it's going from hex, and making an integer.</pedantic>

Marshal float* to C#

I have a DLL which exports a function that returns a float*, that I would like to use it in my C# code. I am not sure how to Marshal my float* so that I can safely use it in C#.
So, in my C++ DLL, I have declared:
static float* GetSamples(int identifier, int dataSize);
In my C# script, I have:
[DllImport ("__Internal")]
public static extern float[] GetSamples (int identifier, int dataSize);
The C++ GetSamples(int,int) allocates memory and return a pointer t the float array. How do I declare the C# GetSamples to Marshal my float array, and how do I access the data (either by iteration or Marshal.Copy)?
Also, can I delete the float* from C# or do I have to call another C++ function to delete the allocated memory?
EDIT:
So this is what I have tried up to now.
First, on the C# side:
Declaration:
[DllImport ("__Internal")]
public static extern int GetSamples ([In, Out]IntPtr buffer,int length, [Out] out IntPtr written);
Trying to call it:
IntPtr dataPointer = new IntPtr();
IntPtr outPtr;
GetSamples(dataPointer, data.Length, out outPtr);
for (var i = 0; i < data.Length; i++){
copiedData[i] = Marshal.ReadByte(dataPointer, i);
}
Then in my C++ lib:
int AudioReader::RetrieveSamples(float * sampleBuffer, size_t dataLength, size_t * /* out */ written)
{
float* mydata = new float[dataLength];
//This is where I copy the actual data into mydata
memcpy(sampleBuffer, mydata, dataLength*sizeof(float));
delete data;
return dataLength;
}
I don't really know what outPtr is for... And I know I have some additional copying steps that I can removes, I just want to get it working for now.
So this is a bit of a complicated answer...
.NET doesn't know how to handle C++ memory allocation, so regardless returning a float * is dangerous at best for this. Furthermore the .NET memory model is based on COM so it is CoTaskMemAlloc based, not that it really helps you here. So here is what I would suggest:
int AudioReader::RetrieveSamples(
float * sampleBuffer,
int dataLength,
int * /* out */ written)
{
// assuming mydata is already defined
if(sampleBuffer == NULL || dataLength == 0)
{
*written = sizeof(mydata);
return -1;
}
ZeroMemory(sampleBuffer, dataLength);
int toCopy = min(dataLength, sizeof(myData));
//This is where I copy the actual data into mydata
memcpy(sampleBuffer, mydata, toCopy);
*written = toCopy;
return 0;
}
[DLLImport("__internal")]
private static extern int GetSamples(
[In, Out]IntPtr buffer,
[In] int length,
[Out] out int written);
float[] RetrieveFloats()
{
int bytesToAllocate = 0;
GetSamples(IntPtr.Zero, 0, out bytesToAllocate);
if(bytesToAllocate == 0)
return null;
int floatCount = bytesToAllocate/ sizeof(float);
float[] toReturn = new float[floatCount];
IntPtr allocatedMemory = Marshal.AllocHGlobal(bytesToAllocate);
int written = 0;
if(GetSamples(allocatedMemory, bytesToAllocate, out written) != -1)
{
floatCount = written/sizeof(float);
Marshal.Copy(allocatedMemory, toReturn, 0, floatCount);
}
Marshal.FreeHGlobal(allocatedMemory);
return toReturn;
}
Passing a bufferLength of zero would return the space required for the buffer, which can then be allocated and passed in.
You will need to allocate the memory for the buffer in C#, you cannot allocate it in C++

Passing byte array between C++ and C# ByRef raises AccessViolationException

I am trying to create a Win32 DLL exposes some functions which are called in C# as follows
__declspec(dllexport) int GetData(unsigned char* *data, int* size)
{
try
{
int tlen = 3;
unsigned char* tchr = new unsigned char[5];
tchr[0] = 'a';
tchr[1] = 'b';
tchr[2] = 'c';
*size = tlen;
*data = tchr;
return 1;
}
catch (char *p)
{
return 0;
}
}
And on C# side
[DllImport("MyDll.dll")]
static extern int GetData(ref byte[] data, ref int size);
static void Main()
{
try
{
int hr = 0;
byte[] gData = null;
int gSize = 0;
hr = GetData(ref gData, ref gSize);
Console.WriteLine(gSize);
for (int i = 0; i < gSize; i++)
Console.WriteLine((char)gData[i]);
}
catch (Exception p)
{
Console.WriteLine(p.ToString());
}
}
When I run C# code, AccessViolationException happens on GetData function which is a sign of exception in C++ code however, following C++ code snippet works fine without any error.
int _tmain(int argc, _TCHAR* argv[])
{
unsigned char* data = NULL;
int size = NULL;
GetData(&data, &size);
printf("%d", size);
for (int i = 0; i < size; i++)
printf("%c,", data[i]);
return 0;
}
If you compare C# main function and C++ _tmain, they are almost analoguous so where I may make a mistake?
You are returning an array allocated by a call to C++ new and hoping that the marshaler will turn it into a C# byte[]. That won't happen.
You'll need to pass a pointer by reference and then marshal it by hand. Your p/invoke should look like this:
[DllImport("MyDll.dll")]
static extern int GetData(out IntPtr data, out int size);
When the function returns data will point to the array and you can read the contents using the Marshal class. I guess you would copy it to a new byte array.
var arr = new byte[size];
Marshal.Copy(data, arr, 0, size);
Some other points:
The calling conventions do not match. The native side is cdecl and the managed is stdcall.
You'll need to export a deallocator to delete the memory returned by the native function. Consider a re-design where the caller allocates the buffer.

Categories

Resources