Log in

View Full Version : nightmare protection on cache explorer


Lbolt99
April 12th, 2002, 16:18
I've been messing around with CacheX 4.51 for a week or so now and have a couple of questions. First of all, the author is paranoid and the protection is pretty heavy. A brief synopsis on the executable file: it is not "wrapped" with anything traditional like ASpr or whatever.. the author uses his own protection mechanism.

By debugging and trial and error, it looks like the program checks its file on disk as well as the image in memory. It does a couple of crc checks on the code and data in memory, placing various result codes in memory that are later used as decryption keys for sections of the program that are later decrypted. This decryption seems to occur throughout the program.

The one weak point I've found in the CRC check on disk -- the author placed the 32 bit "key" in the EXE file's data section, so one can replace the key in the EXE with the result of the calculation when debugging the CRC routine.

The memory is CRC'd at two spots, and I *think* I might be able to add code to the mem check routine to have it "fool" the checker if any patches are made.

The program has a nag on startup, as usual. If you bypass this, with the program expired (30 day trial), anything you try to do in the program will pop up the nag. I've found a way around the initial nag, but am having no luck figuring out the internal "check" that it does. It seems to use the same windows calls to pop up the nag that it does to do "normal program functions". I've debugged the program both normally and expired, at this point, nothing seems obvious.

Patching the memory it checks to see whether it should skip the startup nag, well, that seems to be detected by the mem check somehow. The decryption routines are screwed up at that point, and it page faults.

Registry keys: I found something in CLSID\blah\blah\CustomType which I deleted, and it reset it to 30 days. But it still detected this somehow. I installed the program on another machine, took the key it installed, placed it in. It *still* detected the tampering, and I can't find anywhere else on the system it might be comparing it with (ran filemon and regmon). The logical thing I can think of is that the key is stored somewhere else, and it's comparing it. Can't find anything though.

I originally wanted to take the keygen approach: the code is so complicated that I abandoned that idea and thought a hard patch would be better...

Any advice?

wbe
April 12th, 2002, 22:15
Long time ago, I dealt with it and had this daemon reversed (It was v4.0 or something).

Unfortunately, I don't remember what I did exactly. For me, the most difficult part was removing the antidebugging and tampering tricks. If I'm not mistaken, the app was messing with the .dat file of the temp cache for date check. That may help if it's still there. I don't remember any encryption either.

My advice: Install it afresh on a new machine and use a good monitoring app (Winalysis) for snapshots, if you're targeting a hard patch.

CacheX is a rare example of how a s/w can be protected without the aid of a ready made tool.

Good luck.

Solomon
May 9th, 2002, 07:04
yes its protection is quite good.
I tried it several years ago but failed. Will retry it later

Lbolt99
May 11th, 2002, 04:34
I think I've got this one figured out, finally, after working on it on and off for a couple of weeks (aspr stuff is too distracting

Basically, the crc check on disk is no problem, but the memory image checks are pretty complicated. I've come up with a way to inline patch them, sort of. It's pretty convoluted. My plan is to add a little code to "fool" the memory image checks.

I'm writing a tut as I work, to document what I did.. hopefully will be done next week.

crUsAdEr
May 11th, 2002, 19:04
Wow... what a hell of a protection... i do miss frogsice now.... the sice detection trick works real well with its crc and hash check... annoyed me to death!!!

But it was fun figuring out those sice check and overcome them without patching the file... time to dig up the owl's old tutorial :>...

A hell of a protection i would say... the hash table is as big as 1000h bytes so emulating it is out of question... some of the codes are decrypted in memory, executed and then deleted right after that... real neat!!... How are you getting on with your patching Lbolt99? I trie dpatching but found it real hard cos of excessive hash checking as well as the header is real well protected so we cant touch it at all!!!...

My approach for this one is find the decryption routine, wait for it to decrypt the code in memory, before relocation is performed, dump it, paste it over the encrypted code and disassmble, patch it to skip the whole decryption routine all together... debugging the decryption routine i have found that the same/similiar routine is used throughout the protection to decrypt code into memory, most of the code deleted right after that are not that important, though i dumped them and pasted them in anyway... there is one large chunk of encrypted code at the end where the DialogBoxParamA display the nags and the serial checking routine is stored, i dumped it... paste this one over and patch accordingly....

I have the prog running, but everytime i exit it crash :<... it works fine as long as i dont exit :>>... so i guess i patch it wrong somewhere and stack corruption occurs... or maybe there is still more check???

Really wonder how are you going to cause self deleting code to bypass those hashes:>???

regards,
crUsAdEr

crUsAdEr
May 11th, 2002, 19:32
On a second thought, since the proggie created its own jmp to DialogBoxParamA we can simply write a loader that hook this value and simply clear stack, return eax of 1 to emulate users clicking OK then the nag will never show up again :>>>... but ah well.. it was a good dumping the damn thing anyway....

Still wondering how you are going to bypass the hash check, then intercept the decryption routine to patch the DialogBoxParam? This inline patch has to be right in between the decryption routine and yet it has to pass the hash check??? you reversed it? (actually it might be possible... since serial checking routine is exactly same algorithm.... but rather time consuming) ... if not then how do you do it??

foxthree
May 12th, 2002, 15:16
Yo Crus:

May be it is time for you to join with Mike on the RCE Cryptographics forum. I'm sure your dreams must be full of bits xoring with other bits ...

Anyways, cool analysis. Both this and the arma stuff.... BTW, did u get my email on the ARM Dumper on Win98SE?

Signed,
-- FoxThree

crUsAdEr
May 14th, 2002, 08:51
Hey Lbolt99,

still working on this one? could you tell me how to patch it please ::>.. i am really curious abt your method... to all the lazy idling folks out there, get your butts moving cos this is a protectiion worth looking at :>>...

cheers,
crUsAdEr

Lbolt99
May 14th, 2002, 16:19
I've been working on it a bit today but haven't gotten too far. I have an idea of how to inline patch it but it won't work too well unless I can miminize the # of patches necessary to get the program up and running..

IF I can figure out how to get to the CALL EBX routine that jumps to the high mem location (has the dialogbox, etc) and do whatever patching is required, to "reg" the program, without requiring the internal "main loop" patch, or any further patches in the code segment, I think I can do it.. but I haven't been able to figure out how to NOT have to patch the "main loop" routine that constantly runs once the prog is up and running, awaiting user action, etc.

The patch around the nag inside the CALL EBX is easy, this one's got me:

portion of main loop code:
015F:0043F543 CMP [0044A048],EBP
015F:0043F549 JG 0043F562
015F:0043F54B CMP [0044A7F0],EBP
015F:0043F551 JNZ 0043F562
015F:0043F553 CALL 0043FE85
015F:0043F558 TEST EAX,EAX
015F:0043F55A JNZ 0043F562
015F:0043F55C INC DWORD PTR [0044A048]
015F:0043F562 CMP [ESI+000000C4],EBP
015F:0043F568 JBE 0043F5DB

I have to patch the 43f55a to a JMP 43f562 in order to prevent the program from popping up the nag whenever you try to do something in the program! I've tried "fooling" the routine with various memory values, it always seems to detect and/or overwrite anything I try to do.

It just requires too many patches to too many mem check routines if I have to keep the JMP 43F562 in there

I'm trying to see where it does the regqueryvalue.. I'm thinking that may give a few hints.

Lbolt99
May 15th, 2002, 04:25
Looks like Eclipse keygenned CacheX for Opera!! This may be the breakthrough I've been looking for. The keygen for v1.50 works for v1.51. I'm going to reverse the keygen and see what they did, etc..

Chances are the algo is just tweaked a little bit so codes for one product won't work for the other!!

They DID mention Blowfish and SHA-1, however. Not sure if they're talking about the keygen algo itself or the hashes all throughout CacheX.

So this is what I will likely focus on in the next few days. It was my original approach anyway, so I hope to learn a bit from what Eclipse did. So far, debugging the opera version, looks exactly similar to the IE version

Will post results as I work..

Lbolt99
May 28th, 2002, 16:57
OK, I have finally reverse engineered
a) eclipse keygen
b) cachex opera registration scheme
c) cachex ie registration scheme (similar)

This is one HELL OF a key registration scheme. It bites too because I *think* you need at least one valid key to find out a certain constant.. I believe eclipse might have have one which allowed them to keygen Cachex Opera. Because it wouldn't be too hard to do the IE and netscape versions to: the (obscured) constant changes.

*** GO TO THE CRYPTO area for a complete analysis and see if you agree ***

Lbolt99
June 4th, 2002, 14:36
Thanks for your input concerning your work on CacheX, and for sharing the registry entry info.. I had known about the registry entry, but didn't know the formula you came up with for how it works. BTW, the trick doesn't work on 4.51, which I believe was the author's response to this problem (no changes from 4.50 that I could tell EXCEPT the reg entry trick not working any more)

Quote:
Originally posted by Artifex

In Softice :
g 43f7e6
just rewrite the 3 first bytes in dd18cc with : c2 0c 00 (=ret)
and the program will work at any date !
It works because the CRC is made only on part of program from 43e4da to 4415c4.

Artifex


It kicks you out if you try to do anything though There's an internal check that's parts of the routine or whatever you call it that loops around, awaiting kb/mouse input. If the internal check fails, it actually proceeds to a different section of this loop, which doesn't normally run, and cause the nag to appear on anything you do. The way around the internal check (in softice) : portion of main loop code:


015F:0043F543 CMP [0044A048],EBP
015F:0043F549 JG 0043F562
015F:0043F54B CMP [0044A7F0],EBP
015F:0043F551 JNZ 0043F562
015F:0043F553 CALL 0043FE85
015F:0043F558 TEST EAX,EAX
015F:0043F55A JNZ 0043F562
015F:0043F55C INC DWORD PTR [0044A048]
015F:0043F562 CMP [ESI+000000C4],EBP
015F:0043F568 JBE 0043F5DB

You have to patch the 43f55a to a JMP 43f562

Lbolt99
June 20th, 2002, 17:32
CacheX continues to torment...

Been working on the dump method for the past three days.

Dumped and pasted in the code for the CALL EDI, the CALL EBX (the real long one with the messagebox stuff) and also one later on in the program before the startup where part of the import table is encrypted..

Fixed all 3 of those - basically I added a section with a few memory copy routines, patched the prog to jump to these routines instead of doing the blowfish executable code decryption.

Tried to maintain the integrity of the stack, etc, so I just crippled the final writes in the blowfish algo so it doesn't write anything.

The big problem I am having at this point is that the program comes up to the main screen, loads the cache, etc, but immediantly exits. I have tracked this down to a loop routine where it runs thru peekmessage etc, and specifically tracked it to a getmessage call. Basically, it just calls getmessagea, and exits! This happens after several iterations. The paramaters it pushes doesn't indicate anything wrong..

Crusader, if you are reading this, did you have this same problem? Maybe it has to do with the way I bypass the nag and the trial date check.

Artifex: have you made any progress?

Matthais: I think you'd make more money off this protection than CacheX itself


Thanks for any help anyone can provide.

BTW, checking the Win32 API for GetmessageA, there is nothing that would indicate it being capable of just exiting the proggy when called

foxthree
June 20th, 2002, 19:21
Yo LBolt:

Is it "the" message loop? Getmessage(), Translatemessage, DispatchMessage. I very recently "bug-fixed" an application that had a timer routine to check the licensed version apart from the initial check. That had to be on a WM_TIMER so on a WM_TIMER the app checked and just exited. Does your process also set a timer? Check it out. Also, you could try bpmb exitprocess and see what IP last executed before ExitProcess and then back and so on...

Signed,
-- FoxThree

crUsAdEr
June 21st, 2002, 18:33
Howdy guys,

Sorry cant contribute anything much anymore... I am on holiday now and i shant be touching sice for the next 3 months... hmm, actually my dumps work fine ( at least i think so, but i din fully test it), however, the program still crashes when i exit it... it might crash somewhere else as well but i din really test it so i cant be sure...

However, i think the loader approach might be most elegant, did you see how it calls the nag?... it dynamically create a call nag routine liek this
mov eax, offset CreateDlgBoxParamA
jmp eax

Since this part is not used by hashing code, if we can use a loader to wait till this routine is built, patch it to emulate a ret of eax=1 (continue click) then the nag will never appear again, i tot of this but that time i did not know how to write a loader, process patcher yet... now i can but i am not at home, then again it might not work... but process patcher is prolly a sure work way, except it might be slow sometimes... i use Process patcher on Pe Protect so i guess this cant be that hard...

Just some thought, have fun .. and see ya
crUsAdEr

Lbolt99
June 23rd, 2002, 20:21
Quote:
Originally posted by Artifex
CacheX v.4.51

I arrived safely at :
:0043EFDF E8682FFCFF call 00401F4C
That routine should display program window, but it crashes.
It is not a surprise for me :-)
It calls pieces of code in 69e000..., dd0000... and ed0000... I load them but surely not the right ones neither at right time, so it crashes.

Next steps would be :
43f00d : loads cache
43f05d : displays tips
43ed0d : expecting orders

Artifex.


Hi, that part where the call 401F4C contains a decryption routine for part of the import table. Actually, I don't really think its part of the import table. Just placed there to confuse. It's about 128 bytes in the .rdata section are encrypted, and decrypted sometime inside the call 401F4C using similar decryption technique that the CALL EDI and the CALL EBX used. (BTW, good technique on skipping over those).

I think at this point if you dumped and pasted in the 128 bytes in the .rdata section, and nop'ed out the decryption, it might work. You'll need a memory copy routine too.. since the decryption scheme writes the decrypted data out to high memory.. I had to emulate this with my own copy routine, after dumping and pasting.

You'll see references to things like CALL [EAX+70], with EAX+70 referencing a high memory address that contains bytes decrypted previously..

Unfortunately I'm not home right now else I'd help out and send the clip of the dumped .rdata segment off my system.. I might be able to get to it a little later today.

After startup, there is decryption at the Options, Search, and (if i remeber correctly) the import cache features of the program... found all these by putting a bpmb cs:43xxxx rw and seeing where it ran the hash on memory for the decryption keys..

Crusader: thanks for the input.. I don't think the loader approach would work however.. there is an additional check once it loads up, and will kick you out if you bypass the nag and the 30 days is up Also, I bet the search, options and import cache features don't work in the dump u did

Lbolt99
June 23rd, 2002, 21:46
Ok, as promised, here is the dump of the decrypted segment of the .rdata section. I've also went ahead and included dumps of the code at the CALL EDI and CALL EBX sections.

filename:

dump1: code inside the CALL EDI

dump2: code inside the CALL EBX

dump3: decrypted .rdata section

Paste dump3 in at offset hex 43878 in CXIE 4.51. You'll see that part is garbled compared to the rest of the import table

copy1: memcopy routines for dump1

copy2: memcopy """" dump2

copy3: etc

In the program's decryption mechanism, I disabled the memory-write instructions which wrote the decrypted bytes to high memory. Basically the program's decryption scheme would read data from low memory (the encryped bytes), decrypt and write to himem. I emulated this with my own memory copy routine, which copied the (dumped) data out of low memory and placed it in high memory at the right time.

Lbolt99
June 24th, 2002, 02:17
I think I missed this post! Didn't see it before. I tried this, and indeed, the same thing happened on an un-modified version of CacheX. So you are probably correct, the dumped version is not causing this, and that's also the reason Crusader's dump worked right.

Will work on it a bit more tomorrow.. still have to dump search, options and import archive, and Quit I think (as crusader has found, there is additional decryption when you quit the program


Quote:
Originally posted by Artifex
LBolt99 wrote :
"The big problem I am having at this point is that the program comes up to the main screen, loads the cache, etc, but immediantly exits."

Responsability for that may not be the dumping you made. One would have the same problem with the demo program if he refreshed the register entry date : program works but if one didn't empty the Temporary Internet Files it exits inmediatly. After cache loading it checks files dates, and exits if dates are greater than register entry date.

Lbolt99
June 27th, 2002, 04:31
AWesome, glad to hear you've had success in getting it to load up and run properly.. I'm looking forward to working on it, dead in the water right now cause I'm on vacation and away all the stuff I'm working on..

Reading back on older msgs in the thread, it looks like v4.0 was relatively easy to crack compared to v4.5+. Sounds to me like the encrypted code fragments very introduced in 4.5+?

Anyway, good luck on completeing the crack, sounds like you'll have it done before I even get started on it again

Lbolt99
July 3rd, 2002, 16:04
congrats on the completion of the crack Just got back from vac recently, so I've yet to get started on it again. But sounds like it can be wrapped up in about a half hour or so.

As far as the keygenning goes, I pretty much gave up on that aspect.. the bottom line is there is an obscured 64 bit number that is impossible to get (unless brute forced) without a valid name and serial. I have searched, searched and searched again and have come up with NOTHING as far as reg info. The only thing I've been able to find is stuff for v2.0, v2.03, etc

The 64 bit code it used for the DEFAULT user didn't work when I tried it in the registration algorithm. I haven't yet dug down deep enough to know why that's the case though. It might just be a simple additional check on the 30h bytes used as the decryption key.

I do remember the registration algo would to the 32 bit compare right at the end:

MOV EAX, [ESI]
NOT EAX
CMP EAX, [ESI+4]

single step after that part, and you'll come up to something like a:
CMP [EBP+58], 0

That checks for a zero in part of the generated decryption key! Might be the difference between the shareware key and the registered key.

Take care,