PDA

View Full Version : Armadillo 3.xx on a strange Target


LLXX
August 27th, 2005, 03:14
This target which I am trying to reverse is packed with Armadillo 3.00 - 3.61 according to PEid. However, it is not exactly a "normal" target, since it is supposed to be executed by another program - when simply run alone, it just exits as if the only code it contained was an ExitProcess call. Thus for various reasons I cannot have the the target running long enough to dump it, but I figure with Olly it should be only necessary to get to OEP and then dump it. Here is what I've done:

1. Tracing through the Armadillo code with F7 - takes too long, I did it for nearly three hours and still haven't reached anything resembling an OEP. It is apparent the code is hand-made, consisting of self-modifying parts, convoluted jumping sequences, garbage code, and tricky stack manipulations.

2. Identifying the exact species of Armadillo. In all the tutorials I've found there are references to "Standard Protection", "Debug Blocker", "CopyMem II", etc. From what I understand, Standard Protection is like a standard packer, i.e. Unpack then Execute; Debug Blocker is two-process but the second process is completely unpacked and dumpable from the memory; CopyMem II has two process but only unpacks around where the current IP is - correct me if I'm wrong. My target has two processes, that's all I can gather. I reckon either Debug Blocker or CopyMem II.

3. Follow the advice of the Tutorial (ARTeam and others) which describe detaching the second process and then dumping it:

Start Olly, load the program. (My Olly is properly hidden, that is not a problem here.)

Break on WriteProcessMemory - according to tutorial it's the second one which needs to have their byte changed to eb fe to loop infinitely. It breaks, I change these bytes. Strangely enough, in the tutorial the original bytes were 60 e8, which are exactly the same as the ones in my target, even though the target used in the tutorial was completely different from mine.

Next, break on WaitForDebugEvent. After breaking there the tutorial tells to find the Pid of the newly created process then detach it by running a DebugActiveProcessStop call. I manage to detach it successfully, and open a second Olly and Attach there. Now my whole machine slows down severely. Inspection of Task Manager reveals CPU usage is still less than 10%. Not mentioned in Tutorial, this slowing down.

Eventually I see the infinite jump and change it back to the 60 e8 it used to be, after several minutes of waiting due to the slowness. But here I see something familiar - is it the exact same appearance of the entrypoint at the original target (father process)? If so, have I basically done nothing? Or is it the nature of the Armadillo to create a duplicate of itself? At this point I use the LordPE and dump the entire process. I open with a hex editor, and see the entire .text section (which is supposed to be where the unpacked code goes, I think) is filled with the null. Following that is a section containing the same code as the original file, and then the packed data.

After closing both Ollies and then opening the dump in the new one the speed is back to normal, so I decide to trace through it. It is the same code that was in the original file. I then try to break on WriteProcessMemory, and it does, in other words doing the exact same thing the original file was doing. If I just try to executed the dumped thing directly, it displays message like "This program is corrupted please reinstall".

General observations (open target file with hex editor and look around):

Armadillo's body contains (in order of encounterance) the extremely obfuscated first code section which looks like it's been packed (I obtained an Armadillo'd crackme and can verify that this section is identical to it, and should be similar for all the 3.xx versions), a "padding" of "É"s (NOP), a space of nulls, a piece of an import table, some interesting strings (including "Cannot locate protected program data", a table-like structure (8-byte entries) which purpose I'm not sure of, more strings which relate to data compression (e.g. "invalid distance code", and then some unknown binary with the interesting string "deflate 1.1.4 Copyright 1995-2002 Jean-loup Gailly" (occurred in all the Armadillo'd programs I could find), more strange data, "inflate 1.1.4 Copyright 1995-2002 Mark Adler", and a section of strings resembling that of M$'s C++ runtime library. Then follows some empty space, more imports, and finally the most interesting part, a chunk of compressed data beginning with the string "PDATA000" which occurred earlier in the file. This coincides with the .pdata section. The thought happened that this data is compressed with the common "flate" algorithm, maybe I should just use decompressor on it and yield the virgin? But it is probably encrypted too, unfortunately. I tried to breakpoint on access to that section but it never hit the breakpoint (terminate with error code 128 or something like that).

Admiral
August 27th, 2005, 11:43
Hi LLXX.


Tracing through the Armadillo code with F7 - takes too long, I did it for nearly three hours and still haven't reached anything resembling an OEP.You need to work smarter and not harder. I doubt anyone's ever found an OEP (in a decent packer) using only the trace keys.


Identifying the exact species of Armadillo...It certainly does look like the target has Debug-Blocker, so you're on the right track. Since most processor-non-intensive exes (like this one) are very workable with Copymem-II, you're probably best off assuming that your target is packed with the whole shebang: Debug-Blocker & Copymem-II. You'll also want to look out for 'Nanomites' and 'Strategic Code-splicing', but for the moment they can be ignored.


Break on WriteProcessMemory - according to tutorial it's the second one which needs to have their byte changed... Recent releases of Armadillo are a bit trickier about this. You say that you believe your target to be 'Armadillo 3.x'ed, but many packer identifiers aren't too good with this. Arm-4 is very very similar to Arm-3 so unless you know something I don't, you may want to be a bit careful.
I find that the best way to find the OEP is as follows:
Hardware breakpoint on WriteProcessMemory. When it breaks, set a BP on WaitForDebugEvent and run to that. Locate the DEBUG_EVENT structure ([ESP+4]) in your dump window and keep it there. Remove the WaitForDebugEvent BP and keep Shift-F9ing until OllyDbg breaks on a WriteProcessMemory due to write 0x1000 bytes. Check the dump window and it should contain the last DEBUG_EVENT structure that was returned by WaitForDebugEvent. If the father process is decrypting a block (the first block, and hence the one containing the OEP) then the fourth dword should in the structure should contain the exception code for a guard-page violation (0x80000001). If this is the case, mosey on down to the seventh dword in the structure. This contains the address at which the exception occurred, which in this case is your OEP. It should fit in the section immediately following the PE header (in both the parent and slave process, which are essentially the same at load time).


Strangely enough, in the tutorial the original bytes were 60 e8, which are exactly the same as the ones in my target
60 E8 is bytecode for PUSHAD followed by a CALL. This is one of a few standard ways a main() function will start out, so don't be too surprised. It is also the way Arma+Debug-Blocker always starts out, so make sure the 'OEP' you have is actually the OEP (as described above) and not the EP to Armadillo's code (as the rest of your post seems to indicate).


Now my whole machine slows down severely.Windows generally manages a tight infinite-looping process quite well, but it's possible that your process has been set with a high(est) thread priority. If the slowing is bothering you, you may want to try (at the first WriteProcessMemory, say) setting the slave/child thread's priority to 'Lowest' via the task manager.


Eventually I see the infinite jump...There should be no 'eventually' to it. Your slave process isn't going anywhere, so hitting F9 followed shortly by F12 will get you straight there.


But here I see something familiar - is it the exact same appearance of the entrypoint at the original target (father process)? If so, have I basically done nothing?This is why I get the impression that you have your OEP wrong. If you put the 'JMP EIP' (EB FE) at the EP of the exe and not at the OEP then you will see exactly this. Again, double-check that you have the OEP correct before you start patching.


Or is it the nature of the Armadillo to create a duplicate of itself? It is indeed. The master process fires up the slave process, and at launch the two are identical. It is only when they call IsDebuggerPresent and get different results that they start behaving differently. However, you still want to be attaching to the slave at the OEP (not the PE EP), which is well into its life-cycle. If you attach too early, the slave process will promptly notice that the master process has terminated and will hence terminate itself. If you attach before it even knows it is the slave process (i.e. before the call to IsDebuggerPresent) then it will know no better than to act as the master process itself.


the entire .text section (which is supposed to be where the unpacked code goes, I think) is filled with the nullThis is further evidence that you're breaking into the slave too early. This section starts out all null and gets filled in by the master process before it gets anywhere near its OEP.

So I think the diagnosis is pretty concrete. Check the 'OEP' that you're using against the one in the PE header. If they're the same (which I suspect they will be) then you're method is flawed. Use the one I gave above and let us know how it works out for you.

Regards
Admiral

LLXX
August 28th, 2005, 03:50
Hi Admiral, thanks for the reply.

I tried your method of breaking on WriteProcessMemory and then on WaitForDebugEvent. I managed to locate the DEBUG_EVENT structure, remove the breakpoint on WaitForDebugEvent, then shift+F9 as you said. However it just terminates (exit code 128) without breaking again, even though I made sure there was a breakpoint on WriteProcessMemory.

I then restarted but this time ran to WaitForDebugEvent and watched the DEBUG_EVENT structure for the 80000001 as I stepped past and then ran to WaitForDebugEvent again. The 80000001 never appeared, and after several breaks at WaitForDebugEvent it just terminates. I'm wondering if Olly is really hidden - I'm using the hider plugins and renamed the file to 0llydbg.exe. However it just terminates, not even falling into the infinite loop or the "A debugger is present" message which happens if I don't use the hider plugin.

From noticing that all Armadillo'd files have a .pdata section starting with the string "PDATA000" (this string also occurs further back in the file), and apparently contain "flate 1.1.4" compressed data, it might be possible to decompress the .pdata section and yield the virgin. I found a crackme packed with Armadillo 3.71 and tried it in the Olly. I set breakpoint on the .pdata section and F9, this one did break on access. So I wondered, is it possible to splice the body of that armadillo onto my target? I used a hex editor and copied/pasted the whole body, excluding the relocation table and PE header, over the exact same place in my target, and tried the bp .pdata and F9 again. Didn't work - stack overflowed and then IP went to 00000000. Maybe it's possible to unpack the .pdata section and thus kill the armadillo without ever executing one of its bytes.

Admiral
August 28th, 2005, 13:44
When set to maximum protection, Armadillo encrypts its target several times over using different algorithms. Silicon Realms Toolworks seem quite proud of the fact that 'even they' can't decrypt your program without knowing your private key, so I doubt you'll have too much luck decrypting it manually.

You say that your target is terminating prematurely with code 128. Armadillo has a nasty habit of doing this when it thinks it's being debugged. Newer versions won't even let you run to the first WriteProcessMemory using a standard INT3 breakpoint from WinMain.
Chances are, you're being rumbled in one of two ways:

Armadillo may be timing itself. I know from experience that it measures the amount of time (using GetTickCount) it takes to construct each thunk of the IAT. If it takes more than a few dozen milliseconds then it happily terminates itself, confident that a debugger has paused it during the process. I've never seen this technique cause problems in finding the OEP though. If you get desperate, set log breakpoints on GetTickCount and invistigate.

However, I suspect that your breakpoints are being detected. Armadillo does regular CRC checks to ensure that none of its critical code has been patched. This includes the first two or three bytes of many API functions (in their own address space). You may want to make sure that you only set breakpoints four or five (to be safe) instructions into Kernel32's code itself, none at the base addresses of any API functions, and certainly none in Armadillo's code. I find this to be a bit of a pain though, as OllyDbg no longer gives you an at-a-glance view of the function's parameters.

Of course, a much better way to deal with your breakpoints being visible is to use hardware breakpoints. I've yet to see an app that can detect them, and so you can put them wherever you want.
Looking back at my last post, I did specify that the WriteProcessMemory breakpoint should be hardware, though I don't recall this being entirely necessary. Perhaps my subconscious is a better reverser than I am.

Anywho, the points of this post occur in reverse order of importance:

1. Try using hardware breakpoints instead of standard ones.
2. If that fails, try restricting your breakpoints so they occur only deep inside API code. Also ensure that you delete any breakpoints you're not using anymore. They just stand you a worse chance of slipping by unnoticed.
3. If you still find Armadillo is bailing out on you before you get to find the OEP, check all the usual 'time' functions (GetTickCount, QueryPerformanceCounter, GetLocalTime, GetSystemTime etc.). This, though, is a last resort (as you'll be doing little more than stabbing in the dark), and I've never found it to be necessary at this stage of the reversing.

Good luck
Admiral

LLXX
August 29th, 2005, 04:10
This version of Armadillo is probably a very new one. I tried the hardware breakpoint on WriteProcessMemory, but it still doesn't break, and again terminates with exit code 128. Somehow this Armadillo is detecting the hardware breakpoints or something about Olly that I didn't manage to hide properly. In fact, I placed a hardware breakpoint at the end of WriteProcessMemory, right on the ret. Result: again terminates with code 128 when attempted to run it. I then tried running it without any breakpoints set at all, but it still returns 128.

I had the crazy idea of cutting and pasting the entire .pdata section from my target over that of an Armadillo crackme I found, since I unpacked that one successfully, maybe it could unpack the .pdata of my target for me. Unfortunately this idea didn't work.

I searched the Internet and found "Armadillo unpacking ollyscript by MEPHiSTO", which worked perfectly, stopping at the OEP and reporting that this file was packed with Armadillo v3.70a with Debug-Blocker Protection. No CopyMem II, nanomites, nor code splicing. I used the ImpRec to dump the file and fix the imports, it now works perfectly identical to the original after substituting the import SetLastError in place of the equivalent API 2K/XP specific RestoreLastError (otherwise it would refuse to run on 9x). The file was 6 times the size of the packed one, but it was due to the .text1, .data1, .adata, and .pdata sections of the now-dead armadillo remaining in there. This was corrected by deleting the sections and relocating the .rsrc and .idata which was originally after the deleted sections.

I know I'm "cheating" a bit by using the ollyscript as opposed to doing it manually, but the Armadillo isn't the main focus of this reversing project. Nonetheless, I still wanted to know how it could be done, so I read the script. It breaks on kernel32.OpenMutexA, msvcrt.time, msvcrt.strchr, and kernel32.VirtualProtect. This means an automated unpacker for all Armadillos could conceivably be made. I'm going to try unpacking this target again, manually, following the script as a sort of "tutorial", just for fun and to gain some more knowledge.

Quote:
When set to maximum protection, Armadillo encrypts its target several times over using different algorithms. Silicon Realms Toolworks seem quite proud of the fact that 'even they' can't decrypt your program without knowing your private key, so I doubt you'll have too much luck decrypting it manually.

Well, it appears I've defeated the Armadillo. My unpacked target is running as good as a virgin. Now, onto the real part of the reversing project...

Thanks for helping.