Unpacking the RLPack Premium edition
It’s been a bit quiet for a while, as I was on a vacation :) As you might remember, I published unpacking instructions for RLPack a while back. I mentioned that while the free version of RLPack contained no anti-whatnot code, the premium version supposedly did but I didn’t have any files packed with it. I got contacted by ap0x, the coder of RLPack, and he was kind to send me a sample file packed with the premium edition.
After taking a glance at the file it was clear that there was a whole lotta more stuff in the RLPack stub than before. IDA was struggling a bit in the analysis, and analyzed a huge load of junk among with some real code. So, let’s dig inside a bit. First off, there are two different packing algorithms which could be used: LZMA or aPLib. The sample file I received had an entrypoint looking like this:
So, it seems that the sample was packed using the LZMA library. Most of the function calls have been made by calling ebp+<offset>, which makes it much harder for IDA to display library calls correctly. The first real functioncall the stub does is the call sub_480254 seen in the picture above. This function will first allocate more memory in two different ranges, and then decompresses a chunk of bytes. Next function loaded the user32.dll in memory, and the function following that resolved CreateMutex and OpenMutex and created a mutex called RLpack.
The next function is interesting. If you look at the picture above its the call sub_481A46. Scroll a bit down, and you’ll see this bit of code:
As you can see, the code installs an exception handler into the stack and then causes an access violation. If the execution is not transferred to the exception handler, you’re hosed. After you finish executing the SEH, and get back to the normal code, there are few harmless function calls made, and then we run into another nice trick:
What the code in the picture above does is it changes the in-memory imagesize, causing some dumpers enough trouble to prevent dumping. Easiest way to avoid this is to select and right-click the retn command before you’ve executed any of the above code, and then select the New Origin Here menuitem. This will effectively set the EIP at the retn, and by pressing F7 once you single-step out of the function. The next function is once again another trick to make our life harder:
This code will erase the PE Header from memory, screwing up some dumpers. It first calls GetModuleHandle with NULL as an argument to get a handle to itself, then calls VirtualProtect to set the needed memory range as writable and then it just zeroes out the header. Once again, select and right-click on the retn, select New Origin Here from the menu and press F7 to single-step out. A bit more memory is allocated, and then the IsDebuggerPresent API name is decrypted from memory and resolved from kernel32.dll. Then a check is made to see whether there is an breakpoint at the beginning of the API function:
It does the same check for the following API calls also: CheckRemoteDebuggerPresent, GetVersionExA and CreateFileA. If the checks clear out ok (read: no breakpoints), the functionpointers will be saved in memory. What follows then is a nice load of debugger checks:
As you can see, there are quite a many checks. But don’t jubilate yet: The function call at 00482B4F calling the function at offset 00482871 contains even more checks :)
In the above, the code that comes after resolving the ZwQueryInformationProcess is checking the whole function for any jumping, short or explicit. I reckon this is to detect any detours that might be set for debugging / tracing purposes. The same process is done for a few other functions as well:
A nice little bunch, eh? Next, the FindWindowAAPI pointer is resolved, and a check is made for a few monitoring applications:
Right after we return from these checks, another call for FindWindowA is made to detect OllyDbg, as well as few others :)
The same call that’s made for the SoftICE check is used also to check for 8 or so other handles that belong to SoftICE. After this we’ve passed all the debuggerchecks present. Just trace forward patiently, and you’ll land on the OEP. You’ll see the stub resolving imports and so on. Comparing to any of the packers I’ve seen, RLPack has the widest variety of debugger checks present.
May 1st, 2007 at 7:28 pm
Nice work :) But there are some protection options you did not describe. Such as Import Elimination and Redirection, Advanced antiDumping and VM OEP. They are the key features of the protection.
May 1st, 2007 at 7:35 pm
:) In general, I’d say RLPack Premium is well worth the money