terça-feira, 18 de outubro de 2011
A crack in Redgate's Reflector
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.
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.
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
That is 401000 in this case.
3. Code analysis3.1. Instruction 1 – Initialize resources
If we enter the function, we should see the resources being pushed and the qRegisterResourceData function being called:
3.3. Instruction 3
This function calls all the subclasses constructors
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.
sábado, 2 de julho de 2011
Cracking a Pimp
What I found was a really interesting and defying piece of protection software, and I think worth mentioning in a post about cracking and RE.
This specific issue relates to the authors having used a known issue where some debuggers get lost or fail to synchronize when an LDT is used to detour the execution path.
The reversed source code to setup the LDT entry is this:
codeSegment = getCodeSegment(); // CS=0x1B GetThreadSelectorEntry(GetCurrentThread(), codeSegment, &SelectorEntry); SelectorEntry.LimitLow = 0xFFEF; SelectorEntry.HighWord.Bytes.Flags2.LimitHi = 0x7; pHandle = GetCurrentProcess(); error = setLDT(pHandle, (int *)0x7FF, &SelectorEntry); // LDT = 0x7F8 ... memcpy(farCallClone, farCall, 0x1Fu);In process, we've got this selector before setup:
DWORD LimitHi :4; DWORD Sys :1; DWORD Reserved_0 :1; DWORD Default_Big :1; DWORD Granularity :1;
009200DD call far 07FF:00000000 to our original execution segment: 009200DD call far 001B:00000000
0040CD95 mov word ptr ss:[ebp-2],1B 0040CD9B jmp short pimp_cra.0040CDC1 0040CD9D nop 0040CD9E nop 0040CD9F nop 0040CDA0 push ebp 0040CDA1 mov ebp,esp 0040CDA3 sub esp,14 0040CDA6 mov eax,[arg.1] 0040CDA9 and al,0F8 0040CDAB shr eax,1 0040CDAD mov edi,eax 0040CDAF shl eax,2 0040CDB2 add eax,edi 0040CDB4 lea eax,dword ptr ds:[eax+91FE14] 0040CDBA mov eax,dword ptr ds:[eax] 0040CDBC mov dword ptr ss:[ebp-6],eax 0040CDBF jmp short pimp_cra.0040CD95 0040CDC1 mov edi,dword ptr ds:[AF8EF8] 0040CDC7 push [arg.2] 0040CDCA call far fword ptr ss:[ebp-6]

What this code does is it resolves dynamically the function address to our home segment, based on the segment index passed as an argument to the dispatcher and retained in a VM call dispatcher table.
With this you can set a breakpoint at address 0x0040CDCA. Now just relax and wait for the key validation, and you can now trace all the virtual machine operations.
Replace the code at address:
00403046 mov eax,9200C00040304B nop 0040304C nop 0040304D nop 0040304E nop 0040304F nop 00403050 nop
00403243 mov eax,9200C0 00403248 nop
The reversed code for it is again presented here:
... BaseAddress = 4; RegionSize = 4092; pHandle = GetCurrentProcess(); error = NtAllocateVirtualMemory(pHandle, &BaseAddress, 0, &RegionSize, MEM_TOP_DOWNMEM_RESERVEMEM_COMMIT, PAGE_EXECUTE_READWRITE); if ( error >= 0 ) { farCallClone = 0; memcpy(farCallClone, farCall, 0x1F); ....
Good look finding the correct key.