I have written a C# application that injects a DLL into a third-party executable (which happens to have been built using the Qt framework). This DLL uses EasyHook to intercept calls to a number of specific functions. When my injected code is called, I then try to inspect some of the objects that are parameters to these functions.
For example, I have intercepted a call made to parse some XML:
virtual bool __thiscall QXmlSimpleReader::parse(class QXmlInputSource const &)
In my C# code, I have a PInvoke signature to match this:
static extern bool XmlParse(IntPtr Reader, IntPtr Source)
I would like to call the "data()" function which is a member of the "Source" class. That is, the QXmlSimpleReader parses the raw XML from the QXmlInputSource, but before it does so, I am trying to inspect the raw XML via this "data()" function.
On the advice of one of the experts here, I have tried to use C++/CLI to access the object natively (see Calling methods in third-party DLLs ). I have constructed a wrapper object in C++ that accepts the IntPtr from the C# code:
Header:
public ref class QXmlInputSource
{
public:
// Constructor must be called with C# IntPtr
QXmlInputSource(IntPtr Ptr);
bool LoadQt(void);
bool UnloadQt(void);
String^ Data();
private:
// Pointer to the native Qt object
void * Native;
HINSTANCE DllHandle;
// SIGNATURE: virtual QString QXmlInputSource::data() const
typedef void * (__thiscall *QXmlInputSource_Data)(void *);
QXmlInputSource_Data fpData;
};
CPP file:
QXmlInputSource::QXmlInputSource(IntPtr Ptr)
{
LoadQt();
Native = Ptr.ToPointer();
}
bool QXmlInputSource::LoadQt(void)
{
FARPROC Addr;
/* get handle to dll */
std::wstring LibName = QtPath + QtXml;
DllHandle = LoadLibrary(LibName.c_str());
/* get pointer to the function in the dll*/
Addr = GetProcAddress(HMODULE (DllHandle), "?data@QXmlInputSource@@UBE?AVQString@@XZ");
fpData = QXmlInputSource_Data(Addr);
return true;
}
bool QXmlInputSource::UnloadQt()
{
/* Release the Dll */
FreeLibrary(DllHandle);
return true;
}
String^ QXmlInputSource::Data()
{
void* Ptr = fpData(Native);
return "EPIC FAIL";
}
The Qt-based application crashes when I try to call the fpData() function pointer. Help :P
Some additional information which may or may not help:
I have successfully called functions on "simpler" objects, such as QString.count() and QString.data() using the same methodology. (QString seems to be just a lightweight wrapper for a standard unicode string).
In the QtXml4.dll file that contains the XML functions I am interested in, there are actually TWO parse() methods; one where the Source is a const &, and in the other, Source is a const *. I have no idea if I should be using one or the other. I don't think my signatures will change in any event.
While I was trying to play around, I tried dereferencing the IntPtr in the C# code and passing it to C++:
IntPtr DerefSrc = (IntPtr)Marshal.PtrToStructure(Source, typeof(IntPtr));
If I print out the values of these two IntPtrs, Source has a value of around 3.5Mb, while the DerefSrc has a value of 1.6Gb - which roughly matches the address of the QtXml4.dll in memory. My guess is that the 3.5Mb is a relative offset, while the DerefSrc is clearly an absolute reference. Is it worth a shot converting the DerefSrc to a relative address and passing that to C++ instead ... ?