Log in

View Full Version : Strange armadillo target


Heathcliff
June 9th, 2004, 06:02
Hi all,

I'm back after 2 years of no reversing. I found a usefull tool, but I can't seem to get it correctly unpacked. I know it's Armadillo, but it looks like it got some new features. I tried to follow the tuts from Ricardo (excellent job!) Here are my notes:


To find target search Google with these keywords (this is not the target name!):

nyfnet client


Notes:

DebugDetectionByte: 7FFDF002
DebugEventFrame: 12EB88
OEP: 401000
.text: 401000 - 527000


The unpacking:

Start OllyDbg
Debug options, exceptions -> Ignore all.
Load target exe
In hex pane: Go to Expression 7FFDF002
Type 00
BP WriteProcessMemory
3 x F9
In code pane: Go to Expression 5D022A (this is the encryptor call)
Space (Assemble): NOP
Go to Origin
F2
SHIFT-F4: Log expression: [ESP+8] (optional)
CRTL-F9
F7
Start PUPE
Note the ProcessID of the first target process in list (child)
Right click on this process and select 'Parchear'
Set number of bytes to: 2 (arrow down)
Set OEP: 401000
Click 'Buscar' (search)
Note 2 bytes: EB10
Type bytes for infinite loop: EBFE (will let the child sleep on entrance)
Click 'Parchear'
Close Pupe
Go back to Olly
BC WriteProcessMemory
BP WaitForDebugEvent
F9 (to hit the BP)
In code pane: Go to Expression: 5CD7F0 (skip event to return-address)
New Origin Here
Go to Expression: 5CD7DE (to show assembly from the right address on)
Space (Assembler): NOP complete call with pushed arguments from 5CD7DE to 5CD7EF)
Select 5CD7F0 and Space (Assemble): JMP 401000 (NOP is added, note: code continues at 5CD7F7)
Replace OEP values in DebugEventFrame with: 00 00 40 00
Go to Expression: 401000
Space (assemble):
ADD DWORD PTR DS:[12EBA0],1000 (Locations in DebugEventFrame where OEP is)
ADD DWORD PTR DS:[12EBAC],1000
ADD DWORD PTR DS:[12EBB0],1000
CMP DWORD PTR DS:[12EBB0],527000 (End of .text)
JNZ 5CD7F7 (Don't continue original code after the last unpack-section)
PUSH 21C4 (childs ProcessID is shown in PUPE)
CALL DebugActiveProcessStop (Detach child)
NOP
BP on last NOP
When the BP is hit exit Olly (kill the parent-process)
Restart Olly
Attach to child (ignore warnings)
When EIP is in ntdll, hit CTRL-F9 until in target
In hex-pane: Go to Expression: 401000
Type: EB 10
Start LordPE
(If there are too many processes, burn some of them to get the child visible)
Select IntelliDump
Dump full: Dumped.exe
Click 'PE Editor' (or open any other PE Editor, it doesn't matter)
Open Dumped.exe
Change EntryPoint to: 00001000
Calculate Checksum
Save
Close LordPE
Running Olly can be closed
Start new Olly
Open Dump -> Olly error: Unable to start file 'C:\Dumped.exe'


So it seems i cannot open the dumped exe in Olly! It is however possible to open the dumped exe in IDA Pro. I'm trying to work around this problem and get the IAT reconstructed in another way, but it would sure help if someone could tell me why Olly won't open my dump!

Some other things I found out when I opened my dump in IDA:
- The tool is written in Delphi
- The registration is done with ArmAccess.dll (part of Armadillo). This dll is hard to reverse, so it would be much easier to get the dump fixed and patch the dump so ArmAccess.dll will not be called anymore and make it 'always registered'.
- Search for 'REGISTERED' and scroll up and down to see the registration code.

I'm not sure yet if this target has nanomites. I haven't looked into that yet.

Any help is appreciated!
Thanks in advance to Ricardo for his great tuts!

Greetz,
Heathcliff

Heathcliff
June 9th, 2004, 06:28
I found out that if you don't close Olly with the child process at the OEP it is possible to continue with seaching for the IAT etc (as described in Ricardo's second tut).

The jumps to the IAT start at: 525A98
The IAT is: 563000 - 564147

There is a lot missing here and I suspect some import-redirection.

I'm still wondering why I can't open the dump in Olly, coz I might need this later on.

Heathcliff

dELTA
June 9th, 2004, 19:58
Always nice to see one of the names from the good old days return, welcome back Heathcliff.

Heathcliff
June 13th, 2004, 19:20
Hi all.

Thanks dELTA. It's good to be back. But this Armadilla really gives me headages! Some help is appreciated here! This is what I've got:

The parent is 'debugging' the child. When the child has sent 47 debug-events to the parent, the offsets for the IAT have just been copied and the IAT is about to be filled with absolute addresses (original and redirected) before jumping to the OEP. So the child needs to be debugged at that moment. The parent needs to be detached and killed before OllyDbg can attach to the child-process. But the child must not continue to fill the IAT. It is not possible to alter the code in the child-process because the parent will kill the process. Ricardo's trick to set an infinite loop at the 'magic jump' does not work on this target. So an infinite loop must be placed in an API-call which is used by the child and then the child will wait for us to attach Olly. The routine for filling the IAT starts at 00C8F453 (addresses may have a different offset on other systems). The first imported function which is called is 'msvcrt.strchr'. This is the API-call in which the infinite loop has to made with Pupe. After the parent is detached and a new Olly is attached to the child, the child can be altered so it will fill the IAT with original addresses.

The loop, which fills the IAT, is different from what Ricardo describes in his tut. In the first part the next DLL-name is retrieved from the IT. If it reached the end of the IT, loop will exit at 00C8F48E. This is where an infinite loop must be set to pause for the Import Reconstructor when the IAT is built.

The loop which really fills the IAT-entries for the DLL's in the IT starts at 00C8F7CC. In this loop a table with redirected addresses is checked first. If a redirected address is found for the function-address currently being calculated, this address will overrule the address of the real DLL-import. If no redirected address was found, the base-address of the DLL will be added to the offset in the IAT. To prevent the redirected address being retrieved, the code at 00C8FA3B has to be filled with NOP.

There's another trick. This trick makes it difficult for Import Reconstructor to correctly sort out the different DLL's in the IAT. The zero's, which normally indicate the end of an DLL in the IAT, are also being replaced with redirected addresses. To prevent this the code at 00C8F8E7 has to be filled with NOP.

When I looked at the IAT, I noticed that NOT all entries had been calculated. It seemed there were no correspondent entries in the IT for them and I also couldn't find code using these entries. So they seem unused. And my guess is, that the only reason they're there, is to accomplish some harmless error reports in Import Reconstructor. I think the errors in Import Reconstructor could be safely ignored.

After I used Import Reconstructor to fix my dumped exe I still have same problem as I had before. My dumped exe can't be run in any debugger! Olly still reports 'Unable to start file 'C:\Dumped.exe' when I try to open the dumped and fixed exe. IDA is able to load the exe, but when I try to
run it, it reports 'Command "ProcessStart" failed'. Arg! When I open the exe in PE Editor everything looks normal.

When I try to run the exe it reports:
C:\Dumped.exe
Only part of a ReadProcessMemory or WriteProcessMemory request was completed.

This is the same message I got before I fixed the IAT. I hoped the fix would enable me to use a debugger on the exe, or fix the ProcessMemory errors. But it didn't. I'm kinda stuck again. Maybe it's all easy to fix, but I must at least be able to run this dumped exe in a debugger. Can someone please give me an indication of how it is possible, this exe cannot be run in any debugger?

This is what I did to get the IAT fixed for my exe:

Start new Olly
Open original exe
Reset Debugging-flag
BP WaitForDebugEvent
47 x F9 (After 47th time WaitForDebugEvent the IAT was build and now being destroyed)

View Executable Modules
Right click msvcrt
View Names
Look for 'strchr' and write down the address (77C43600)

Open Pupe
Select first target (child)
Write down the ProcessID (1E18)
Right click
Parchear

Optional:
Number of bytes: 4
Enter address: 563360 (Redirected IAT-Entry)
Buscar (Search)
Check to see if it contains an offset: D0 42 16 00

In Pupe enter address: 77C43600 (= strchr)
Numer of bytes: 2
Buscar (Search)
Write down the original contents: 33 C0
Enter new values: EBFE
Parchear

In Olly code pane: Go to Expression: 401000
New origin here
Space (assemble)
PUSH 1E18 (ProcessID of child)
CALL DebugActiveProcessStop
NOP
Select the NOP
F2
F9 (EAX must be 1 when the BP is hit, CPU usage goes to 100%)
Close Olly

Start new Olly
Attach to target (only child remained)
CTRL-F9 (to get from ntdll to the infinite loop on msvcrt.strchr)
In Code pane: Go to Expression: 77C43600
Enter original values: Binary Edit: 55 8B
CTRL-F9 (to get to the IAT-filling)

In Code pane: Go to Expression: 00C8F48E
Binary Edit: EB FE
In code pane: Go to Expression: 00C8FA3B
Space (Assemble): NOP
In code pane: Go to Expression: 00C8F8E7
Space (Assemble): NOP
F9

Run Import Reconstructor
Select child process
Fix dump

My guess is, something already went wrong when I dumped the exe. But I have no clue.

HELP!

Heathcliff

nikolatesla20
June 13th, 2004, 22:52
Quote:
[Originally Posted by Heathcliff]Hi all.

TThe loop which really fills the IAT-entries for the DLL's in the IT starts at 00C8F7CC. In this loop a table with redirected addresses is checked first. If a redirected address is found for the function-address currently being calculated, this address will overrule the address of the real DLL-import. If no redirected address was found, the base-address of the DLL will be added to the offset in the IAT. To prevent the redirected address being retrieved, the code at 00C8FA3B has to be filled with NOP.

There's another trick. This trick makes it difficult for Import Reconstructor to correctly sort out the different DLL's in the IAT. The zero's, which normally indicate the end of an DLL in the IAT, are also being replaced with redirected addresses. To prevent this the code at 00C8F8E7 has to be filled with NOP.

When I looked at the IAT, I noticed that NOT all entries had been calculated. It seemed there were no correspondent entries in the IT for them and I also couldn't find code using these entries. So they seem unused. And my guess is, that the only reason they're there, is to accomplish some harmless error reports in Import Reconstructor. I think the errors in Import Reconstructor could be safely ignored.


Those are most likely the traditional entries in between DLL thunks, which should normally be zero, instead they put in some junk code. No matter because if the rest of the IAT is valid, you can just open up the tree in ImpREC (expand the "bad" invalid tree), scroll to the bottom of the tree, and you will see the invalid thunk. All you have to do is right click on choose "delete thunks" to get rid of the bad entry, an wallah your thunk list becomes valid.


For Olly, also make sure your imagesize correctly matches what it really should be (the imagesize entry in the header). And check the sections for their read/write/execute settings, and sometimes Arma puts in garbage for the "Pointer to symbol table". Remove this pointer completely, set it to zeros.

-nt20
-nt20

Heathcliff
June 14th, 2004, 01:39
Quote:
[Originally Posted by nikolatesla20]Those are most likely the traditional entries in between DLL thunks, which should normally be zero, instead they put in some junk code. No matter because if the rest of the IAT is valid, you can just open up the tree in ImpREC (expand the "bad" invalid tree), scroll to the bottom of the tree, and you will see the invalid thunk. All you have to do is right click on choose "delete thunks" to get rid of the bad entry, an wallah your thunk list becomes valid.


For Olly, also make sure your imagesize correctly matches what it really should be (the imagesize entry in the header). And check the sections for their read/write/execute settings, and sometimes Arma puts in garbage for the "Pointer to symbol table". Remove this pointer completely, set it to zeros.

-nt20



Okay! Thanks alot! I will try this..

Greetz,
Heathcliff

Heathcliff
June 14th, 2004, 05:26
Damn! This is really starting to freak me out! I followed all Nico's instructions:

- I set the Base of Code to: 00001000 (VOffset of .text, flags seem ok)
- I set the Base of Data to: 00127000 (VOffset of .data, flags seem ok)
- I filled Pointer of Symbol Table and Number of Symbols to 0
- I set the IAT offset and size to 00163000 and 00001168
- I recalculated the checksum
- The ImageSize was already ok: 00327000
- I reconstructed the imports again, but now I deleted all invalid thunks.

I still can't seem to run this dump in the debugger! Any more suggestions are very welcome!

Some extra notes from me for people who want to help me:

- The IAT seems to be from 563000 to 564167 (not 564148, as I said before). So in ImpRec use offset 163000 and size 1168.
- If you remove the infinite loop in msvcrt.strchr at 77C43600, replace it with 33 C0 (these are the original values and not 55 8B, as I said before)

This target is in some aspects different from the target in Ricardo's tuts:
- The call to the decrypter and the encrypter are different from eachother
005D0172 CALL 005D04BF (= decrypter for dumping)
005D022A CALL 005DC4A0 (= encrypter for dumping, should be NOP)
- It is not possible to set an infinite loop on the 'magic jump', because the integrety of the child process is checked before building the IAT. Altering the child will cause it to end the process. Set the infinite loop in msvcrt.strchr work ok though.
- The routine for filling the IAT is very different. Many offset don't seem to be calculated, because they are unused. The end-marks for the DLL's in the IAT are being overwritten. The CALL Ricardo refers to for patching is in this case only being called when writing correct values to the IAT, so other patches have to made (as I described in a previous post in this thread).

I really hope someone can help me out! I suspect I still have an invalid PE-header somehow. If someone want to look at it I can PM my dump.

Greetz,
Heathcliff

crUsAdEr
June 14th, 2004, 06:01
Hi Heathcliff,

I decided to look at this one... i assume u r talking abt the client version...
here are my finding
OEP : 1000
IAT start : 163138

I am not sure what your IAT problem is cos this one is 3.50a, doesnt have Import elimination...

Heathcliff
June 14th, 2004, 06:12
Quote:
[Originally Posted by crUsAdEr]Hi Heathcliff,

I decided to look at this one... i assume u r talking abt the client version...
here are my finding
OEP : 1000
IAT start : 163138

I am not sure what your IAT problem is cos this one is 3.50a, doesnt have Import elimination...


Hi crUsAdEr,

Thanks for your help. I'm talking about the client-version indeed. I did find the OEP and IAT too. This target absolutely does have Import redirection. If you watch the IAT you will see a lot of addresses beginning with 00C8xxxx or anywhere near this address-range. Though all addresses should be something like 77xxxxxx. Anyway, this is not really my problem, coz I already successfully patched the routine for filling the IAT and everything seems to be ok now.

The main problem I have is that I can't open the dumped exe in OllyDbg. I keeps telling me Unable to start file 'C:\Dumped.exe'. I can't go on if it won't run in the debugger. Do you have this problem too?

Thanks!
Heathcliff

crUsAdEr
June 14th, 2004, 07:30
nope... i rebuild Import directory completely based on Import dump, didnt use Imprec at all... i can load the program fine with Olly, reloc need to be corrected but i can run it here...

I notice my IAT is a bit higher than yours... i did look at the range RVA 163000-163138 but they are not IAT entries... so perhaps that is why Olly wont load it...

Js
June 14th, 2004, 07:36
had exactly the same problem recently

try imprec with these options
rebuild original FT
create new IAT
use header from disk

didn't find out what the problem was, too old, fat and lazy now to be bothered but it worked.

Heathcliff
June 14th, 2004, 07:57
@ crUsAdEr

Well, I'm not really an experienced unpacker, but the first dump I made seems to be wrong. I don't exacly understad what you mean with rebuilding the import directory based on the import dump and correcting the reloc. Could you take a look at how I unpacked (see my first post in this thread) and see what you did different? And could you please explain in a bit more detail? The first dump I made can't be loaded in Olly. I did change the IAT to different addresses already, including the address you gave, but it doesn't seem to matter at all.

@ Js

The first dump I made cannot be loaded into Olly, so it doesn't seem to have anything to do with the reconstruction of the imports. I tried your suggestion anyway, but I still got 'Unable to start C:\Dumped.exe'. Thanks for your help.

Greetz,
Heathcliff

crUsAdEr
June 14th, 2004, 09:24
hi Heathcliff,

to be honest i dont understand what you did to unpack the program, truth to be told i have not read Ricardo's tut so i dont even know what you are talking abt up there...

if u PM me your email, i will could send u the unpacked.exe's import directory dump...

Heathcliff
June 14th, 2004, 11:55
Hey crUsAdEr,

I tried to add the dumped IT to my dumped exe. I added a section to my exe and entered the IT offset and size in the header, but still no luck!

Unable to start file 'C:\Dumped.exe'

The header of the original exe is a bit incomplete (some section offsets and sizes are set to 0). When I try to copy the original header to my exe, the sections are totally screwed.

I starting to feel defeated by those Arma-bastards!

Heathcliff

crUsAdEr
June 14th, 2004, 12:33
try one of those PE verifier... i think there was one posted recently in exetools forum...

Heathcliff
June 14th, 2004, 14:46
Well thanks for the tip crUsAdEr! I downloaded PEVerify and it came up with this error:

Error: resource name points out of image 69cb67f1h
File loading error code is 51 (breaked at offset 002b7000h)

I tried to open my exe in Resource Hacker and it gave me an error. If I open the original exe in RH all resources are visible, so they are not packed. My resources were f*cked when I dumped my exe!!

So I then copied the original resource with an hex-editor to the dump with the original IT attached. When I use PEVerify on this exe it says:

Error: imported DLL name points out of image 16b43800h
File loading error code is 56 (breaked at offset 002b5600h)

So there is something wrong with the imports. I am able to open the exe in Olly at this point, but Olly also gives some errors.

As I described in previous posts I did some efforts to reconstruct the imports. I kept this version of the exe and I now have copied the original resource section to the raw-offset in this reconstructed exe. I used PEVerify once again and it now says everything is ok!!

AND I CAN FINALLY OPEN IT IN OLLY AGAIN!!

Pfff! Thanks to PEVerify I can finally continue with normal cracking! And all my efforts to reconstruct the IAT also have payed off! I still don't know why my resource got screwed. I tried dumping on different machines with different dumper-progs. I think the resource-memory is already relocated when I enter the OEP.

Anyway, thank for all the help so far, guys!

Heathcliff

Heathcliff
June 17th, 2004, 05:18
Damn! This one use Strategic Code Splicing (same sort of thing as Nanomites, but a little bit different). See also: http://www.woodmann.net/forum/showthread.php?t=5330

There is nowhere a good description of how to defeat this.

The easy way is to dump the memory where the spliced code is right after the exe is dumped. It must be done in the same session, because the spliced code is relocated every time you run the exe. You can see where the spliced code is by viewing the jump at 401145 (this is the first jump to spliced code) right after the exe is dumped. The spliced code must be added as a section to the dumped exe. Then add some code which allocates some memory at the same address as the original address of the spliced code and then copy the code to this allocated memory. After this is done the code must jump to the OEP. And the EP must be set to this new code.

The hard way (better) is to intercept the code which overwrites the original code with a jump to the spliced code. Maybe this is not possible when the code is already modified during packing and not at runtime. I haven't found a clue where this might be happening. I'm not even sure this is happening in the parent process or in the child process.

I thought I was almost there. But it seems I still have some work to do.

Greetz,
Heathcliff

kyrios
July 5th, 2004, 15:39
Amazingly, you've returned after 2 years absent. Welcome back m8.
it's good to see you that you never give up.
Try to activate this option in LordPE:
Full dump: paste header from disk.

This option always needed in Arma, SVKP and TElock. Good luck heathcliff.

BR,
kyrios