I am using the method below to read bytes in memory. I want to read values in memory addresses which are very near each other. Previously I have been making individual calls for each byte in memory and adding the result to an array using a for loop. This became really inefficient, so instead I want to adapt the below code to read a large block of memory and then try to do an itteration through the array to pull out the bytes I want. I have spent a bit of time trying to work it out, but really struggling. FYI, this method reads a pointer, and then if that value is a pointer, it reads that pointer, and so forth until it gets to the static address then reads the byte value at that address.
[DllImport("kernel32", EntryPoint = "ReadProcessMemory")]
private static extern byte ReadProcessMemoryByte(int Handle, int Address, ref byte Value, int Size, ref int BytesRead);
public static byte ReadPointerByte(string EXENAME, int Pointer, int[] Offset)
{
byte Value = 0;
checked
{
try
{
Process[] Proc = Process.GetProcessesByName(EXENAME);
if (Proc.Length != 0)
{
int Bytes = 0;
int Handle = OpenProcess(PROCESS_ALL_ACCESS, 0, Proc[0].Id);
if (Handle != 0)
{
foreach (int i in Offset)
{
ReadProcessMemoryInteger((int)Handle, Pointer, ref Pointer, 4, ref Bytes);
Pointer += i;
}
ReadProcessMemoryByte((int)Handle, Pointer, ref Value, 2, ref Bytes);
CloseHandle(Handle);
}
}
}
catch
{ }
}
return Value;
}
What I have so far:
private void label1_Click(object sender, EventArgs e)
{
int[] valuesSeperated[200];
List<byte> PreArray = new List<byte>();
Process[] test = Process.GetProcessesByName("MyProcess"); //Get process handle
int baseAddress = test[0].MainModule.BaseAddress.ToInt32(); //Get base address
byte ReadX = MyClass.ReadPointerByte("MyProcess", BaseAddress, new int[] { 0xc, 0x0, 0x2 }); //call memory reading function (including memory offsets)
PreArray.Add(ReadX);
byte[] PreArrayToInt = PreArray.ToArray();
int[] MYConvertedBytes = PreArray ToInt.Select(x => (int)x).ToArray();
foreach (int i in MYConvertedBytes)
{
valuesSeperated // (don't really know what to do here, if the read was successful I would have a long number at [0], so now need to seperate these as if I had read each one in memory one at a time.
}
string TestString = MYConvertedBytes[0].ToString();
label1.Text = TestString;
}
So to summarize: I don't know how to read a larger block of memory (say 200 addresses at once) using the above method. I don't know how best to extract the values from the resulting array to form a new array that has the bytes now separated. Please ask if anything is unclear, I am quite new and really want to learn so any hints/help would be really appreciated.
Your interop signature looks completely wrong to me.
The c signature is:
BOOL WINAPI ReadProcessMemory(
__in HANDLE hProcess,
__in LPCVOID lpBaseAddress,
__out LPVOID lpBuffer,
__in SIZE_T nSize,
__out SIZE_T *lpNumberOfBytesRead
);
It should be something like:
[DllImport("kernel32", EntryPoint = "ReadProcessMemory",SetLastError=true)]
private static extern unsafe bool NativeReadProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte* buffer, IntPtr size, out IntPtr bytesRead);
static unsafe void ReadProcessMemory(IntPtr processHandle, IntPtr baseAddress, byte[] buffer,int start, int size)
{
fixed(byte* pBuffer=buffer)
{
IntPtr bytesRead;
if(!NativeReadProcessMemory(processHandle, baseAddress, pBuffer+start,(IntPtr)size, out bytesRead))
throw new Win32Exception(Marshal.GetLastWin32Error());
if((int)bytesRead!=size)
throw new Exception("Incomplete read");//User better exception type here
}
}
Related
I want to create a function in c++ that takes two parameter(char[], int) and modifies the parameters(Similar to out parameter in c#) and then create a dll that can be used in c#.
C++ Sample Code:
static void funct(char * name, int size)
{
char[] testName="John";
name=&testName;
size=5;
}
C# Sample Code:
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(StringBuilder name, int size);
This is not correct code. It is just to give an idea of what I want. I want to use c# to access the c++ function through dll and obtain the name and size(no of characters).
Use pointers in the C++ side and marshal these by ref on the C# side.
static void funct(char** name, int* size)
{
char[] testName="John";
*name=&testName;
*size=5;
}
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(ref StringBuilder name, ref int size);
Beware with the char array, it may create memory leaks or worse crashes, it would be better to first test the size of the buffer and the size of the data you want to pass to C#, if there is enough room copy it, else inform to C# that it needs more size so it's allocated by C#.
Something like this:
static int funct(char** name, int* size, int bufferSize)
{
if(bufferSize < 4)
return 4;
char[] testName="John";
memcpy(name*, &char[0], 4);
*size=5;
return -1;
}
const string dllLocation = "D:\\Test.dll";
[DllImport(dllLocation, CallingConvention = CallingConvention.Cdecl)]
private static extern void funct(ref StringBuilder name, ref int size, int bufferSize);
StringBuilder sb = null;
int size = 0;
//Request size
int neededSize = funct(ref sb, ref size, 0);
//Create buffer with appropiate size
sb = new StringBuilder(neededSize);
//Call with the correct size, test result.
if(funct(ref sb, ref size, neededSize) != -1)
throw new Exception();
I am trying to write to process memory, so I copied the code from a video.
But this video does not show the function "ReadInt32", can someone send me to finally be able to run this application?
ReadInt32(process, (IntPtr)address)
public static long GetRealAddress(IntPtr process, IntPtr baseAddress, int[] offsets)
{
var address = baseAddress.ToInt64();
foreach (var offset in offsets)
{
address = ReadInt32(process, (IntPtr)address) + offset;
}
return address;
}
Error Highlighted in Code:
Pointer: (The type is float)
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(IntPtr handle, IntPtr baseAddress,
byte[] buffer, int size, out IntPtr lpNumberOfBytesRead);
public static int ReadInt32(IntPtr processHandle, IntPtr address)
{
byte[] buffer = new byte[4];
ReadProcessMemory(processHandle, address,
buffer, buffer.Length, out IntPtr bytesRead);
// if this gives the wrong value:
// Array.Reverse(buffer);
var myInt = BitConverter.ToInt32(buffer, 0);
return myInt;
}
Need to load this C++ method from a DLL in CSharp and I'm wondering which datatypes I have to use?
WORD FunA (BYTE Num, BYTE *pFrameTX, DWORD nbbitTX, BYTE
*pFrameRX, DWORD *pnbbitRX)
My first approach was:
[DllImport("Example.Dll")]
public static extern UInt16 FunA(byte Num, Byte[] pFrameTX, UInt32 nbbitTX, ref Byte[] pFrameRX, ref UInt32 pnbbitRX);
Byte[] toSend = new Byte[1], toReceive = new Byte[1024];
toSend[0] = 0x26;
UInt32 numberOfBitsReceived = 0;
FunA(Convert.ToByte(1), toSend, 0, ref toReceive, ref numberOfBitsReceived);
What's wrong here? Can someone help me to find the correct datatypes and calling usage?!
Thanks!
Guess you missed the ref modifier in front of pFrameTX.
[DllImport("Example.Dll")]
public static extern UInt16 FunA(byte Num, ref Byte[] pFrameTX, UInt32
nbbitTX, ref Byte[] pFrameRX, ref UInt32 pnbbitRX);
[DllImport("Example.Dll")]
public static extern UInt16 FunA(byte Num, IntPtr pFrameTX, UInt32
nbbitTX, IntPtr pFrameRX, ref UInt32 pnbbitRX);
// ...
Byte[] toSend = new Byte[1], toReceive = new Byte[1024];
toSend[0] = 0x26;
UInt32 numberOfBitsReceived = 0;
// reserve unmanaged memory for IntPtr
IntPtr toSendPtr = Marshal.AllocHGlobal(Marshal.SizeOf(toSend[0])*toSend.Length),
toReceivePtr = Marshal.AllocHGlobal(Marshal.SizeOf(toReceive[0])*toReceive.Length);
// copy send buffer to Unmanaged memory
Marshal.Copy(toSend, 0, toSendPtr, toSend.Length);
// call C++ DLL method
FunA(Convert.ToByte(1), toSendPtr, 0, toReceivePtr, ref numberOfBitsReceived);
// copy receive buffer from Unmanaged to managed memory
Marshal.Copy(toReceivePtr, toReceive, 0, numberOfBitsReveived/8);
// free memory
Marshal.FreeHGlobal(toSendPtr);
Marshal.FreeHGlobal(toReceivePtr);
I have c# method ReadBytesInTask, which is called from c++ code, using function pointer acquired with Marshal.GetFunctionPointerForDelegate method.
ReadBytesInTask gets ptr to unmanaged short[] array populates it and sends back to unmanaged code. Array is unmarshalled to unmanaged memory correctly inside method, but c++ gets only zero populated array.
What should I do?
[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Auto)]
private delegate int BytesReader([In,Out] IntPtr buffer, int samplesCount, string taskId);
private static readonly BytesReader _readBytesInTask = ReadBytesInTask;
private static int ReadBytesInTask(IntPtr buffer, int samplesCount)
{
var bufferSize = samplesCount;
var samplesToRead = bufferSize <= task.Buffer.Length - task.Offset ? bufferSize : task.Buffer.Length - task.Offset;
buffer = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(short))*samplesToRead);
Marshal.Copy(task.Buffer, task.Offset, buffer, samplesToRead);
task.Offset += samplesToRead;
if (samplesToRead < bufferSize) task.Offset = 0;
return samplesToRead;
}
You are changing the pointer and not what it points to. So you will need a pointer to pointer. So it would be something like this:
private static int ReadBytesInTask(IntPtr* buffer, int samplesCount)
I've successfully read a PE header from an unmanaged module loaded into memory by another process. What I'd like to do now is read the names of this module's exports. Basically, this is what I have so far (I've left out a majority of the PE parsing code, because I already know it works):
Extensions
public static IntPtr Increment(this IntPtr ptr, int amount)
{
return new IntPtr(ptr.ToInt64() + amount);
}
public static T ToStruct<T>(this byte[] data)
{
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
public static byte[] ReadBytes(this Process process, IntPtr baseAddress, int size)
{
int bytesRead;
byte[] bytes = new byte[size];
Native.ReadProcessMemory(process.Handle, baseAddress, bytes, size, out bytesRead);
return bytes;
}
public static T ReadStruct<T>(this Process process, IntPtr baseAddress)
{
byte[] bytes = ReadBytes(process, baseAddress, Marshal.SizeOf(typeof(T)));
return bytes.ToStruct<T>();
}
public static string ReadString(this Process process, IntPtr baseAddress, int size)
{
byte[] bytes = ReadBytes(process, baseAddress, size);
return Encoding.ASCII.GetString(bytes);
}
GetExports()
Native.IMAGE_DATA_DIRECTORY dataDirectory =
NtHeaders.OptionalHeader.DataDirectory[Native.IMAGE_DIRECTORY_ENTRY_EXPORT];
if (dataDirectory.VirtualAddress > 0 && dataDirectory.Size > 0)
{
Native.IMAGE_EXPORT_DIRECTORY exportDirectory =
_process.ReadStruct<Native.IMAGE_EXPORT_DIRECTORY>(
_baseAddress.Increment((int)dataDirectory.VirtualAddress));
IntPtr namesAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNames);
IntPtr nameOrdinalsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNameOrdinals);
IntPtr functionsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfFunctions);
for (int i = 0; i < exportDirectory.NumberOfFunctions; i++)
{
Console.WriteLine(_process.ReadString(namesAddress.Increment(i * 4), 64));
}
}
When I run this, all I get is a pattern of double question marks, then completely random characters. I know the header is being read correctly, because the signatures are correct. The problem has to lie in the way that I'm iterating over the function list.
The code at this link seems to suggest that the names and ordinals form a matched pair of arrays, counted up to NumberOfNames, and that the functions are separate. So your loop may be iterating the wrong number of times, but that doesn't explain why you're seeing bad strings from the very beginning.
For just printing names, I'm having success with a loop like the one shown below. I think the call to ImageRvaToVa may be what you need to get the correct strings? However I don't know whether that function will work unless you've actually loaded the image by calling MapAndLoad -- that's what the documentation requests, and the mapping did not seem to work in some quick experiments I did using LoadLibrary instead.
Here's the pInvoke declaration:
[DllImport("DbgHelp.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ImageRvaToVa(
IntPtr NtHeaders,
IntPtr Base,
uint Rva,
IntPtr LastRvaSection);
and here's my main loop:
LOADED_IMAGE loadedImage = ...; // populated with MapAndLoad
IMAGE_EXPORT_DIRECTORY* pIID = ...; // populated with ImageDirectoryEntryToData
uint* pFuncNames = (uint*)
ImageRvaToVa(
loadedImage.FileHeader,
loadedImage.MappedAddress,
pIID->AddressOfNames,
IntPtr.Zero);
for (uint i = 0; i < pIID->NumberOfNames; i++ )
{
uint funcNameRVA = pFuncNames[i];
if (funcNameRVA != 0)
{
char* funcName =
(char*) (ImageRvaToVa(loadedImage.FileHeader,
loadedImage.MappedAddress,
funcNameRVA,
IntPtr.Zero));
var name = Marshal.PtrToStringAnsi((IntPtr) funcName);
Console.WriteLine(" funcName: {0}", name);
}
}