CacheX program and keygen analysis.
Disassembled keygen (eclipse) and also registration routine in CacheX opera version.
5) NOTE: As of this point, the Eclipse keygen and the program’s internal routine have done the same thing.
5a) the KEYGEN at this point calls blowfish again, with data that is preinitalized at the start of the keygen: 85 09 1E 93 91 9D FD 74. After blowfish is done, it results in the correct S/N to enter into CacheX opera. The keygen is finished.
8) OK. Whew. This part seems to be a large constant operation, in general. I’ve commented it in one of the attached documents, but all in all I believe it generates the same info every time regardless of name/Serial#.
b. Blowfish crap all over again (xor subkey table w/30h data read in), 0x12 iteration , 0x200 iteration, p1 thru p18 swap).
e. Final Check: 1st 8 bytes of the 30h data. Read bytes 5-8, NOT them, compare with bytes 1-4. if same, exit. They will be the same on the 2nd iteration of Step #15, if your code is correct.
OK, now that it’s all in a nutshell, I have a bad feeling that there is no way to keygen CacheX unless you have a valid code, in order to find out the CONSTANT: 85 09 1E 93 91 9D FD 74. This constant is different between the different cachex’s: IE/netscape and Opera. The subkey tables in the three version are the same, for what it’s worth. Since the constant is unknown, and there doesn’t seem to be any way to figure it out from working backwards in part 3. Is my analysis correct?
So eclipse must have had a valid serial in order to figure out the obscured constant?
In the end, then, the check is against a 32-bit number? It looks as though you could bruteforce the whole process, though you'd probably need to distribute it. How long does it take to run through a single check of the name/SN?
is reached, then it kicks out and sets the unregistered flag.
What debugger did you use? SI doesn't give very good timing for very short bits of code. Perhaps you could go in and alter the code in memory so it tries a test 100000 times and then check the time between breakpoints.
Assuming it takes 50 ms = 1/20 s per test, then it will take ~6 P266-years to "force brutally"
I bet it runs much faster than that, though.
Basically, regardless of what name/serial number is entered, if it is a correct combination, it ALWAYS results in the same "constant" discussed before.
Since we only need to find out this constant, Part I can be canned, as well as Part II. All part II really does is decrypt Part III (the code that runs at the CALL ESI).
Part III runs the hash on the constant, XOR's hash w/P-table, does all the blowfish crap, etc.
I'll give your suggestion a shot tomorrow and see how long it takes on just part 3 @ several hundred thousand iterations.. in fact, might even replicate the process in C++, but that'd have to wait until the weekend.. no time now..
This got me wondering how the author managed to get two 32 bit numbers next to each other, one the inverse of the other, after all this blowfishing and everything.. could there possibly be several different constants, other than those the author "picked" which would somehow result in it passing the final check? I guess I'll have to take a closer look at the data passed in Step 15-c.. maybe that holds a clue.
could there possibly be several different constants, other than those the author "picked" which would somehow result in it passing the final check?
Yes, absolutely. The constant is 8 bytes, while the check is only 4 bytes, so there are 2^32 constants that would work. It would take about 4 billion times longer to try to find a S/N that matches the original 8-byte constant.
BTW, the check might seem to be 8 bytes, but for *any* first four bytes, there's a valid last four bytes. So the check is really only 32 bits. The "NOT" op is irrelevant.
Thanks for the ideas. I've done a little more analysis on exactly what is going on in the CALL ESI routine. As stated before, regardless of name/code, it will always arrive at the same (unknown) constant.
So now the hash is "meshed" into the blowfish table.
Now he's got his highly modified blowfish 0x1048 byte long table set up.
He picks out 0x30 bytes of random data, ensuring that the 2nd set of 4 bytes are the inverse of the 1st set of 4 bytes.
Stores it in the exe file.
Now, when the program is run, with a correct serial, it will arrive at the correct 8 byte constant, do steps 1-3, in addition to a P1 thru p18 reverse..
Pulls the data from the exe (30 bytes), and after all the looping, arrives "back at" the original 30 bytes of random data he picked out.
I would have to brute-force 48 bits and "emulate" all these checks.. (I originall thought it was a 64 bit constant, but the program discards the first 16 bits for whatever reason). I verified this by overwriting them after the registeration number was blowfished into the constant.
Anyway hope all this makes sense How realistic is it to Bruteforce 48 bits?
I found the app simply crashed.
Armadillo. Some time ago I reversed an Armadillo protected app.
Message and I may also give you my bruteforcer source.
Hi, thanks for the info. I reset CacheX into trial mode, and took a look at what happens. I took the constant produced but unfortunately it doesn't look like it works with the "registered-mode" decryption routine. The routines look the same but are different and in different locations of the program.
They must use a different algo and key for decrypting the data between the unreg and reg versions. I think that's why the constant arrived at when running in trial mode doesn't work. Basically, I took the constant and planted it into the Eclipse CXOE keygen. Didn't work.
The upside is that it would reveal the CONSTANT, allowing the keygen to be complete.
the 32 bit comparison to check out. Search thru ONLY those values, looking for a 48 bit number that will generate the CORRECT 0x30 bytes for the decryption..
Hi, Lbolt99 and all fellows.
As we don't know the proper 64-bit constant for Cxie, couldn't we try to use the Opera constant and get our Cxie decrypting process to think that we are using Opera.
1. Would we have to modify many things in Cxie decrypting routine ? It seems that a lot is shared between versions. First step could be to get correct decrypting in live, as we can't patch the prog without altering the process.
2. Could you explain what would we have to dump and paste to restore the decrypting process if we patch the prog ?
(As far as cryptology is concern I am still in the Enigma times).
I will enter in "Unlock" name "DEFAULT" and SN = 3482-bc11-c786-e749, and will watch why first check is false and second is true.
Note that it continues iterating, about 5 or so more times, reading in different chunks of 30h bytes to "decrypt" into the decryption key used to decrypt the stuff in other parts of the program.
It somehow comes up with a different (default) 64 bit number for the second call into 69FAF5, which allows it to pass the "final check".
In retrospect, it might be a quicker crack to paste in the blowfish subkey table, and let it do it's work, instead of dumping/pasting each section.. I'm going to give that a shot to see if it'll work..
"In retrospect, it might be a quicker crack to paste in the blowfish subkey table, and let it do it's work, instead of dumping/pasting each section.. I'm going to give that a shot to see if it'll work.."
I also feel that it is worthwhile.
I'm going to give this a shot sometime today or tomorrow -- hopefully this will be much quicker, with dumping each part it got more and more to the point of not being worth it.. if dumping and pasting the blowfish table instead is better, I'll document the method and everything..
wow, what a great thread, I learned quite a bit by watching!
Hi, Lbolt99, UrgeOverKill and all fellows.
P and S-box tables dumping and patching seems to works.
:0043ec81 call 0043eed8 (startup window display).
In there prog crashes (at :0043efdf call 00401f4c) because it calls an address in edxxxx that had not been correctly decrypted.
and I loaded them just before the call to 00440bf4.
Startup window popped up, and prog exited without crashing.
Address to dump or paste is the last push before the call 440bf4.
Each function requires to load different tables.
So this method is worse than the other.
Is it possible that CacheX is using a method similar to "Shamir's secret sharing" scheme?