Kremlin 2.0: they learn, we learn
(Lesson for shareware-programmers: Don't place the protection scheme in a DLL)

by Jon

(24 December 1997, slightly edited by reverser+)

Courtesy of reverser's page of reverse engineering
Well, merry Xmas to anyone... since on Xmas everybody is nice, I sent an email to Mark Rosen (Author of Kremlin, a very nice guy, see his complete letter inside Jon's Blowfish essay) and I wrote to him:
>Your last protection cracked, may I publish?
and he answered immediately:
Sure. You can publish the crack, but please don't publish the cracked
DLL file; that way you have to have half a brain and be willing to do a
little work to get the regged version of Kremlin.

- Mark
So here you are with an essay about a very interesting cryptographical program (Kremlin) that you now know has been made by a nice programmer. I would say that the minimum we cand o for Mark Rosen is to send him a 'ready-made' +HCU's tough protection for his next version (I hope that our specialists +Rcg and +Sync are reading this :-)

This Kremlin-cracking seems to be a Jon's speciality.
Jon is our "encryption specialist" (as a matter of fact cryptography is -almost- more interesting than cracking itself). You may want to have a look at Jon's other essays: the one about kremlin version 1, and the one about Blowfish and you may want to read his Encryption, a short tutorial as well. With the present (fourth) essay Jon has done a good job indeed... judging for instance from this letter that appeared THIS MORNING on a maillist:

Subject: Kremlin v2.0 - Protection against wdasm?

Kremlin is one of my favourite encryption tools and i like to follow it
with regards to its cracking aspects. It has been the subject of a
couple of tutorials and the Author himself wrote a letter to reverser+ in
good faith. When i noticed the new version 2.0 was out i d/l it to see
if he had improved on the last version VERY bad protection. I was
slightly dissapointed to see that the first .dll file i targeted
(KremDLL.dll) housed the guts of the encryption scheme. after doing a
half crack on it so that it would accept any rego key and running the 
program successfully i got a strange window with something along the 
lines of "Some how you have enter the correct registration key without 
paying for Kremlin... (yadda yadda yadda)" this also triggered the 
program to cripple itself again. Although it still accepted psuedo-rego 

Without finding any referance to that particular window in KremDLL.dll
i tried to disassemble the main exe with wdasm and got a segment fault. 

Maybe he has learnt from the past after all?

And I received another message regarding this Kremlin protection scheme:
Kremlin 2.0 has definetely a better algorithm. Checks all the numbers
sequentially. Still 10 numbers, but does a iterative number check based
on integer division, first 4 kept constant, checking the values of the
others, for every check, if fails, clears edi... best Wishes.


magic number: 1111991167
Of course we await a short addition to this essay about this specifical anti-wdasm trick (which interests us more than the cracking of this simple protection scheme, btw). Anyway, as it seems, I could already fill a new section of my site about encryption using only the many good essays that Jon sent to the +HCU... ok, read and enjoy his last one now, and merry Xmas to anyone reading this!

Kremlin 2.0 - By Jon, on December 23, 1997.
Greetings, all! Intro: In this essay I will crack Kremlin 2.0. As some of you might know, I have already written an essay about an earlier version of this program, 1.1. In that essay I defeated a weak protection scheme, using ONLY the help-file, the Window$-registry editor, and about 1% of my brain. A couple of weeks later the author, Mark Rosen, emailed reverser+: "Hey. Nice reverse engineering page. I saw the thing on Kremlin... I'm the author of Kremlin! Oops! Well, I guess next time I'll spend more time on the protection scheme -- I concentrated on making a good program, not making a good protection scheme. Kremlin 2.0 will be really cool and will, now, have better security features and won't be as stupid. If the Jon guy who cracked the program wants a free copy, just tell him to e-mail and I'll give him one -- nice work." ~ Mark Rosen, Mach5 Software,, 30 September 1997 And indeed, he did spend (a little) time on the protection-scheme! And that's not all that's changed, Mr. Rosen has improved his program VERY much, with added Encryption-Texteditor, and an automatic encryption agent (like the System Agent, from M$Plus!). However the protection-scheme is still an easy crack. Although it does not tolerate the trick I used last time: "You have not registered but you have somehow selected a registered algorithm.", it's still fairly easy to crack. Honestly, I'd been disappointed if that trick still worked :-) Enough crap, let's crack! Tools needed: W32DASM 8.9 - There's no need for IDA here (BTW, I enjoyed a lot the full version!) A good hexeditor (I use HexWorkShop, use whatever you prefer) - To apply the patch. A string search utility (I use Search And Replace, use whatever you prefer) (I'll explain later why we need this ;-) About 5% of your brain! The crack: OK, we start by disassembling Kremlin Encrypt.exe with W32DASM. We find that at the near end of the disassembly, W32DASM freezes/crashes! Maybe Mark DID put some anti-disassembly tricks in! I don't know, but after viewing the text-strings of the executable, I find that we should not even be concentrating on this file anyway, so who cares :-( Let's try a slightly different approach: Drag & drop a file to Kremlin Encrypt... Enter a fake registration key, say +ORC's famous "1212121212" and you will immediately see this: "Invalid registration code". Of course, what did you expect? ;-) Now, start Search & Replace (a "grep" utility for Windows95 which is actually only "Search & Nag" in his crippleware version until you modify its functionalities, anyway 'search' is more than enough for this target). Search for "Invalid registration code" with file mask *.* inside the Kremlin directory. You find that the string is located in the KremDLL.dll file. OK, now we know that the protection scheme probably hides inside this DLL, so load it inside W32DASM... We start looking through the disassembly for suspicious code... BTW, when you need to change some bytes, see the status-line in order to get the hex-address and then just pass to your hexeditor... you wont even need to search any long hexstring ;-) The following is almost all we need: Exported fn(): IsRegisteredCode ;NOT a good idea to name a function like this... :05E10 56 push esi ;pass parameter :05E11 8B742408 mov esi, dword ptr [esp+08] :05E15 56 push esi ;pass passed parameter :05E16 E835FEFFFF call 10005C50 ;Call protection-scheme :05E1B 83C404 add esp, 00000004 ;correct stack :05E1E 85C0 test eax, eax ;Check if returned reg-code is valid :05E20 750F jne 10005E31 ;If not zero jump to good guy :05E22 56 push esi ;change the above jne to a jmp :05E23 E8A8FCFFFF call 10005AD0 :05E28 83C404 add esp, 00000004 :05E2B 85C0 test eax, eax ;second check :05E2D 7502 jne 10005E31 ;If not zero jump to good guy :05E2F 5E pop esi :05E30 C3 ret * Referenced by a Jump at Addresses:05E20(C), :05E2D(C) | :05E31 B801000000 mov eax, 1 ;We just changed the above code :05E36 5E pop esi ;to always jump here! :05E37 C3 ret ;in order to get flag 1 :05E38 90 nop ... :05E3F 90 nop Exported fn(): FixRegisteredAlg ;Almost selfexplaining. Fixes greyed algorithms! :05E40 83EC20 sub esp, 00000020 :05E43 B907000000 mov ecx, 00000007 :05E48 33C0 xor eax, eax :05E4A 57 push edi :05E4B 8D7C2404 lea edi, dword ptr [esp+04] :05E4F F3 repz :05E50 AB stosd :05E51 66AB stosw :05E53 683CBD0010 push 1000BD3C :05E58 8D442408 lea eax, dword ptr [esp+08] :05E5C 6A1E push 0000001E :05E5E 50 push eax * StringData Ref->"RegNum" ;Ha, ha! We don't need to change anything, though! | :05E5F 6848B30010 push 1000B348 :05E64 683CBD0010 push 1000BD3C * Reference To: KremDLL.GetGlobalString | :05E69 E832CEFFFF call 10002CA0 :05E6E 83C414 add esp, 00000014 :05E71 6AFF push FFFFFFFF * StringData Ref from Data Obj ->"Algorithm" | :05E73 686CB30010 push 1000B36C * StringData Ref from Data Obj ->"Encrypt" | :05E78 68F8B10010 push 1000B1F8 * Reference To: KremDLL.GetGlobalInt | :05E7D E8FECCFFFF call 10002B80 :05E82 83C40C add esp, 0000000C :05E85 50 push eax * Reference To: KremSDK.IsRegisteredAlgorithm, Ord:003Fh | :05E86 E863370000 Call 100095EE :05E8B 83C404 add esp, 00000004 :05E8E 85C0 test eax, eax :05E90 744D je 10005EDF :05E92 8D4C2404 lea ecx, dword ptr [esp+04] :05E96 51 push ecx :05E97 E8B4FDFFFF call 10005C50 ;Call protection scheme once more :05E9C 83C404 add esp, 00000004 :05E9F 85C0 test eax, eax :05EA1 753C jne 10005EDF ;Another check. Change to jmp . :05EA3 8D542404 lea edx, dword ptr [esp+04] ;to avoid the nag-text below :05EA7 52 push edx :05EA8 E823FCFFFF call 10005AD0 :05EAD 83C404 add esp, 00000004 :05EB0 85C0 test eax, eax :05EB2 752B jne 10005EDF :05EB4 8B442428 mov eax, dword ptr [esp+28] :05EB8 6A30 push 00000030 * StringData Ref from Data Obj ->"Kremlin" | :05EBA 6840B30010 push 1000B340 ;*NAG*! Bypassed by the change above! * StringData Ref from Data Obj ->"You have not registered but you " ->"have somehow selected a registered " ->"algorithm. You may not use Blowfish, " ->"IDEA, RC4, or Safer unless you " ->"have registered Kremlin. Please " ->"register." | :05EBF 6880B50010 push 1000B580 :05EC4 50 push eax OK, these two changes: 1. Fix the "greyed" algorithms, making them available. 2. Make sure that the nag about the "unselectable algorithms" doesn't show. But we need to take care of the *NAG* splashscreen, which still pops up on load! :0625A E841CAFFFF call 10002CA0 :0625F 8B74243C mov esi, dword ptr [esp+3C] :06263 83C414 add esp, 00000014 :06266 8935D8C10010 mov dword ptr [1000C1D8], esi :0626C 833E00 cmp dword ptr [esi], 00000000 :0626F 752C jne 1000629D :06271 8D4C2404 lea ecx, dword ptr [esp+04] :06275 51 push ecx :06276 E8D5F9FFFF call 10005C50 ;Call protection scheme 1 :0627B 83C404 add esp, 00000004 :0627E 85C0 test eax, eax :06280 7511 jne 10006293 :06282 8D542404 lea edx, dword ptr [esp+04] :06286 52 push edx :06287 E844F8FFFF call 10005AD0 ;Call protection scheme 2 :0628C 83C404 add esp, 00000004 :0628F 85C0 test eax, eax ;Check reg code :06291 740A je 1000629D ;Jump to *NAG*? Change to jne! * Referenced by a Jump at Address:06280(C) | :06293 B802000000 mov eax, 00000002 :06298 5E pop esi :06299 83C420 add esp, 00000020 :0629C C3 ret * Referenced by a Jump at Addresses:0626F(C), :06291(C) | :0629D 8B4604 mov eax, dword ptr [esi+04] ;Here starts the *NAG* :062A0 8B0D30BD0010 mov ecx, dword ptr [1000BD30] :062A6 6A00 push 00000000 :062A8 68F05E0010 push 10005EF0 :062AD 50 push eax * Reference to Dialog: DialogID_0081 ;The dialog-box (found at disassembly start) | :062AE 6881000000 push 00000081 :062B3 51 push ecx * Reference To: USER32.DialogBoxParamA, Ord:008Eh | :062B4 FF1568D20010 Call dword ptr [1000D268] :062BA 5E pop esi :062BB 83C420 add esp, 00000020 :062BE C3 ret :062BF 90 nop :062C0 8B442408 mov eax, dword ptr [esp+08] :062C4 81EC04020000 sub esp, 00000204 :062CA 83E853 sub eax, 00000053 :062CD 53 push ebx :062CE 55 push ebp :062CF 56 push esi :062D0 57 push edi :062D1 0F84BE020000 je 10006595 :062D7 2DBD000000 sub eax, 000000BD :062DC 0F8412020000 je 100064F4 :062E2 48 dec eax :062E3 740F je 100062F4 :062E5 33C0 xor eax, eax :062E7 5F pop edi :062E8 5E pop esi :062E9 5D pop ebp :062EA 5B pop ebx :062EB 81C404020000 add esp, 00000204 :062F1 C21000 ret 0010 Yeah! We're done! Our target now runs beautifully, without even having to enter any registration code! No nag, and all algorithms are available! And since it's in a DLL we don't need to apply patches to all the program files! Lessons for shareware-programmers: Don't place the protection scheme in a DLL, as two things could happen: 1. The DLL will be reversed and altered, making the program(s) believe that everything is OK! Any anti-disassembler protection inside the program wont make any sense! 2. The program is reversed and altered, completely bypassing the DLL check! Even more important (how long will we have to repeat it? For goddamn sake! Don't make your functions so obvious! With names like "IsRegisteredAlgorithm", "RegNum", "IsRegisteredCode" and "FixRegisteredAlg", anybody can figure out what's going on! Make the names cryptic and hard-to-guess! Well, that's it! I hope you enjoyed reading this! Greetings fly out to: All +crackers, The +HCU, +ORC and everybody reading this! Jon Email me your comments (good or bad) to Don't spam or email-bomb me; it's a remailer, which I can easily disable!

Well, just editing in a hurry this essay, two immediate questions, still unanswered, spring out of the text:
First: why two different protection calls? The one at :06276 E8D5F9FFFF (call 10005C50 - Call protection scheme 1) and the 'second' one at :06287 E844F8FFFF (call 10005AD0 - Call protection scheme 2)?
Second How does the main exe blow wdasm?
Hope somebody will send an addendum to Jon's essay asap (I haven't the time, I didn't even download Kremlin 2... I'm working -again- on Screen ruler :-)

(c) Jon (+HCU's encryption specialist) All rights reversed
You are deep inside reverser's page of reverse engineering, choose your way out:

redhomepage redlinks redanonymity +ORC redstudents' essays redacademy database
redtools redcocktails redantismut CGI-scripts redsearch_forms redmail_fravia
redIs reverse engineering legal?