Finding a 3rd party QWidget with injected code & QWidget::find(hwnd) - qt

I have a Qt Dll wich I inject into a third-party Application using windows detours library:
if(!DetourCreateProcessWithDll( Path, NULL, NULL, NULL, TRUE,
CREATE_DEFAULT_ERROR_MODE | CREATE_SUSPENDED, NULL, NULL,
&si, &pi, "C:\\Program Files\\Microsoft Research\\Detours Express 2.1\\bin\\detoured.dll",
"C:\\Users\\Dave\\Documents\\Visual Studio 2008\\Projects\\XOR\\Debug\\XOR.dll", NULL))
and then I set a system-wide hook to intercept window creation:
HHOOK h_hook = ::SetWindowsHookEx(WH_CBT, (HOOKPROC)CBTProc, Status::getInstance()->getXORInstance(), 0);
Where XOR is my programs name, and Status::getInstance() is a Singleton where I keep globals.
In my CBTProc callback, I want to intercept all windows that are QWidgets:
HWND hwnd= FindWindow(L"QWidget", NULL);
which works well, since I get a corresponding HWND (I checked with Spy++)
Then, I want to get a pointer to the QWidget, so I can use its functions:
QWidget* q = QWidget::find(hwnd);
but here's the problem, the returned pointer is always 0. Am I not injecting my code into the process properly? Or am I not using QWidget::find() as I should?
Thanks,
Dave
EDIT:If i change the QWidget::find() function to an exported function of my DLL, after setting the hooks (so I can set and catch a breakpoint), QWidgetPrivate::mapper is NULL.

Answered:
Stupid mistake, I was compiling in Debug, so it was QtGui4d.dll and QtCore4d.dll that where loading, not QtCore4.dll and QtGui.dll

Compare the addresses of `QWidgetPrivate::mapper in the DLL and in your code. Esp. if one is linked statically, there might be two instance of it, each with it's own, disjoint, set of widgets.

Related

setting CilBody.KeepOldMaxStack or MetadataOptions.Flags

While decompiling .net assembly using de4dot I am getting following message in console:
Error calculating max stack value. If the method's obfuscated, set CilBody.KeepOldMaxStack or MetadataOptions.Flags (KeepOldMaxStack, global option) to ignore this error
How do I set CilBody.KeepOldMaxStack or MetadataOptions.Flags?
Maybe a bit late, but I ran into the same problem today, finding your open question while looking for a solution, and this is how I solved it - I hope it works for you, too:
// Working with an assembly definition
var ass = AssemblyDef.Load("filename.dll");
// Do whatever you want to do with dnLib here
// Create global module writer options
var options = new ModuleWriterOptions(ass.Modules[0]);
options.MetadataOptions.Flags |= MetadataFlags.KeepOldMaxStack;
// Write the new assembly using the global writer options
ass.Write("newfilename.dll", options);
If you want to set the flag only for a selection of methods that produce the problem before writing, just for example:
// Find the type in the first module, then find the method to set the flag for
ass.Modules[0]
.Types.First((type) => type.Name == nameof(TypeToFind))
.FindMethod(nameof(MethodToFind))
.KeepOldMaxStack = true;
CilBody is maybe a bit confusing, if you're not too deep into the internal .NET assembly structures: It simply means the body object of the method that produces the problem, when writing the modified assembly. Obfuscators often try to confuse disassemblers by producing invalid structures, what may cause a problem when calculating the maxstack value before writing the assembly with dnLib. By keeping the original maxstack value, you can step over those invalid method structures.
In the context of de4dot it seems to be a bug, or the application is simply not designed to solve invalid method structures of obfuscated assemblies - in this case there's no solution for you, if the de4net developer won't fix/implement it, and you don't want to write a patch using the source code from GitHub.

When Qt-5 will fail the connect

Reading Qt signal & slots documentation, it seems that the only reason for a new style connection to fail is:
"If there is already a duplicate (exact same signal to the exact same slot on the same objects), the connection will fail and connect will return false"
Which means that connection was already successful the first time and does not allow multi-connections when using Qt::UniqueConnection.
Does this means that Qt-5 style connection will always success? Are there any other reasons for failure?
The new-style connect can still fail at runtime for a variety of reasons:
Either sender or receiver is a null pointer. Obviously this requires a check that can only happen at runtime.
The PMF you specified for a signal is not actually a signal. Lacking proper C++ reflection capabilities, all you can do at compile time is checking that the signal is a non-static member function of the sender's class.
However, that's not enough to make it a signal: it also needs to be in a signals: section in your class definition. When moc sees your class definition, it will generate some metadata containing the information that that function is indeed a signal. So, at runtime, the pointer passed to connect is looked up in a table, and connect itself will fail if the pointer is not found (because you did not pass a signal).
The check on the previous point actually requires a comparison between pointers to member functions. It's a particularly tricky one, because it will typically involve different TUs:
one is the TU containing moc-generated data (typically a moc_class.cpp file). In this TU there's the aforementioned table containing, amongst other things, pointers to the signals (which are just ordinary member functions).
is the TU where you actually invoke connect(sender, &Sender::signal, ...), which generates the pointer that gets looked up in the table.
Now, the two TUs may be in the same application, or perhaps one is in a library and the other in your application, or maybe in two libraries, etc; your platform's ABI starts to get into play.
In theory, the pointers stored when doing 1. are identical to the pointers generated when doing 2.; in practice, we've found cases where this does not happen (cf. this bug report that I reported some time ago, where older versions of GNU ld on ARM generated code that failed the comparison).
For Qt this meant disabling certain optimizations and/or passing some extra flags to the places where we know this to happen and break user software. For instance, as of Qt 5.9, there is no support for -Bsymbolic* flags on GCC on anything but x86 and x86-64.
Of course, this does not mean we've found and fixed all the possible places. New compilers and more aggressive optimizations might trigger this bug again in the future, making connect return false, even when everything is supposed to work.
Yes it can fail if either sender or receiver are not valid objects (nullptr for example)
Example
QObject* obj1 = new QObject();
QObject* obj2 = new QObject();
// Will succeed
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
delete obj1;
obj1 = nullptr;
// Will fail even if it compiles
connect(obj1, &QObject::destroyed, obj2, &QObject::deleteLater);
Do not try to register pointer type. I've used the macro
#define QT_REG_TYPE(T) qRegisterMetaType<T>(#T)
with pointer type CMyWidget*, that was the problem. Using the type directly worked.
No it's not always successful. The docs give an example here where connect would return false because the signal should not contain variable names.
// WRONG
QObject::connect(scrollBar, SIGNAL(valueChanged(int value)),
label, SLOT(setNum(int value)));

QPluginLoader.instance() - how does it really work?

I am currently working on a Qt project where dynamic plugin loading is central. I am loading DLLs by using Qt's QPluginLoader. The different plugins are accessed through CameraPluginStructs, defined as follows:
struct CameraPluginStruct
{
QString name;
QString filePath;
CameraPluginInterface* plugin;
QPluginLoader* pluginLoader;
CameraPluginStruct(QString filePath=nullptr, QString name=nullptr):
filePath(filepath), name(name), plugin(nullptr), pluginLoader(nullptr){}
};
To load a plugin, the following function is called:
void loadPlugin(CameraPluginStruct& p)
{
p.pluginLoader = new QPluginLoader(p.filePath);
p.pluginLoader->load();
QObject* possiblePlugin = p.pluginLoader->instance(); //QPluginLoader.instance();
if(possiblePlugin)
{
// cast from QObject to correct type:
p.plugin = qobjectcast<CameraPluginInterface>(possiblePlugin);
}
}
And to unload a plugin, I use this function:
void unloadPlugin(CameraPluginStruct& p)
{
p.pluginLoader->unload(); // QPluginLoader.unload();
p.pluginLoader->~QPluginLoader();
p.pluginLoader = nullptr;
p.plugin = nullptr;
}
I have made a few, simple test plugins that write messages to the console when the constructor is called. For simplicity, let's say that I have two test plugins, DLL A and DLL B. When I load A by using the loadPlugin() function, the constructor in the plugin is called, and the corresponding message is written in the console. I can do the same thing with B, and everything seems to work – B's constructor message is written to the console, and the other functions seem to work as well.
Now, the problem occurs when I try to create another CameraPluginStruct connected to either A or B. No message is written to the console, which leads me to think that the constructor is not called. Even though, I am able to call the other test functions in the plugin with success (DoSomething(), see below). If I unload all CameraPlugins connected to A or B, and then load the DLL again, the constructor is called again on the first load.
The QPluginLoader.instance() call is described as follows in the documentation:
"Returns the root component object of the plugin. (...) The component object is a QObject. Use qobject_cast() to access interfaces you are
interested in." http://doc.qt.io/qt-5/qpluginloader.html#instance
Wouldn't it then be natural that the constructor in the DLL would be called each time, and not only the first time?
As I've understood, a DLL is only loaded once for any program. Therefore I have also tried to use only one QPluginLoader per DLL file, with the same result. Qt also says that:
"Multiple instances of QPluginLoader can be used to access the same physical plugin." http://doc.qt.io/qt-5/qpluginloader.html#details
Therefore I can't see how this can be a source to the problem anyway.
I would really appreciate if anyone could clarify how the QPluginLoader.instance() really works. Why is the constructor – at least how it seems – only called the first time I use the instance() call?
Thank you!
Here is the code found in the DLLs (the output texts differ in A and B):
TestDLL::TestDLL()
{
std::cout << "This is written from the constructor in A \n";
}
QString TestDLL::Name() const
{
return "Hello, writing from Name() \n";
}
void TestDLL::DoSomething() const
{
qDebug() << "Hello, this text comes from DoSomething()"\n;
}
When your plugin is loaded (i.e. the first time QPluginLoader::instance() is called), then a single instance of it is created - this is your root instance. The root instance is the only instance QPluginLoader will ever create for you.
If you want more, then you create a createInstance() or clone() method for your plugin class, so that new instances can be created from the root instance. Or more conventionally, make your plugin class a factory for the class type you wish to expose.

OpenCL: What is the properties argument in the cl::Context constructor for?

I'm new to OpenCL, and have followed this tutorial to get started. Before creating the cl::Context, the tutorial creates a static array of three cl_context_properties which it doesn't explain what it is for, but which it sends as the properties argument in the cl::Context constructor.
However when looking at the reference page for cl::Context, there is no explanation of what the properties parameter is, but it does say that it "is reserved and must be zero". So why does the tutorial send a non-zero value as that argument? What purpose does it serve? And if you have been able to pass that argument before, how does it come that it is suddenly "reserved", doesn't that make OpenCL non-backward compatible?
The code compiles and runs fine both with and without the parameter there. The only difference is that I get a warning that cprops is unused when putting NULL there instead of cprops.
Also, when I pass CL_DEVICE_TYPE_CPU | CL_DEVICE_TYPE_GPU as the type argument to the cl::Context constructor, my application will crash (SIGSEGV) when I later try to create a cl::Buffer with the context. Why? Am I not able to specify more than one device type to use simultaneously?
Update: By giving NULL as the properties argument to the cl::Context constructor, the variable platformList is suddenly not used to anything OpenCL related anymore. The tutorial seems to use platformList to specify the platform for which the cl::Context should be created, but now the context is just created like this:
cl::Context context(
CL_DEVICE_TYPE_GPU,
NULL,
NULL,
NULL,
&err);
so I don't get to specify the platform. Shouldn't I get to do that? How does it come I can't do that when the tutorial seemed to be doing that?
On your first question, see the official OpenCL documentation for a description of this parameter: http://www.khronos.org/registry/cl/sdk/1.1/docs/man/xhtml/. This is the C API, but it is the same as the C++ API.
As to your second question - you may want to check the error result from creating the context to see why it doesn't like the type parameters you specify.

QVariantMap crash in destructor

I am building a JSON-object with Qt and convert it to a QString using QJson. This (normally) works fine and it does in this case but in the destructor of my Qt data structure, it crashes with an Access Violation. The Object is built fine, it is sent over my network connection and after the function ends, my application crashes.
My code looks like this:
void bar()
{
QVariantMap data;
data.insert("Id", 1);
QList<QVariant> list; //QVariantList
for (QMap<...>:ConstIterator ... ) //Loop through a Map
{
QMap<QString, QVariant> singleEntry; //QVariantMap
singleEntry.insert("LocalId", it.value());
QList<QVariant> entryList; //QVariantList
for (...) //Loop through another structure
{
entryList.append("foo");
}
singleEntry.insert("List", entryList);
list.append(singleEntry);
}
data.insert("Entries", list);
QJson::Serializer.serialize(data); // Works fine
} // Crash here
If I remove the inner loop, which builds up entryList, everything works fine. It seems that the destructor of data cannot delete the contents but I have no idea, why. The whole data structure seems to be fine while serializing it (and I hope that QJson does not change anything in the given data) but it cannot be cleaned up..
Best Regards,
Tobias
As Raiv said this can happen when mixing debug and release dlls, but in my oppinion this can also happen if the application and the Qt DLL's use different CRT libraries. Some people say that when they recompiled Qt on their machines the problem dissapears and I think this is because the CRT dlls after Qt rebuild are the same as the app's. Try to set the Runtime Library option in C/C++ Code Generation is set to Multi-threaded Debug DLL (/MDd) or Multi-threaded DLL (/MD) respectively for Debug and Release. Some Qt types as QVariantMap, QVariantList, QModelIndexList are probably allocated with /MD (in Qt's dll) and when they are deallocated with /MT (in the app) I think this causes the crash. This can also fix the crash on QString::toStdWString(). In order for this to link maybe the Ignore All Default Libraries should be set to No and Ignore Specific Library should not mention crt dlls used by Qt.
I got a little workaround, which fits my needs. I have still no idea, why this crash happens, but I know, which should be the problem.
I tried to build up a static structure like this:
QVariantMap
QVariantList
QVariantMap
QVariantList
and it crashes. If I remove the QVariantList at the bottom and add QVariantMap or anything else instead, it is working fine. I think this is a problem with the nesting level in this case.
I have now just joined my list as a comma-seperated QString and then it works fine.
If anyone of you has an idea, why the crash in destructing such a nested struct (another information: doesnt matter if a allocate the QVariants in heap and delete them myself or stack) and how to fix it, please let me know.

Resources