I am trying to convert an array of the RECT structure (given below) into an IntPtr, so I can send the pointer using PostMessage to another application.
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
// lots of functions snipped here
}
// so we have something to send, in reality I have real data here
// also, the length of the array is not constant
RECT[] foo = new RECT[4];
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf(foo[0]) * 4);
Marshal.StructureToPtr(foo, ptr, true); // -- FAILS
This gives an ArgumentException on the last line ("The specified structure must be blittable or have layout information."). I need to somehow get this array of RECTs over to another application using PostMessage, so I really need a pointer to this data.
What are my options here?
UPDATE: This seems to work:
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Win32.RECT)) * foo.Length);
IntPtr c = new IntPtr(result.ToInt32());
for (i = 0; i < foo.Length; i++)
{
Marshal.StructureToPtr(foo[i], c, true);
c = new IntPtr(c.ToInt32() + Marshal.SizeOf(typeof(Win32.RECT)));
}
UPDATED AGAIN to fix what arbiter commented on.
StructureToPtr expects struct object, and foo is not structure it is array, that is why exception occurs.
I can suggest you to write structures in cycle (sadly, StructureToPtr does not have overload with Index):
long LongPtr = ptr.ToInt64(); // Must work both on x86 and x64
for (int I = 0; I < foo.Length; I++)
{
IntPtr RectPtr = new IntPtr(LongPtr);
Marshal.StructureToPtr(foo[I], RectPtr, false); // You do not need to erase struct in this case
LongPtr += Marshal.SizeOf(typeof(Rect));
}
Another option is to write structure as four integers, using Marshal.WriteInt32:
for (int I = 0; I < foo.Length; I++)
{
int Base = I * sizeof(int) * 4;
Marshal.WriteInt32(ptr, Base + 0, foo[I].Left);
Marshal.WriteInt32(ptr, Base + sizeof(int), foo[I].Top);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 2, foo[I].Right);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 3, foo[I].Bottom);
}
And the last, you can use unsafe keyword, and work with pointers directly.
Arbiter has given you one good answer for how to marshal arrays of structs. For blittable structs like these I, personally, would use unsafe code rather than manually marshaling each element to unmanaged memory. Something like this:
RECT[] foo = new RECT[4];
unsafe
{
fixed (RECT* pBuffer = foo)
{
//Do work with pointer
}
}
or you could pin the array using a GCHandle.
Unfortunately, you say you need to send this information to another process. If the message you are posting is not one of the ones for which Windows provides automatic marshaling then you have another problem. Since the pointer is relative to the local process it means nothing in the remote process and posting a message with this pointer will cause unexpected behavior, including likely program crash. So what you need to do is write the RECT array to the other process' memory not your own. To do this you need to use OpenProcess to get a handle to the process, VitualAllocEx to allocate the memory in the other process and then WriteProcessMemory to write the array into the other process' virtual memory.
Unfortunately again, if you are going from a 32bit process to a 32bit process or from a 64bit process to a 64bit process things are quite straightforward but from a 32bit process to a 64bit process things can get a little hairy. VirtualAllocEx and WriteProcessMemory are not really supported from 32 to 64. You may have success by trying to force VirtualAllocEx to allocate its memory in the bottom 4GB of the 64bit memory space so that the resultant pointer is valid for the 32bit process API calls and then write with that pointer. In addition, you may have struct size and packing differences between the two process types. With RECT there is no problem but some other structs with packing or alignment issues might need to be manually written field by field to the 64bit process in order to match the 64bit struct layout.
You could try the following:
RECT[] rects = new RECT[ 4 ];
IntPtr[] pointers = new IntPtr[4];
IntPtr result = Marshal.AllocHGlobal(IntPtr.Size * rects.Length);
for (int i = 0; i < rects.Length; i++)
{
pointers[i] = Marshal.AllocHGlobal (IntPtr.Size);
Marshal.StructureToPtr(rects[i], pointers[i], true);
Marshal.WriteIntPtr(result, i * IntPtr.Size, pointers[i]);
}
// the array that you need is stored in result
And don't forget to free everything after you are finished.
I was unable to get this solution to work. So, I did some searching and the solution given here worked for me.
http://social.msdn.microsoft.com/Forums/en-US/clr/thread/dcfd6310-b03b-4552-b4c7-6c11c115eb45
Related
I'm trying to use Marshal.GetDelegateForFunctionPointer to execute a LdrLoadDll's syscall stub that I get from disk using my code, the code uses Marshal.AllocHGlobal and later changed the memory protection changed into RWX(this is where the syscall stub from the disk lives). The defined syscall stub size in my code is 23 bytes. And this is the code that I use when I want to use the pointer to the allocated memory containing the syscall stub
// pLdrLoadDll contains the pointer to the allocated memory containing the syscall stub
// LdrLoadDllDelegate is my delegate for LdrLoadDll
Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(pLdrLoadDll, typeof(LdrLoadDllDelegate));
NativeDeclarations.NTSTATUS retValue = (NativeDeclarations.NTSTATUS)funcDelegate.DynamicInvoke(funcargs);
The code returns memory Access Violation when this line get executed
Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(pLdrLoadDll, typeof(LdrLoadDllDelegate));
And I try to use other methods, like this one, and it returns the same error.
LdrLoadDllDelegate fSyscallLdrLoadDll = (LdrLoadDllDelegate)Marshal.GetDelegateForFunctionPointer(pLdrLoadDll, typeof(LdrLoadDllDelegate));
I use the same function to get other syscall stubs and it works just fine using both of the these methods. I also try to use Marshal.GetDelegateForFunctionPointer to execute LdrLoadDll but from the in-memory ntdll and it works fine. This is the only function that I test that doesn't work for my syscall stub extractor function. I literally don't know why it throws out that error.
This is the code I use for extracting syscall stub from disk
public const int SYSCALL_STUB_SIZE = 23;
public static IntPtr GetSyscallStub(string FuncName) {
IntPtr output = IntPtr.Zero;
// get NTDLL full path
string NTDLLFullPath;
try{ NTDLLFullPath = (Process.GetCurrentProcess().Modules.Cast<ProcessModule>().Where(x => "ntdll.dll".Equals(Path.GetFileName(x.FileName), StringComparison.OrdinalIgnoreCase)).FirstOrDefault().FileName); }catch{ NTDLLFullPath = null; }
if (NTDLLFullPath != null) {
// allocate and copy original DLL to unmanaged memory
byte[] NTDLLBytes = System.IO.File.ReadAllBytes(NTDLLFullPath);
IntPtr pNTDLLBytes = Marshal.AllocHGlobal(NTDLLBytes.Length);
Marshal.Copy(NTDLLBytes, 0, pNTDLLBytes, NTDLLBytes.Length);
PEReader NTDLL = new PEReader(NTDLLBytes);
int RegionSize = NTDLL.Is32BitHeader ? (int)NTDLL.OptionalHeader32.SizeOfImage : (int)NTDLL.OptionalHeader64.SizeOfImage;
int SizeOfHeaders = NTDLL.Is32BitHeader ? (int)NTDLL.OptionalHeader32.SizeOfHeaders : (int)NTDLL.OptionalHeader64.SizeOfHeaders;
IntPtr pNTDLLImage = Marshal.AllocHGlobal(RegionSize);
// copying image header
Marshal.Copy(NTDLLBytes, 0, pNTDLLImage, SizeOfHeaders);
// copying sections
for (int i = 0; i < NTDLL.FileHeader.NumberOfSections; i++) {
IntPtr pVASectionBase = (IntPtr)((UInt64)pNTDLLImage + NTDLL.ImageSectionHeaders[i].VirtualAddress);
Marshal.Copy(NTDLLBytes, NTDLL.ImageSectionHeaders[i].PointerToRawData, pVASectionBase, (int)NTDLL.ImageSectionHeaders[i].SizeOfRawData);
}
// allocate unmanaged memory for the syscall stub
IntPtr pSyscallStub = Marshal.AllocHGlobal(SYSCALL_STUB_SIZE); // dont forget to change it to RX later
// get pointer to function
IntPtr pFunc = GetExportAddress(pNTDLLImage, FuncName);
// copy from the function pointer to the allocated memory for syscall stub
byte[] bSyscallStub = new byte[SYSCALL_STUB_SIZE];
Marshal.Copy(pFunc, bSyscallStub, 0, SYSCALL_STUB_SIZE);
Marshal.Copy(bSyscallStub, 0, pSyscallStub, SYSCALL_STUB_SIZE);
// change syscall stub memory to RWX,using RX crashes the process,dont ask me why
uint oldProtect;
VirtualProtect(pSyscallStub, (UIntPtr)SYSCALL_STUB_SIZE, 0x40, out oldProtect);
// free temporary allocations
Marshal.FreeHGlobal(pNTDLLBytes);
Marshal.FreeHGlobal(pNTDLLImage);
output = pSyscallStub;
return output;
}else {
Console.WriteLine("Failed to get NTDLL path.");
return output;
}
}
*GetExportAddress = GetProcAddress
I test the code on Windows 10 v20H2 using the built-in CSC as the compiler. To clear it out, I'm learning about AV/EDR Defense Evasion, cause that I use syscall stubs instead of P/Invoke.
After a bit of debugging on ntdll.dll, it turns out that LdrLoadDll doesn't use a normal syscall stub, cause it's a combination of multiple syscalls. the access violation error is caused by the syscall stub is not complete, cause it's size is not like a normal syscall stub.
In our project we communicate two applications, one in C# and the other in C++, via named pipes. Our intention is to pass memory pointers between them and be able to access the objects pointed by them in either application. Our current code rises a System.AccessViolationException:
System.AccessViolationException:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
So far we are using a shared_ptr that points to a custom struct and writting the pointer to the buffer in C++ as seen below:
typedef struct {
int one;
int a;
int two;
int b;
} DATA_STRUCT; // C++ struct
DATA_STRUCT ds;
ds.one = 10;
ds.a = 5;
ds.two = 99;
ds.b = 0;
shared_ptr<DATA_STRUCT> ptr_ds(new DATA_STRUCT);
shared_ptr<DATA_STRUCT> p(ptr_ds);
*ptr_ds = ds;
const int size = BUFFER_SIZE;
char buf[size];
memset(buf, 0xCC, 100);
while (keepReading)
{
printf("Write message:");
scanf("%s", buf);
memcpy(buf, &p, sizeof(shared_ptr<DATA_STRUCT>));
if (strcmp(buf, "quit") == 0)
keepReading = false;
else
{
WriteFile(hPipe1, buf, dwBytesToWrite, &cbWritten, NULL);
memset(buf, 0xCC, 100);
}
}
Then, in C# we read the whole buffer, we keep the bytes with the relevant information in another buffer (Rc) and convert the byte array to our custom data structure using unsafe IntPtr as you can see below:
buffer = new byte[BUFFER_SIZE];
bytesRead = clientCSharp.stream.Read(buffer, 0, BUFFER_SIZE);
public struct DATA_STRUCT
{
public int one;
public int a;
public int two;
public int b;
}; // C# struct
unsafe
{
Buffer.BlockCopy(buffer, 0, Rc, 0, ReadLength);
DATA_STRUCT ds = new DATA_STRUCT();
IntPtr aux_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
IntPtr final_ptr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(IntPtr)));
Marshal.Copy(Rc, 0, aux_ptr, 4);
final_ptr = (IntPtr)Marshal.PtrToStructure(aux_ptr, typeof(IntPtr));
ds = (DATA_STRUCT)Marshal.PtrToStructure(final_ptr, typeof(IntPtr));
}
The exception rises when we try to access the final_ptr in order to load the DATA_STRUCT, the last code line presented above. Here I give some Debug images:
C++ Debug image with Pointer value written to the named pipe buffer
C# Debug image with Pointer value read from the named pipe reduced buffer (Rc)
Could it be something related to the pointer length? As it seems to me in the C++ application it has 8bytes and in the C# application it has 16bytes? Dhould we declare a safe memory location for C# and C++? If yes, then how could it be done?
Note: Our goal is to work with the unsafe IntPtr in the C# application. In this example we are loading the DATA_STRUCT object because we wanted to be sure that in the C# application we are retrieving the same object passed in the C++ application. The final applications is meant to be used in Windows.
Application data spaces are completely distinct, and have been for many years. you can't simply pass a raw pointer between applications and expect to access the same memory.
The normal approach is to serialise the content of your object, squirt it through your pipe and then reconstruct the object at the receiver.
You can set up named shared memory regions, and these are faster to share large objects (in unix, and I assume in windows), but these shared regions will probably not be located at the same address, so still only good for raw data.
I am trying to port some code from our C++ application to ensure that the licence files are compatible with both applications.
I've tried marking the functions as external, however that opened a whole other can of worms that I wouldn't like to delve into considering this is my last week at my current employer.
The C++ code I'd like to port is as follows:
std::fstream licenceFile(filePath, std::ios::in | std::ios::binary);
licenceFile.read((char *) &this->m_FileData, sizeof(this->m_FileData));
m_FileData is a struct and is as follows:
struct LicManKeyFileData
{
BYTE m_EncryptedKey[255];
WCHAR m_MacAddress[33];
WCHAR m_PreviousMacLicense[33];
WCHAR m_SoftwareName[16];
WCHAR m_ClientName[65];
BYTE m_Version;
BYTE m_EncryptionLength;
time_t m_LicenseTime;
};
I have tried several methods of replicating this in C#, firstly reading the file member by member, for example:
BinaryReader reader = new BinaryReader(licenceFileStream, Encoding.BigEndianUnicode);
licenceFileData.EncryptedKey = reader.ReadBytes(licenceFileData.EncryptedKey.Length);
byte[] mac = new byte[sizeof(char) * licenceFileData.MacAddress.Length];
mac = reader.ReadBytes(mac.Length);
Something strange I noticed about this method is that a lot of the values were being set as 204 seemingly arbitrarily, when they are read correctly in the C++ application, so I've had to add this:
if (mac[0] == 204)
mac[0] = 0;
Which makes no sense to me, it's not an alignment issue, reading from a byte before or after that gives totally garbage values (chinese characters) and this check and assigning 0 to the first index allows me to get the proper value.
Another method I've tried was found on here on StackOverflow, and is as follows:
public static T ReadStruct<T>(this BinaryReader reader) where T : struct
{
Byte[] buffer = new Byte[Marshal.SizeOf(typeof(T))];
reader.Read(buffer, 0, buffer.Length);
GCHandle handle = default(GCHandle);
try
{
handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
return (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
}
finally
{
if (handle.IsAllocated)
handle.Free();
}
}
Oddly, this method also returns some values as 204 where the C++ application reads them as the correct value.
The struct I'm using in C# looks like this:
unsafe struct LicenceFileDataS
{
internal fixed byte m_EncryptedKey[255];
internal fixed char m_MacAddress[33];
internal fixed char m_PreviousMacLicense[33];
internal fixed char m_SoftwareName[16];
internal fixed char m_ClientName[65];
internal byte m_Version;
internal byte m_EncryptionLength;
internal long m_LicenseTime;
}
Does anyone know a better method for porting this code or how I can fix the values that are being read as 204? It works perfectly in C++. My apologies for the wall of text.
How do I find a raw pointer to a managed class in C#, and, hopefully, it's raw size in memory? Obviously, this is not allowed by CLR - more precisely, strictly prohibited, as unmanaged representation of managed classes should never, ever be worked with for both stability and safe reasons - so I'm looking for a hack. I'm not looking for serializing - I do actually need a dump of managed class as it is represented in raw memory.
More precisely, I'm looking for something like function getObjectPtr in the following example:
IntPtr getObjectPtr(Object managedClass) {...}
void main() {
var test=new TestClass();
IntPtr* ptr_to_test=getObjectPtr(test);
Console.WriteLine(ptr_to_test.ToString());
}
Thanks in advance!
EDIT:
I've finally found a solution by myself, and, when came back to post it as an answer, was totally surprised by the amount of so-quickly already posted answers... Thanks to all of you! This was very quick and totally unexpected.
The closest to mine solution was #thehennyy's one, but I'm not posting it since #Chino proposed far better one (sorry I've mistaken it to be wrong at first, I've just forgot to dereference the pointer again). It does not require a code to be unsafe and a bit more tolerates GC:
class Program
{
// Here is the function in case anyone needs it.
// Note, though, it does not preserve the handle while you work with
// pointer, so it is less reliable than the code in Main():
static IntPtr getPointerToObject(Object unmanagedObject)
{
GCHandle gcHandle = GCHandle.Alloc(unmanagedObject, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
gcHandle.Free();
return thePointer;
}
class TestClass
{
uint a = 0xDEADBEEF;
}
static void Main(string[] args)
{
byte[] cls = new byte[16];
var test = new TestClass();
GCHandle gcHandle = GCHandle.Alloc(test, GCHandleType.WeakTrackResurrection);
IntPtr thePointer = Marshal.ReadIntPtr(GCHandle.ToIntPtr(gcHandle));
Marshal.Copy(thePointer, cls, 0, 16); //Dump first 16 bytes...
Console.WriteLine(BitConverter.ToString(BitConverter.GetBytes(thePointer.ToInt32())));
Console.WriteLine(BitConverter.ToString(cls));
Console.ReadLine();
gcHandle.Free();
}
}
/* Example output (yours should be different):
40-23-CA-02
4C-38-04-01-EF-BE-AD-DE-00-00-00-80-B4-21-50-73
That field's value is "EF-BE-AD-DE", 0xDEADBEEF as it is stored in memory. Yay, we found it!
*/
Hovewer, now I'm a bit clueless. According to the this article, first 2 addresses in the class should be pointers to SyncBlock and RTTI structure, and therefore the first field's address must be offset by 2 words [8 bytes in 32-bit systems, 16 bytes in 64-bit systems] from the beginning. Mine is 64-bit; however, as you can see in the output, it is obvious that first field's raw offset from the object's address is only 4 bytes, which doesn't make any sense.
I've asked this as a separate question.
Maybe I should ask this as a separate question, but it is possible that there is an error in my solution.
Hey is this what you want?:
GCHandle gcHandle = GCHandle.Alloc(yourObject,GCHandleType.WeakTrackResurrection);
IntPtr thePointer = GCHandle.ToIntPtr(gcHandle);
You can write a small IL function that leaks an objects address.
var o = new object();
var d = new DynamicMethod("GetPtr", typeof(IntPtr), new Type[] {typeof(object)}, Assembly.GetExecutingAssembly().ManifestModule);
var il = d.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ret);
var address = (IntPtr)d.Invoke(null, new object[] {o});
Console.WriteLine(address);
The source is: IllidanS4 / SharpUtils
/ UnsafeTools.cs
I want to use c# interop to call a function from a dll written in c. I have the header files.
Take a look at this:
enum CTMBeginTransactionError {
CTM_BEGIN_TRX_SUCCESS = 0,
CTM_BEGIN_TRX_ERROR_ALREADY_IN_PROGRESS,
CTM_BEGIN_TRX_ERROR_NOT_CONNECTED
};
#pragma pack(push)
#pragma pack(1)
struct CTMBeginTransactionResult {
char * szTransactionID;
enum CTMBeginTransactionError error;
};
struct CTMBeginTransactionResult ctm_begin_customer_transaction(const char * szTransactionID);
How do I call ctm_begin_customer_transaction from c#. The const char * mapps well to string, but despite various attempts (looking at stackoverflow and other sites), I fail to marshal the return structure. If I define the function to return IntPtr it works ok...
Edit
I changed the return type to IntPtr and use:
CTMBeginTransactionResult structure = (CTMBeginTransactionResult)Marshal.PtrToStructure(ptr, typeof(CTMBeginTransactionResult));
but it throws AccessViolationException
I also tried:
IntPtr ptr = Transactions.ctm_begin_customer_transaction("");
int size = 50;
byte[] byteArray = new byte[size];
Marshal.Copy(ptr, byteArray, 0, size);
string stringData = Encoding.ASCII.GetString(byteArray);
stringData == "70e3589b-2de0-4d1e-978d-55e22225be95\0\"\0\0\a\0\0\b\b?" at this point. The "70e3589b-2de0-4d1e-978d-55e22225be95" is the szTransactionID from the struct. Where is the Enum? Is it the next byte?
There's a memory management problem hidden in this struct. Who owns the C string pointer? The pinvoke marshaller will always assume that the caller owns it so it will try to release the string. And passes the pointer to CoTaskMemFree(), same function as the one called by Marshal.FreeCoTaskMem(). These functions use the COM memory allocator, the universal interop memory manager in Windows.
This rarely comes to a good end, C code does not typically use that allocator unless the programmer designed his code with interop in mind. In which case he'd never have used a struct as a return value, interop always works much less trouble-free when the caller supplies buffers.
So you cannot afford to let the marshaller do its normal duty. You must declare the return value type as IntPtr so it doesn't try to release the string. And you must marshal it yourself with Marshal.PtrToStructure().
That however still leaves the question unanswered, who owns the string? There is nothing you can do to release the string buffer, you don't have access to the allocator used in the C code. The only hope you have is that the string wasn't actually allocated on the heap. That's possible, the C program might be using string literals. You need to verify that guess. Call the function a billion times in a test program. If that doesn't explode the program then you're good. If not then only C++/CLI can solve your problem. Given the nature of the string, a "transaction ID" ought to change a lot, I'd say you do have a problem.
I hate to answer my own question, but I found the solution to marshal the resulting struct. The struct is 8 bytes long (4 bytes for the char * and 4 bytes for enum). Marshalling the string does not work automatically, but the following works:
// Native (unmanaged)
public enum CTMBeginTransactionError
{
CTM_BEGIN_TRX_SUCCESS = 0,
CTM_BEGIN_TRX_ERROR_ALREADY_IN_PROGRESS,
CTM_BEGIN_TRX_ERROR_NOT_CONNECTED
};
// Native (unmanaged)
[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)]
internal struct CTMBeginTransactionResult
{
public IntPtr szTransactionID;
public CTMBeginTransactionError error;
};
// Managed wrapper around native struct
public class BeginTransactionResult
{
public string TransactionID;
public CTMBeginTransactionError Error;
internal BeginTransactionResult(CTMBeginTransactionResult nativeStruct)
{
// Manually marshal the string
if (nativeStruct.szTransactionID == IntPtr.Zero) this.TransactionID = "";
else this.TransactionID = Marshal.PtrToStringAnsi(nativeStruct.szTransactionID);
this.Error = nativeStruct.error;
}
}
[DllImport("libctmclient-0.dll")]
internal static extern CTMBeginTransactionResult ctm_begin_customer_transaction(string ptr);
public static BeginTransactionResult BeginCustomerTransaction(string transactionId)
{
CTMBeginTransactionResult nativeResult = Transactions.ctm_begin_customer_transaction(transactionId);
return new BeginTransactionResult(nativeResult);
}
The code works, but I still need to investigate, if calling the unmanaged code results in memory leaks.