Besides his article, not much on the subject of reversing Qt code seemed to be around. Since then I was faced with a fair amount of Qt applications, even Portuguese ones, so I decided to post my thoughts on the subject, and build a tutorial for the 4th version of Qt (coincidentally its also the same version of IDA 6.1, hihi):
Note: The Qt platform has an OO approach, so consider before reading this tutorial, to gather some insight about reversing C++ stuff, like RTTI, MS calling convention, virtual functions, etc.
Usually looks like this and Olly is smart enough to identify it as it is the EP defined in the PE header.
Consider Main function source code. Let’s see what do we need to find it’s corresponding assembly code, and what this code looks like after compilation.
2.2 Second step, select QtCore4.qWinMain and jump into it’s code definition.
To verify if we’ve selected the correct function call, go up some lines and the following api calls should be present:
- QByteArray::detach2.4. And we’re in QMain
2.5. The startup address is usually pointing to the start of the .CODE section
That is 401000 in this case.3. Code analysis
3.1. Instruction 1 – Initialize resources
If we enter the function, we should see the resources being pushed and the qRegisterResourceData function being called:
Pretty easy to follow right? The QApplication class is calling it’s constructor with the following arguments: Arg1 = argc, Arg2 = argv, Arg3 = compile_version
3.3. Instruction 3
3.4. Instruction 4
3.5. Instruction 5
This function calls all the subclasses constructors3.6. Instruction 6
3.7. Instruction 7
4. Intercept Messages in Qt
Messages in Qt are set thru slots definition. Slots are then connected using the connect macro to a QWidget based class. As sampled in the code:
So we have here 3 types of message redirection, the first one “saveAsAct” is defined in the slot set of the MainWindow class. “saveAsAct” will be made part of the MainWindow class dispatcher table.
The second one, “closeAct”, is defined as an overload of QMainWindow superclass, so it will not be part of MainWindow class dispatcher table, but will be dispatched thru MainWindow dispatcher function. But as “closeAct” is not found in MainWindow class dispatcher table it will be forwarded to QMainWindow superclass dispatcher using an Event class. The definition of “closeAct” is:
Finally “exitAct” is applied or connected to qApp. qApp is an instance of QApplication, so it can’t be intercepted in the MainWindow dispatcher function, but in QApplication dispatcher function.
Considering that everything was easy till now, this will be the “hard” part of the process, getting to trace the GDI interaction. Let’s see how we can accomplish this task. Basically there are three approaches that can be used:
4.1. Find and set a conditional breakpoint at QMetaObject::metacall with [esp+4] == object addr
The object is any GDI particular object like a QTextControl, QMainWindow, etc. that you might know it’s memory address.
4.2. Set a conditional breakpoint on Q
4.3. Set a breakpoint on QMainWindow::qt_metacall (QMainWindow is defined in QtGui4.dll). This being a special case of the previous one.
On stop set a breakpoint on .code section of main executable, it should stop on the Qt dispatcher.
In the main Qt dispatcher built by the compiler, Olly tells us that there are 6 cases on switch.
The six destinations are set here:
Which correspond to the slots definitions of MainWindow class:
4.4. To target messages attached to events, set a breakpoint on QMainWindow::qt_metacall, on stop set a breakpoint on QMainWindow::event. After break set a new breakpoint in the .code section of main executable, it should stop on the Qt function you’re after.
For example, tracing the MainWindow::Close, after following the steps defined before we reach:
Just to confirm we’re in the right place let’s enter the first call:
Which is maybeSave() function who’s definition is:
See the corresponding text? We’re in the right place.
For the sake of completeness, there’s a caveat you need to be aware regarding the first approach I presented: Setting a breakpoint in QMetaObject::metacall. After entering QMetaObject::metacall and setting a breakpoint on the user section code of the main module, it won’t enter immediately in the function code we’re after; instead the metacall will just try to find the virtual stub function responsible for the dispatching. For resolving this, all you need is let the code enter in the Qt core dispatcher and then set a second section code breakpoint in the main module and finally you’ll be there.Ufff… Good luck in you reversing.
Hope you enjoyed it!
PS: If you want the printed version of this text you can get it here.