sábado, 6 de agosto de 2011

QT 4 You

I was asked a couple months ago by a friend of mine to “tweak” a software protection as he wanted to “evaluate” more “thoroughly” the targeted program. As I went in to it, I found the protection scheme very interesting as it involved a couple of cross platforms based engines interacting together to serve as anti-hacking security licensing system. One was Qt, the other being JavaScript. It was the second time that I came against a Qt based software. The first time thought, I just used the basic cracking skills every reverser uses with Windows GDI apps. But this time I needed to go deeper to understand the cross VM interactions, and a bigger understanding of the Qt framework was needed, so, I engaged into searching for more info on the subject. The results were quite poor, except for an article by Daniel Pistelli, who now works at Hex Rays (coincidence that IDA has been reassembled using this framework?).

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.

For the purpose of this demonstration I used a demo application who accompanies the Qt SDk called sdi.exe, located in the examples/mainwindows/sdi folder. You can use any program you wish, to follow this explanation, thought.

1. Recognizing the Entrypoint

Usually looks like this and Olly is smart enough to identify it as it is the EP defined in the PE header.

2. How to find Main?

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.1. First step is to search for all inter-modular calls and locate the imported dispatcher function qWinMain defined in QtCore4.dll.

2.2 Second step, select QtCore4.qWinMain and jump into it’s code definition.

2.3. The first call after QtCore4.qWinMain sets up memory. But, we are impatient and we want QMain. QMain function will always be the second call, as highlighted in the figure.

To verify if we’ve selected the correct function call, go up some lines and the following api calls should be present:

- GetCommandLineW

- QString::fromWCharArray

- QString::toLocal8Bit

- QByteArray::detach

2.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
Instruction 1 – Initialize resources

If we enter the function, we should see the resources being pushed and the qRegisterResourceData function being called:

3.2 Instruction 2 – Instantiate QApplication

Pretty easy to follow right? The QApplication class is calling it’s constructor with the following arguments: Arg1 = argc, Arg2 = argv, Arg3 = compile_version

Instruction 3

3.4. Instruction 4
3.5. Instruction 5

This function calls all the subclasses constructors

3.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<class of object>::qt_metacall with [esp+8] == WM_

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.

4 comentários:

Rhk0 disse...

Interesting stuff.
Really Thank You :)

Majid disse...

Each post, One Book
Good job :-*

Majid disse...

Each post, One Book
Good job :-*

Ignacio Martin disse...

Very good article.
ar1vr, are you still active with qt4 reversing?