-
DLL Injection with slots... ?!?!?
Hi,
I'm quite new to QT so be nice ;-)
I have a DLL that I inject into a QT application (I don't have the source)
I want this DLL to get some signals from the application that it's injected into.
the injection is working very well, and I have access to all the UI, I can even change values of text fields etc.
BUT, I can't connect the DLL slots to the UI's signals.
I've been reading about it a bit, but no one could give a good answer on how to do it.
please please, help!
Thanks
Gil.
-
Re: DLL Injection with slots... ?!?!?
By "can't" what do you mean? Do you get an error message?
-
Re: DLL Injection with slots... ?!?!?
I did an internal connection (With two text fields in the main APP) and it worked.
Like this:
Code:
connect(lineEdit,
SIGNAL(textChanged
(QString)), lineEdit2,
SLOT(setText
(QString)));
But when I connect to my own DLL slot function, it didn't work (It didn't get to the slot function)
like this:
Code:
connect(lineEdit,
SIGNAL(textChanged
(QString)),
this,
SLOT(mySlot
()));
As I'm guessing, I can't connect to slots that didn't compile with the main app.... My DLL's slot is not known to the main app...
am I write? what's the work around?
-
Re: DLL Injection with slots... ?!?!?
Are you sure you are using the exact same DLLs and library instance for Qt as the main application?
I don't think the main app needs to know about your slots, as they defined by MOC, and as long as you are using the same version of MOC (and Qt) as the main app, it should find your slot at run time.
If the app you are hooking into using a statically linked version of Qt, then it's a lot more difficult.
-
Re: DLL Injection with slots... ?!?!?
As squidge already said, signals and slots are handled by MOC.
Thus, make sure that your injected DLL is processed by MOC before linking it (here I mean the actual linking of the DLL, not injecting it).
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
But when I connect to my own DLL slot function, it didn't work (It didn't get to the slot function)
like this:
connect(lineEdit, SIGNAL(textChanged(QString)), this, SLOT(mySlot()));
What error do you get or how do you know the dll slot isn't called? And this is surly not pointing to the dll!
-
Re: DLL Injection with slots... ?!?!?
I don't know how to get the error... I just don't see the slot function being called.
In the slot function I have a code that sends a log message. (The log is working great)
Is there a way to see if the connection is ok?
btw: what should I put instead of "this"?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
Is there a way to see if the connection is ok?
On runtime there will be a warning on the console.
Quote:
btw: what should I put instead of "this"?
A pointer to your "dll", since it should be the slots of the "dll", right?
-
Re: DLL Injection with slots... ?!?!?
Can you show us the header file for the object in the dll declaring the slot you wish to connect to?
-
Re: DLL Injection with slots... ?!?!?
tbh, I would have expected 'this' to work, as you are referring to a class in the same memory space as the application (since you have injected the dll into the application). Giving the dll instance to the connect call doesn't make sense to me, as then it wouldn't know which class to call the metacall methods.
-
Re: DLL Injection with slots... ?!?!?
Quote:
On runtime there will be a warning on the console.
I'm unable to debug this... so where can I see the console? (Sorry if it's dumb question)
Quote:
A pointer to your "dll", since it should be the slots of the "dll", right?
I'm ready to try anything, so where can I get this "dll" pointer from (Sorry again)
Quote:
can you show us the header file for the object in the dll declaring the slot you wish to connect to?
Sure will, soon. (Currently at work)
Some more info:
- I'm using Visual studio
- I'm injecting my dll (Using WinJect) into the BasicLayout QT example (Just for the tests)
- I'm communicating with the DLL using windows WM_COPYDATA Messages
MANY THANKS for your time and effort!!!
-
Re: DLL Injection with slots... ?!?!?
I'm unfamiliar with how WinJect works and possibly others thought that by "injecting" you meant something else. Is the "injected" dll in the same memory space as the main application or are they two different processes? If the latter then obviously signal/slot connections will not work.
-
Re: DLL Injection with slots... ?!?!?
yea it's in the same memory space! this is what injection means.
When injected you have access to all the QT objects, widgets, and you can call functions there, like change a some text fields, change data.. everything, if you're not injected... you can't
-
Re: DLL Injection with slots... ?!?!?
@squidge: Ok, now I am confused. Seems I have a logical understanding problem. I'll work that out for me :) Thanks.
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
Lykurg
@squidge: Ok, now I am confused. Seems I have a logical understanding problem. I'll work that out for me :) Thanks.
what do you need me to clarify?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
I'm unable to debug this... so where can I see the console?
If you start your application on the command line and the slot can't be found a warning will be printed (or inside Qt Creator on the application output), but
Quote:
what do you need me to clarify?
I get the "injecting" wrong (thought you would using QPluginLoader), so your slot should be found. So I am out of ideas right now.
-
Re: DLL Injection with slots... ?!?!?
Ok, I'll check the command line error.
And I'll post a short code that do what I say, maybe it'll be clear than.
Thanks again!
-
Re: DLL Injection with slots... ?!?!?
I'm assuming you didn't create a plugin. This means a library exporting certain symbols that you use directly in the application you want to inject.
I assume that you can not change the application code itself directly. If that's not the case, then see the examples and documentation of creating plugins or using libraries.
Consider the following schema:
Code:
+-----------------------------------------------------------------------------------------+
| Application |
| |
| +---------------+ +-----------------------------------------+ |
| +---------------+| | Application code, contains objects. | |
| +---------------+|| | | |
|
+---------------+||| | mainWindow
(a
QMainWindow) | |
| | Linked |||+ | | | |
| | |
+ |
+-- label
(a
QLabel) | |
| +---------------+ +-----------------------------------------+ |
| | |
| v |
| +-------------------------------------------------------------------------------------+ |
| | Your injected DLL | |
| | | |
| | +--------------------------+ | |
| | | inside DLL | | |
| | | | | |
| | | Contains signals and | | |
| | | slots | | |
| | +--------------------------+ | |
| | | | |
| | v | |
| | +-------------------------------------------------------------------------+ | |
| | | Create an object: | Do this from within a context | | |
| | | | where the application event | | |
| | | MyClass *myclass = new MyClass; | loop is running. | | |
| | +-------------------------------------------------------------------------+ | |
| | | | |
| | v | |
| | +------------------------------------------------+ | |
| | | Example: | | |
| | | Suppose you have installed an application | | |
| | | event filter. | | |
| | | | | |
| | | Also, suppose you intercept the mainWindow | | |
| | | show event. | | |
| | | | | |
| | | From this event, you have a pointer to | | |
| | | mainWindow, let's call it pMainWindow | | |
| | | | | |
| | | Then you can write: | | |
| | | | | |
| | | connect(pMainWindow->button, SIGNAL(...), | | |
| | | myclass, SLOT(...)); | | |
| | | | | |
| | | | | |
| | | In pseudocode: | | |
| | | ---------------------------------------------- | | |
| | | when application started | | |
| | | install eventfilter | | |
| | | | | |
| | | when eventfilter gets called | | |
| | | check the event and the target object | | |
| | | if event = show and object = mainWindow | | |
| | | Create a new MyClass object if none | | |
| | | already exists. | | |
| | | Connect signals and slots | | |
| | | | | |
| | +------------------------------------------------+ | |
| | | |
| +-------------------------------------------------------------------------------------+ |
| |
+-----------------------------------------------------------------------------------------+
You create a dll that reimplements the application event function to install an event filter.
In that event filter, you intercept the show event of a widget (for example). While intercepting that event, create a new QObject based object that contains signals and slots. Connect the slots of that object to the signals of the widget (or a member of that widget).
Make sure that when you build your library, the definitions of all the classes are known (include the correct headers). Also make sure that your code is processed by MOC.
Then inject the library in the program.
How this is exactly done on Windows, I don't know. Maybe you don't need to reimplement the event function of the application in order to install an event filter. That would make it a little bit easier.
EDIT: this is just a brainstorm from me. I do not assume that everything above is 100% correct.
-
Re: DLL Injection with slots... ?!?!?
I think what he means is that the application doesn't know about the DLL and is not loading the DLL.
Instead, he is using Winject to inject the DLL into the applications memory space, the application doesn't know the DLL has been injected. I assume it is being done this way because the source code of the original application isn't available and he wants to modify that application somehow. Maybe get some data from an existing Qt widget or manipulate the data somehow.
Kinda similar to how flaab wanted to grab data from inside a Poker engine in his thread.
-
Re: DLL Injection with slots... ?!?!?
This is almost the same thing... and we're talking about the same software, FullTiltPoker!
But flaab is asking how to intercept into internal function of QString or somthing like that...
I want my DLL to get signals from this software, like dataChanged, etc.
I'm not building a poker bot like flaab, I'm collecting players statistics.
for this, I need my DLL to be able to "connect" to the software UI signals.
Thanks for clearing me up.
Gil.
-
Re: DLL Injection with slots... ?!?!?
For best results in this case, you should use the same compiler as FTP. I'm going to guess that FTP uses something like Visual Studio 2008 rather than QtCreator (big companies don't like using free software)
-
Re: DLL Injection with slots... ?!?!?
yea I'm using Visual Studio 2008, How can I tell what's the FTP QT version?
-
Re: DLL Injection with slots... ?!?!?
Is it dynamically linked? (does it refuse to run if the DLLs are missing?)
-
Re: DLL Injection with slots... ?!?!?
Can you inject a dll into a statically linked app (which is probably packed or encrypted too) at all?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
wysota
Can you inject a dll into a statically linked app (which is probably packed or encrypted too) at all?
Short answer: yes
But: it is extremely difficult. It is done in software cracking. You need to alter the assembly source code.
-
Re: DLL Injection with slots... ?!?!?
You can do it without altering the application code at all, if have something that easily identifies the 'target' application (such as the text for the window title or the process name) you can VirtualAllocEx and CreateRemoteThread, then your thread runs in the process space of the application and can do whatever it wishes.
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
squidge
You can do it without altering the application code at all, if have something that easily identifies the 'target' application (such as the text for the window title or the process name) you can VirtualAllocEx and CreateRemoteThread, then your thread runs in the process space of the application and can do whatever it wishes.
Hey guys, this is not the issue at all...
It is possible, and this is the working part of my question.
I'll post my code soon (And you can try it too)
Back to the original question:
Can I connect a slot function in my injected dll to the main app?
Thanks
-
Re: DLL Injection with slots... ?!?!?
Until you provide some code of yours (namely the header file for the class you wish to call a slot from) we're stuck so we might as well get a bit offtopic here.
-
4 Attachment(s)
Re: DLL Injection with slots... ?!?!?
Here are the files:
Attachment 5347
Attachment 5346
Attachment 5348
Attachment 5349
I'm injecting this DLL into the BasicLayout example (Comes with QT, run it to see where I'm going with this) , and do two connections:
1. Line1 with Line2
2. Line1 with mySlot function
I than change Line1 text, and see that Line2 also changes, and any change that I do to Line1 are reflected in Line2 too -> The connection is working!
And I did this connection from my DLL.
In mySlot function I change the Line3 text (We know that I'm able to do it)
so if the 2nd connection was successful we would have seen Line3 also change... but it doesn't... -> The connection didn't work!
I've created MyQWidgetMoc.cpp with moc.exe that comes with QT...
HELP HELP. :confused:
Thanks
-
Re: DLL Injection with slots... ?!?!?
So how do you know your slot was not called? And please don't reply that the text on lineEdit3 didn't change.
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
wysota
So how do you know your slot was not called? And please don't reply that the text on lineEdit3 didn't change.
sorry, but the text on lineEdit3 didn't change...
If the 2nd connection was working, the lineEdit3 should have changed to "mySlot CALLED, yey"...
What am I missing!?!?!?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
sorry, but the text on lineEdit3 didn't change...
If the 2nd connection was working, the lineEdit3 should have changed to "mySlot CALLED, yey"...
What am I missing!?!?!?
Debugging your application by changing values of lineedits is not a very professional way of doing things. What if you change the value but the change isn't reflected on the widget? Or if something rewrites the old value?
1. Check the return value of connect()
2. Use qDebug() or your debugger to see whether the slot is called.
-
Re: DLL Injection with slots... ?!?!?
Quote:
Check the return value of connect()
The return value is TRUE for both connections
Quote:
Use qDebug() or your debugger to see whether the slot is called.
I can't use a debugger, because this code is an injected dll, and don't know how to use the qDebug()... (Sorry)
But just to make sure, inside mySlot function I disconnected the first connection, but it wasn't getting disconnected... man! this function is NOT being called!
I've also tried
Code:
this->metaObject()->indexOfSlot("mySlot()")
and got 4!! the information is there! but not being called... :-(
I'm about to cry! anyone!? :crying:
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
The return value is TRUE for both connections
So the connection is successfully made.
Quote:
I can't use a debugger, because this code is an injected dll,
It doesn't change anything, you can still run the original application under the control of a debugger together with your dll.
Quote:
and don't know how to use the qDebug()... (Sorry)
So learn to use it.
Quote:
But just to make sure, inside mySlot function I disconnected the first connection, but it wasn't getting disconnected...
man! this function is NOT being called!
I've also tried
Code:
this->metaObject()->indexOfSlot("mySlot()")
and got 4!! the information is there! but not being called... :-(
I'm about to cry! anyone!? :crying:
Maybe the respective signal is not emitted :)
-
Re: DLL Injection with slots... ?!?!?
for a better test I did this:
I've opened the BasicLayout project in Visual Studio, added my MyQWidget.cpp/h and moc and connected the fields there...
Inside mySlot function I did a qDebug out, and saw it!!! when I do the connection from inside the app it's working! meaning -> MyQWidget is good for receiving signals! the caller is having a problem! maybe it can't find me in some slots table!?
When a signal is fired, how does QT "know" where to call to?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
the caller is having a problem!
The caller is not having a problem, it is you who has a problem while trying to break into the application.
Quote:
maybe it can't find me in some slots table!?
Maybe the signal is not emitted (I hate to repeat myself)?
Quote:
When a signal is fired, how does QT "know" where to call to?
It looks into the connection table for the object emitting the signal.
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
wysota
It looks into the connection table for the object emitting the signal.
Where can I see this code? I want to debug it.
-
Re: DLL Injection with slots... ?!?!?
QMetaObject class, as far as I remember. If not, then it's in QObject. But trust me, you won't be able to debug it, it's complicated. If your connect() statement returned true, it means the connection is placed in the connection table. As long as both interested objects are alive, it will stay there (if you don't disconnect the signal manually).
-
Re: DLL Injection with slots... ?!?!?
Post your solution (something loadable into VS or QtC) and we'll have a look at it.
-
Re: DLL Injection with slots... ?!?!?
The solution is "Qt::DirectConnection"
I did some deep debugging and found that the code is checking if the caller and the sender are from the same thread... OR Qt::AutoConnection! so I did DirectConnection and it's working!!!!!!!!!!!!!!!!!
I want to thank all of you guys, for the time and effort! you are the best!
-
Re: DLL Injection with slots... ?!?!?
Hold on, there is something wrong here. Regardless of what the connection type is (be it AutoConnection or DirectConnection or QueuedConnection), the slot eventually gets called unless the target slot is in a thread that doesn't have an event loop running. So if your slot doesn't get called if you use AutoConnection then it means it runs within a thread without an event loop which in turn implies it is not the main application thread. And accessing widgets from the non-gui thread leads to a crash. I see some contradictions here:
1. since your test app doesn't use worker threads, auto and direct connections should be equivalent
2. your test app doesn't crash so you are not accessing widgets from a worker thread which in turn means the slot should work in the first place
2. if the application you are trying to break into uses threads and that's why the auto connect doesn't work (because your injection code works in the context of one of the worker threads), then accessing any component behind its back will/should likely lead to a crash.
To sum things up - either you are wrong now about direct connections or your solution will be crashing on you like hell soon.
-
Re: DLL Injection with slots... ?!?!?
ok, ok... we have something here.
I'm comming for managed languages (Java) and I'm used to Garbdge collectors... (Be nice)
The new problem is that the slot is being called only one time.... I'm creating an object of MyQWidget when the DLL is being called, I'm calling the function that does the slot-signal connection, and I'm not releasing the object...
The DLL is still in the Main Application memory space, but MyQWidget is somehwere in memory!? maybe that was the reason that slot was not getting called...
I understand that I'm suppose to have some kind of events loop, that will keep MyQWidget alive, so my slot is available for SIGNALS. How Do I do that?
Am I right?
I guess that now you'll send me to read something (Please do)
Many thanks
Gil
-
Re: DLL Injection with slots... ?!?!?
(Please read the previous post, first)
I'm trying now to prevent my MyQWidget from terminating (So it can be available for signals) I've changed it to inherit from QDialog (And not just QWidget or QObject)
When the DLL is running for the first time, I'm creating my "dialog" and calling a public function to do the signal connection, and than calling the "exec()" function of the dialog (To keep it alive)
BUT! the main UI is freezing, until I close my Dialog...
Do I have to create the dialog in a different thread? so the main UI will be able to actually send the signal...
Gil.
-
Re: DLL Injection with slots... ?!?!?
If the application is a Qt application (and it is) then there is already an event loop running and you shouldn't need to do anything more. Especially don't try handling anything related to widgets from another thread (in doubt read my previous post again). It doesn't matter if you inherit from QWidget or QDialog, the main event loop is already handling your widget. As for the memory thing, as long as you don't delete the object yourself and as long as its parent doesn't go out of scope, you'll object will remain alive.
-
Re: DLL Injection with slots... ?!?!?
As far as I can see, I have two options:
1. use exec() -> leads to the main UI waiting for the dialog to close.
2. use show() -> The dialog opens, and closes very fast, no Idea why...
any ideas?
-
Re: DLL Injection with slots... ?!?!?
Quote:
Originally Posted by
gilamran
2. use show() -> The dialog opens, and closes very fast, no Idea why...
You are probably creating it on the stack and not on heap so it gets out of scope and gets deleted by the compiler.
-
Re: DLL Injection with slots... ?!?!?
That was the problem!!
I've created my QDialog on the heap and now I'm getting all the signals!!! yey!
This might be obvious to some of you, but I come from Java (With garbage collector)
Two things left:
1. When I close the main UI, I can still see it in memory (Probably because it still have a slot in an object that wasn't release...)
So I need a way to know when the window is trying to close, or when the data of the model is being deleted... are there any events/signals that I can listen to and delete myself?
2. Still when I use the QDialog show(), it's openning and closing (very fast), and when I use the exec(), the main UI is stuck till I close it... any idea how to solve this?
Thanks
Gil
-
Re: DLL Injection with slots... ?!?!?
Show us how you create the dialog.
-
Re: DLL Injection with slots... ?!?!?
Code:
#include <windows.h>
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved)
{
MyQDialog *m_MyQDialog = new MyQDialog();
switch(Reason)
{
case DLL_PROCESS_ATTACH:
m_MyQDialog->connectQWidget();
m_MyQDialog->show();
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
-
Re: DLL Injection with slots... ?!?!?
This shouldn't cause your dialog to disappear.