Log in

View Full Version : Mini-tute: Getting rid of Armadillo nag


nikolatesla20
December 10th, 2002, 20:22
Heh. Hope someone finds this useful/cool. Just got er done.

Code:

********************** KILL THE NAG *************
***
*** Target: Armadillo 2.65 build 2221
*** Freed By: nikolatesla20
*** Date: December 10, 2002
*** Purpose: Freeing
***
*************************************************



Hi all,

This is a tutorial about using armadillo to protect your own files without having to have a registered armadillo program.

I've been working with Armadillo for a little while now, just trying weird things to see how I can break it. I've been protecting my own test files, and then trying to load them into my own loaders, debuggers, etc, to edit memory during run time. Most of the time armadillo seems to catch something is wrong if it's too early, and it bombs out on you. I tried one very unique thing this morning however, and it worked, and I think it's quite hilarious......

When you download the armadillo evaluation, there really are no limits. You are allowed to use it as long as you wish, but you cannot distribute with it. The main item that prevents you from you doing so is a nice little nag screen that comes up before your protected app that says "This version of armadillo is not registerd..blah..blah..not licensed for distribution". Since CruSader already gave us such a nice tutorial on removing armadillo protection, I decided to try an opposite approach, so I could USE armadillo, but I'd have to kill this nag in my own protected apps. It really is no problem to dissassemble a protected file in IDA, but you won't find the nag in there anywhere. Why? Because it's in the DLL that gets decompressed into memory during runtime. This is the "arma.dll" that CruSader tells us how to dump from memory.

But still, that doesn't help us, because then the only way around it would be to patch that file in memory after it was unpacked during your protected program's startup. The only reliable way to do that would be to either inject code or put another wrapper around your already protected application. I tried those techniques and got away with some things (like adding another section, etc.) but not others (couldn't use a cave). Armadillo was pretty good at preventing any code redirection as well, with some sort of CRC checks and stuff.

Suffice it to say I got bored looking at doing it this way. What I really needed was a way to have the armadillo.dll file ALREADY be how I wanted it BEFORE it ever made its way into my protected application. Well, I found the way to do that.

CruSader seemed happy that he could dump the armadillo.dll from memory while in his protected app, but did you know that it simply sits naked inside armadillo.exe itself? Yes, its just a simple resource file. And lo and behold, its not even CRC checked. Can you believe it?

So for starters, if you don't have a dumped dll file from going through CruSader's tutorial, you can get one very easily by using eXeScope and opening armadillo.exe, and going to the resource section. The DLL's are under the "HEADERS" resources. Take the third one in the list, and export it as "whatever3.dll". Now you have a clean DLL. No memory dumping required ! It's not even encrypted ! *oops* Silicon Realms!

Open that sucker up in IDA. Go to "MessageBoxA" reference, and double click on the second call reference and you will see this code:

Code:

.text:1000E9BD sub_1000E9BD proc near ; CODE XREF: sub_1000DE51+606p
.text:1000E9BD ; sub_1000E55A+33j ...
.text:1000E9BD
.text:1000E9BD var_4 = dword ptr -4
.text:1000E9BD
.text:1000E9BD push ebp
.text:1000E9BE mov ebp, esp
.text:1000E9C0 push ecx
.text:1000E9C1 push ebx
.text:1000E9C2 push esi
.text:1000E9C3 push edi
.text:1000E9C4 call sub_1000F40B
.text:1000E9C9 mov eax, dword_10022EC4
.text:1000E9CE mov esi, ds:MessageBoxA
.text:1000E9D4 mov ebx, 10040h
.text:1000E9D9 mov edi, offset aDistributionWa ; "Distribution Warning"
.text:1000E9DE mov eax, [eax+4ECh]
.text:1000E9E4 test eax, eax
.text:1000E9E6 jz short loc_1000E9EF <-- this checks for a good message string in memory
.text:1000E9E8 push ebx ; uType
.text:1000E9E9 push edi ; lpCaption
.text:1000E9EA push eax ; lpText
.text:1000E9EB push 0 ; hWnd
.text:1000E9ED call esi ; MessageBoxA
.text:1000E9EF
.text:1000E9EF loc_1000E9EF: ; CODE XREF: sub_1000E9BD+29j
.text:1000E9EF mov ecx, dword_10022EC4
.text:1000E9F5 call sub_1000B710
.text:1000E9FA test eax, eax
.text:1000E9FC jz short loc_1000EA10




Notice that jump if zero on 1000E9E6? It will completely jump over showing the "unregistered" nag if it notices that there is no string in memory to show. We want that jump to jump always, in other words, change its byte from 0x74 to 0xEB. So let's do it!

Open up LordPE or PEditor and get the Hex offset in the file of that instruction and write it down. I came up with 0xE9E6.

Now, open armadillo.exe again in eXeScope. Go to the "HEADERS" resources again, and click on the third item (Resource ID 121 in my version). This is one of two versions of the armadillo.dll (ID 121 and ID 153). Anyway, notice it already has an offset in the file. Fire up Calc.exe and add (Resource offset + instruction offset). BE sure you are in HEX mode in Calc!. This is where you will find the offending instruction. Now, scroll down in eXeScope to the address. I have the latest armadillo evaluation version (2.65 build 2221) and the address I got was 0x97466. Once you get there, simply type in the new byte value "EB". Done!. Now you have to do the same thing for the second version of the DLL. The difference between them as I found was one uses SI detection, and the other doesn't.

The other DLL is Resource ID 153. I'll let you calculate the offset to the instrcution. REMEMBER tho that you will have to export and dissassemble this DLL to get the instruction's address again. Since its a different version it won't be in the same place. Once you have edited both resources, you are good to go! Go back out and protect your file, and test it. Wooot! No more nag screen. Now I must say that is quite sad that the Silicon Realms guys put so much work into "anti-crack", etc, but they never seem to bother checking their prebuilt code blox. Well I guess others can enjoy the mistakes eh?

'Til next time...

-nt20

*Remember you have to BUY software if you really want to use it so if you use this software please support the authors and purchase it*

crUsAdEr
December 11th, 2002, 00:30
Very nice, Nicola ...

I exported all teh 5 dlls and look at them, but they are also different from the dll i dump??? Funny.. i guess armadillo append which dll depends on which option of protection you choose??? Not sure...

Armadillo is a weak protection heh... now that it has also been keygenned and unpackers are coded (private though)... i guess we'll expect armadillo 3.0 soon, wonder why there are still apps protected with armadillo...

Next packer on the bashing list ??? any idea ?

cheers
crUsAdEr

P.S : Nikla, maybe you could study armadillo further and tell us how the different dll are used.. i am going on my holiday ... have fun and keep us up to date with reversing

nikolatesla20
December 11th, 2002, 01:44
Thanks for the comments crusader...sometimes I feel though I may never approach the skill level that you are upon! I just try to think out of the box when I can as well


Ya, crusader, it appears to use a different file depending on the protection options you choose.

By the way, two of those files are actually EXE's. You can tell by looking at their imagebase. In fact, it's basically the entire code the gets wrapped around your app. They all come together to form the final protected program.

OH - just one more thing for you crusader if you are reading this, I dumped arma itself but I'm still having trouble fixing the int3's..oh well. Thank you very much for the information and tutorials !

As for the next protection....well you know Code-Lock still has not been fully defeated. Although it's easy to pirate (just hard to "*rack".

I have an idea for a new utility but I still haven't had much success coding it yet. It would be a utility to help reverse protections that use COM objects, such as Code-Lock. AND event tho armadillo has been defeated by a lot of people, I still wouldn't mind to continue trying to make my own little unpacker, just to learn how its done. But I haven't gotten too far just yet.

-nt20

crUsAdEr
December 11th, 2002, 02:20
Hi Nikola,

What is the problem with int3 fixing? I was thinking of coding a generic int3 fixing prog but i have no time, and arma is losing my interest...

CodeLock ? Probably nice protection but i reverse for the fun of it, and VB is not fun to reverse so ah well... maybe, one day but not now ...

cheers,
crus

nikolatesla20
December 11th, 2002, 15:14
Um ok, this is the int3 trouble I was having. I know I can edit your dumpfixer sources, but I just thought it would be good to explain this.

I'm a "fairly" certain I've followed the dumping of the jump tables from memory correctly. I dumped the whole table in one chunk actually the third time I was trying this, and then just broke it up with Hex Workshop into the 4 pieces required.

Basically, and I know I dont want to depend on canned tools of course (gotta use your brain), the EXE that exists right now for fixing exits telling me it can't find the right jump opcodes. OK. So I walked thru the code manually , no not debug mode, just on paper and pen , to see what it was doing. What was wrong with my tables....

The first thing that makes me wonder is the address table that I get from arma. Here is a snippet from its beginning. I know this is the beginning because I stepped thru the code to find out the exact address it was using for the address table (table_1).

Here are excerpts from the 4 tables, I've brought out the first value on its own for your inspection.

This is the address table (table_1)

Code:

69214000
462F4000503640003E3C4000B74240000D4340008C44400021464000024E4000086A40002C6A4000AB6B4000B86B4000BF6B 4000C16B4000B1764000BE764000C5764000D7764000E0764000


Here is the first entry in the "distance" table (table_4):
Code:

90E0BFFF
D6D0BFFFC9CABFFF0BC4BFFFB5BDBFFF67BDBFFF6ABBBFFF16B9BFFFC3B2BFFF1C97BFFFC497BFFF04000000


That's a pretty big negative number!

And here is the "jump instruction length"
Code:

05
010501010101040405040405010404050505010401010104050505010101010404050505050501010101050101040405


and finally the "jump type"
Code:

02
020E0D02080E0E0E0E02020E0E020C0C0C0E0C08110E0C1108110E0C010E0E020C0C0C020211020E02110E0E0E02020E


If you notice the first address in this table is 00402169. And yes, if you go to that location in a HEX editor there will be a CC byte one bye before it. However, if you look at the code location in WinDASM, it appears to be a valid code sequence:

Code:

:00402113 55 push ebp
:00402114 8BEC mov ebp, esp
:00402116 83EC54 sub esp, 00000054
:00402119 8B4508 mov eax, dword ptr [ebp+08]
:0040211C 53 push ebx
:0040211D 56 push esi
:0040211E 57 push edi
:0040211F 8D9800100000 lea ebx, dword ptr [eax+00001000]
:00402125 6A12 push 00000012
:00402127 59 pop ecx
:00402128 8D75AC lea esi, dword ptr [ebp-54]
:0040212B 8BFB mov edi, ebx
:0040212D C745AC886A3F24 mov [ebp-54], 243F6A88
:00402134 C745B0D308A385 mov [ebp-50], 85A308D3
:0040213B C745B42E8A1913 mov [ebp-4C], 13198A2E
:00402142 C745B844737003 mov [ebp-48], 03707344
:00402149 C745BC223809A4 mov [ebp-44], A4093822
:00402150 C745C0D0319F29 mov [ebp-40], 299F31D0
:00402157 C745C498FA2E08 mov [ebp-3C], 082EFA98
:0040215E C745C8896C4EEC mov [ebp-38], EC4E6C89
:00402165 C745CCE6212845 mov [ebp-34], 452821E6 <- supposedly there's an int3 here
:0040216C C745D07713D038 mov [ebp-30], 38D01377
:00402173 C745D4CF6654BE mov [ebp-2C], BE5466CF
:0040217A C745D86C0CE934 mov [ebp-28], 34E90C6C
:00402181 C745DCB729ACC0 mov [ebp-24], C0AC29B7
:00402188 C745E0DD507CC9 mov [ebp-20], C97C50DD
:0040218F C745E4B5D5843F mov [ebp-1C], 3F84D5B5
:00402196 C745E8170947B5 mov [ebp-18], B5470917
:0040219D C745ECD9D51692 mov [ebp-14], 9216D5D9
:004021A4 C745F01BFB7989 mov [ebp-10], 8979FB1B
:004021AB C745F804000000 mov [ebp-08], 00000004
:004021B2 F3 repz
:004021B3 A5 movsd




It's just that it doesn't look like this location needs patching at all, in fact, if you run thru arma, I put a bpx on the code that reads from the tables, (especially the address table) and it never breaks on any address below 00416000. In other words, an Int3 never comes thru with an address below that. I have no idea why these lower addresses are in the table..I'd say about the first 10 or so addresses for sure appear to contain valid code sequences. The only thing I can think of is of course to mislead an autopatcher.

I'm thinking all you really need to do in the dumpfixer is to ignore errors and just keep going on to the next location, instead of bombing out right away. Only thing I can think of right now.

I still must be missing something..mabye this is going out on a limb but seems like some of these int3's might be function calls now and not just jumps..

-nt20

crUsAdEr
December 11th, 2002, 15:55
No Nikola,

Sorry for the misleading info but the DumpFixer will not bomb out as you think... not all the address in the tables are used... if you look at my source code, it will walk the address table, read each address, munis 1 byte, then check if there is a CC there, if there is then it is an int3 replacing jump, if not then get next entry of table...

The dump fixer will only bomb out because the jump type classification is changed... for my version of armadillo for example, jump type B is a LONG JUMP E9xxxxxxx but for another version it is a JNZ short jump for example.. hence the program will check the length of the instruction as well, just to be sure not to mess thigns up... That is why my fixer bomb out...

So to make it work for your case, you will need to look into the Jump_classify routine of armadillo server to get the type number and then rearrange the order of my Data declaration... the first entry is type 0, then Type 1 etc... that is all you need, then compile and run...

You can try coding somethign more generic, that will read the Jump_Classify routine automatically and retrieve the jump type classification etc...

Hope this helps,
crUsAdEr

nikolatesla20
December 11th, 2002, 16:04
Thanks crusader, yep I just thought of that, and was starting to look into it I figured the jump codes must have changed in this version.

-nt20

nikolatesla20
December 11th, 2002, 18:07
crusader , just one more little bit of help, and I've got it. Thanks for the help so far.

Look, I just have trouble with bit ops in my head. I can handle AND and OR but SBB and NEG are killing me for some reason. Does this look right?

Code:


mov edx, [ebp+Context_Arg]
.text1:0045357B mov eax, [edx+CONTEXT.EFlags]
.text1:00453581 and eax, 0C0h ; Check zero flag and sign flag
.text1:00453586 neg eax ; eax negative if either flag is set
.text1:00453588 sbb eax, eax
.text1:0045358A neg eax ; eax = 1 when neither flag are set
.text1:0045358C jmp loc_453626



I just can't get my head around it ! grr!
-nt20

crUsAdEr
December 11th, 2002, 18:21
Yep...

Here is my version

Code:

case_2:
mov ecx, [ebp+context]
mov eax, [ecx+CONTEXT.EFlags]
and eax, 0C0h ; check Zero and Signed flags
neg eax ; set Carry flag if eax!=0
sbb eax, eax ; eax = 0 if Carry flag not set
inc eax ; al = 1 if S and Z flags both not set
jmp loc_44F1FC ; al = 0 if either flag set
; JG


It will jump when al==1

Hope this helps ...
crUsAdEr

nikolatesla20
December 11th, 2002, 19:56
*sigh*

I fear this is over my head for now. I just start falling asleep looking at bit ops. I thought I had the order right, but the my dumpfixer still wont work.

Guess I need to sleep on it some more

-nt20

nikolatesla20
December 11th, 2002, 21:59
ALright!

I got it yay!

I went thru and did as many as the jumps as I could looking at IDA ( I mean I figured out the "jump table". Then rearranged your JMP opcodes to match.

The problem was that I did happen to have a bad table_2 dump. I was missing the first 4 bytes. I ran armadillo again and put a bpx in the code that get the jump type and noticed that my table wasn't in the right location, so I went back out the hex workshop and fixed it, ran the patcher, and it worked.

armadillo is now running just fine all unwrapped and happy. AND it's a LOT faster.

Thanks for your help and bearing with me, crusader ! (I still hate looking at bitwise ops tho)

-nt20 (happy boy )

oh, and here's the new asm code for patching the int3's of the latest armadillo evaluation version.

szon
December 13th, 2002, 21:02
Hmmm you want to crack it but i saw few days ago keygen for armadillo :>

nikolatesla20
December 13th, 2002, 23:22
Keygens wont allow you to disasm the code to perform your will upon it.

There are several ways to approach a target. Why do some consider patching to be "ugly?". I consider it the just as good as keygenning, isn't the whole point to reverse engineer? Yes it is. When data is on my hard drive, it belongs to me. I wish to modify it. While I would say people who write keygens are very intelligent to be able to figure out the algorithms involved, everyone had their own preference.

I do not prescribe to any particular reverse engineering religion. No thank you, I respectfully decline.


-nt20

Iwarez
December 13th, 2002, 23:43
Also using someone else's keygen won't make anyone any smarter. Reverse engineering a protector and understanding the inner part does. After that you can always decide to use the keygen.

My noble opinion...

ReaL|sTy
January 2nd, 2003, 23:28
great information... thid board is great to share knowledge and information this is great information and i just grabbed it sure armadillo ins't so good at all you can even patch the main Nag window for the armadillo program without unpacking it and just one byte hex edited needed 82/90 or 80/7E if you know what i mean i agree with iwarez comment. thanks god people and board like this one exist!

SpeKKeL
February 7th, 2003, 12:57
Hajo,

H'mmm we are back in town .....??!!
I was playing with lydia (email checker) what i think is a nice prog(fast and easy).It's protected with armadillo and i just wondered if i could patch the prog in high memory(9xxxxx), but i can't.
I found the places:expired or not ,the set back clock check and even a nice build in utility which is called fixclock (it resets the install date to the time it is,so another 30 days to go)
So if i only could patch it(i used all memory patchers but all faild)
Any solutions for patching ??

(btw removing the nag works 100 %)

SpeK.