How to crack, an approach
LESSON 1
How to crack, tools and tricks of the trade
LESSON 2
How to crack, hands on, paper protections LESSON
3.1
3.2
How to crack, hands on, time limits LESSON
4.1
4.2
How to crack, hands on, disk-CDrom access
LESSON 5
How to crack, funny tricks
LESSON 6
How to crack, intuition and luck LESSON 7
How to crack windows, an approach LESSON
8.1
8.2
How to crack windows, tools of the trade LESSON
9.1
9.2
9.3
9.4
How to crack, advanced cracking
LESSON A
How to crack, zen-cracking LESSON B
How to crack, cracking as an art LESSON
C.1
C.2
C.3
How to crack INDEX
Lesson 9 (4): How to crack Windows, Hands on 'Dead listing' approach - second part First of all I'll give you a fundamental advice: don't stroll too much inside the dark codewoods without taking a due amount of notes: our paths are narrow, and wind in and out among codetrunks. Everything may seem 'obvious' to you when you are continuously cracking a given target, but after a break, or having cracked something else, you'll notice, as soon as you begin working anew on the original target, that many 'obvious' things are not so evident any more, and that you'll probably have to follow once more quite a lot of previous steps. Therefore heed my advice! NEVER WORK without taking notes, and never leave a crack without 'assembling' these notes in a short review where you'll synthesize 1) the paths you have followed in order to find the protection scheme, 2) a short description of the protection scheme itself and/or 3) the eventual new tricks you'll have found. Beginning with this lesson we will slowly drift towards 'higher' cracking, i.e., simply put, beginning from now I will give as acquired the minimum skills and knowledge you do need in order to crack (at least at this elementary level). Should you not feel able to follow a lesson, just re-read the 'basic' ones and practices on those lines until you do. To day we'll work on WEBEXPRESS, an 'html page designer' program whose 'triple' protection scheme (nagscreens and time protection and disabled functions) has some interest for us. I am using here version 1.0 of Webexpress for Win 3.1 by Microvision Development (at http://www.mvd.com). There is now a new beta version 2.0 out, but I reckon more useful to crack the older 16 bit Windows 3.1 application (august 1996) because this crack can be followed both by Windows 95 and by Windows 3.1 users (which -notwithstanding Microsoft's efforts- are still the majority). Besides, the Windows95 version's protection scheme and the beta one seem both to be more or less the same: you should be able to apply the following approaches, cracking the newer versions, without many problems (I did'nt check very thoroughly, though). I am using version 1.0 of Webexpress, with following files: WEBEX.EXE 1.309.200 12 august 1996 Main program WEBEX.DWR 120.885 12 august 1996 ASCII & resources (As usual you'll be able to fetch the whole application on the Web searching the archies). First of all let's fire Webexpress snapping the nagscreens (use snap32, cracked elsewhere in my tutorial, or PaintShopPro, cracked elsewhere in my tutorial, in order to get the printed snaps). This gives us a rough idea of our target's protection schema: This application is 1) 4 TIMES NAGSCREENED 1) Evaluation copy 'smallscreen' at the beginning 2) Evaluation copy Webexpress is NOT Freeware. This copy... 3) Evaluation copy 'smallscreen' at the end 4) To register Webexpress, enter your registration name... 2) TIME-LIMITED (30 days) 3) CRIPPLED (Prints 'Printed with an evaluation copy...' after 30 days). Gosh, quite a lot of annoyances... that's NICE for us little crackers! (That's actually the real reason I have chosen this crap). There is obviously a lot to learn for us inside its protection scheme... wipe your hands, prepare your cocktail (may I suggest a good Martini-Wodka? Remember: put in your glass always the ice cubes first, then the Martini dry and then the Moskowskaja)... at work! We proceed first with a little reverse engineering, using our 'dead listing' approach (see lesson - 9.3) and loading Webex.exe inside W32dasm in order to get the disassembled listing of the program. A word of caution: I am using only for teaching purposes version 5 of W32dasm, because this is the disassembler that the masses will use (watch carefully the file lengths after you searched w32dasm through the archies, before ftpmailing it, else you'll fish only the shareware and incomplete versions of it) but I originally used WCB, a much older, DOS based, Windozes disassembler, which has, as you will see, some advantages vis-a- vis of W32dasm. Remember that you DO NOT NEED to run windows in order to crack windows programs... cracking has not much to do with a particular OS... since you learn (here) how to 'interact' with an application at a 'fundamental', machine language, level, you'll be ALWAYS able to apply 'DOS cracks' or 'Windows cracks' or 'Unix cracks' to whatever OS the idiots will fancy in 5 years time... you are learning a technique that will NEVER BE OBSOLETE, believe me. Well firing w32dasm (which, I insist, is not a very good disassembler) you'll be able to save the webex.alf listing (which is 16 million bytes long, BTW, a real tribute to the 'overbloatility' of C++ in general and Windows programming in particular). Now load this *.alf inside a wordprocessor (you would be well advised to use a fast and good wordprocessor, i.e. not Microsoft's one, when you deal with such monstrosities, once more there is no reason to work inside Windoze). Ok, let's start with the cracking! Alas! Searching our nagging ASCII strings inside the listing, we do NOT find any trace of the two main nagscreens of Webexpress (Evaluation copy... & To register Webexpress...). These ASCII data are indeed NOT in the main *.exe module, but inside WEBEX.DWR, a file containing the resources for Webex (which seems compiled with Borland C++ 4,5 btw). What now? Should we switch to Winice in order to find our protection scheme then? Has our dead listing approach failed? Well... let's examine a little more our listings... let's forget the ASCII strings -for the moment- and let's start with the easiest possible search in such cases: Since the limit of allowed days is 30 (which corresponds to 1Ex, duh) we could/should have somewhere an instruction like (we are here in a 16 bit application, not 32 one) mov ax,001E (B81E00)... would not we? Well, er... yes, quite. If you think this string of bytes is TOO SHORT and that you'll find much too many mov ax,001E inside a 1309200 bytes long file you are dead right... we would indeed find quite a lot of occurrences where 1E does not represent the 30 days limit at all, but only a parameter for a subsequent call:... let's conclude by saying that with overbloated programs -i.e. all Windows programs- there is no point in searching 'too short' shortcuts. Our search for 'mov ax, 001E'... would fail for sure... But wait! Couldn't we narrow the search a little more? Yes, hey, we can! But we'll need both a little experience and a little feeling: You see: the normal code for such a protection inside Borland C++ would consist in a COUPLE of instructions: E81E00 mov ax,001E 2B06xxxx sub ax,[gone_days] and since the code for 'sub ax,[whatever]' is 2B06xxxx, we now have a more 'robust' sequence of bytes for our search: E8 1E 00 2B 06 Obviously we CANNOT search two consecutive instructions inside our disassembled listing using our wordprocessor search facilities, we will therefore have to search the above sequence inside Hexworkshop (a fairly good hexeditor that we cracked with - lesson 9.3 if you are using windoze, but you could anytime use old good (and powerful) PSEDIT). Let's do it... ahh! Things look muuuch better: splendid! There is only a single occurrence, at bytes 84565-84569 of our hexfile. Ok, done. Struck and destroyed. It's easy now to fetch this part of the code from our disassembled listing (we'll obviously have to translate the address 84565-84569 using the tables at the beginning of our Wdasm disassembly: here the relevant part: ... CSEG053 Off:83400 Size:1FFC Flags:0x1D10-CODE,MOVEABLE ; *53* ... and since 84565-83400 gives us 1165 bytes, the same address inside our listing will be :0053.1165... here it is! :THE_BINGO_QUICK_CRACK :0053.1162 8956EA mov [bp-16], dx :0053.1165 B81E00 mov ax, 001E ;load 30 *** BINGO! :0053.1168 2B066A46 sub ax, [466A] ;subtract gone_days :0053.116C 50 push ax Well, this shows us immediately the importance of location [466A], which is the memory location where the day_counter "grows". OK, bingo! This search has worked here without flaw or error... nevertheless beware! The abovementioned 'zen' method is NOT correct, coz it would in many cases NOT work (even if it actually worked here). Much too many protection schemes would have either a) a different (masked or concealed) initial value for ax instead of the exact one (here 1E): The protectionists could have a 'mov ax, 1F' (which is 31) and a 'dec ax' following it (which gives back our 30 days limit), or a zillion other possibilities in order to 'conceal' (more or less slightly :=) the purposes of the main comparison inside the code; b) another, completely different, assembler construction... say different instructions instead of sub ax,[gone_days], or c) junk between 'real' instructions (see elsewhere in my tutorial the 'junking' techniques for protection schemes). Therefore the abovementioned approach (unless you 'feel' the code) could make you waste too much time and would often miss the mustard... even if, interestingly enough, we ARE as a matter of fact landed smack in the middle of our protection using the simple trick above... but since you are here to learn the solid basic ways of cracking first (and you are not yet ready to feel the code, even if I believe you will, once you understand my 'zen' lessons at the end of this tutorial) here is a more 'sound' approach to this sort of cracking: Looking at all the many data strings inside Webex.exe, as said above, we have NOT found the text of the nagscreens (which is located inside the resource file Webex.dwr), but we can nevertheless find ONE very interesting stringdata reference (did they forgot it?)... just have a look at the "string data references" inside W32dasm once you load webex.exe... HERE!: "Printed with an evaluation copy" Ahha! Protectionist's squalor... how awful! This is a nagstring that should be WRITTEN inside any text printed with our copy of the application, should a user deem necessary to use it for more than the allowed 30 days... you remember our PaintShopPro cracking (- lessons 9.2 and 9.3) don't you? PaintShop had a counter as well, but there was no 'punishment' should you heedlessly 'overuse' the program. These 'MicroVision development' guys have purposely added a protection which cripples the program if you do not register it after 30 days! Buu! Buu! Now please examine code segment 109.1A06... (using W32dasm) there you'll find a whole series of code protection strings. Let's now have a look at the part of the code that pushes "Printed with an evaluation copy", it's segment 82... as you will see, even coming from this direction we land immediately inside the protection scheme. As I said elsewhere... protection schemes inside the code of an application are like tarantulas on a wedding suit, it's impossible not to see them from pretty far away. :COMPARE_VALUES_ADD_FB_AND_PRINT_NAGSTRING... NAGSTRING_ROUTINE :82.0B5F 8CD0 mov ax, ss ;start of routine :82.0B61 90 nop :82.0B62 45 inc bp :82.0B63 55 push bp :82.0B64 8BEC mov bp, sp :82.0B66 1E push ds :82.0B67 8ED8 mov ds, ax :82.0B69 B8D400 mov ax, D4 ;parameter D4 for the next :82.0B6C 9AFFFF0000 call 0001.517Fh ;(and only) ubiquitous call :82.0B71 8C5EFC mov [bp-04], ds :82.0B74 C746FAC319 mov word ptr [bp-06], 19C3 ;fix XX start :82.0B79 8D468E lea ax, [bp-72] ;ax = [bp-72] :82.0B7C 8C56F4 mov [bp-0C], ss ;save ss :82.0B7F 8946F2 mov [bp-0E], ax ;[bp-0E] = [bp-72] :82.0B82 EB14 jmp 0B98 ;begin loop :82.0B84 C45EFA les bx, [bp-06] ;loop from B9F,begin=[19C3] :82.0B87 268A07 mov al , es:[bx] ;load in al es:[19C3](XX) :82.0B8A 04FB add al, FB ;add FB :82.0B8C C45EF2 les bx, [bp-0E] ;load [bp-72] in bx :82.0B8F 268807 mov es:[bx], al ;save XXX at es:[bp-72] :82.0B92 FF46FA inc word ptr [bp06] ;next value loc gets+FB :82.0B95 FF46F2 inc word ptr [bp0E] ;next save location :82.0B98 C45EFA les bx, [bp-06] ;we begin/began at19C3 :82.0B9B 26803F00 cmp byte ptr es:[bx], 0 ;are we done? :82.0B9F 75E3 jne 0B84 ;not yet, so loop up :82.0BA1 C45EF2 es bx, [bp-0E] :82.0BA4 26C60700 mov byte ptr es:[bx], 00 :82.0BA8 16 push ss :82.0BA9 8D468E lea ax, [bp-72] ;prepare for the call :82.0BAC 50 push ax ;passing all... :82.0BAD 1E push ds ;...these params... * StringData Ref from Data Seg 109 -Printed with EvaluationCopy | :82.0BAE 68061A push 1A06 ;push and be betrayed :82.0BB1 9AFFFF0000 call USER.LSTRCMP ;AhHa! A very interesting block of code! You can easily see that here we have a reference to an obvious protection and at the end we have a call to USER.LSTRCMP, which is a case sensitive comparison of two null terminated strings, wildly used by windows protectionists (sic!). As 'usual' (you remember our crack of Hexworkshop in - lesson 9.2, don't you?) we must search the 'caller' of this block of code, i.e., where, inside webex.exe, dwells one of the following calling strings Either call 0B5F or jmp, je, jz... you name it, 0B5F or call 0082.0B5F Since the only common denominator of the above strings is a '0B5F' inside them, let's search first of all for 0B5F occurrences inside our 'protection' segment 82 (we should look further for the eventual call 0082.0B5F inside the other segments only if we do not fetch anything inside 82). And look! We land, almost immediately (remember that protection routines are most of the time 'compacted' inside one -or at most two- segments of wincode): :BE_NAGGED_INFIDEL :0082.0C8F 90 nop :0082.0C90 0E push cs ;prepare for call :0082.0C91 E86202 call 0EF6 ;call DECIDING_ROUTINE and... :0082.0C94 0BC0 or ax, ax ;...check flag ax. IS it 0? :0082.0C96 7506 jne 0C9E ;call compare if ax=1 :0082.0C98 B80100 mov ax, 1 ;AX now 1 if it was zero... :0082.0C9B E9EE01 jmp 0E8C ;...and do NOT call NAGSTRING :compare_howbadareyou :0082.0C9E 833E6E4602 cmp word ptr [466E], 2 ;is it 2? :0082.0CA3 7D02 jge 0CA7 ;[466E] = 2 call NAGSTRING! :0082.0CA5 EBF1 jmp 0C98 ;[466E] 10? :82.07EE 7E08 jle 07F8 ;if yes, Jesus, :82.07F0 C7066E460300 mov word ptr [466E], 3 ;flag 3=VERY BAD :82.07F6 EB15 jmp popout :82.07F8 833E684605 cmp word ptr [4668], 5 ;is 4668 10? :82.0814 7E1E jle 0834 ;yes, then... :82.0816 6A00 push 0 ;...let's... :82.0818 1E push ds ;...prepare * StringData Ref from Data Seg 109 -"CODE" | :82.0819 686D19 push 196D ;...and :82.081C 1E push ds ;...then * StringData Ref from Data Seg 109 -"WB_10" | :82.081D 685119 push 1951 :82.0820 9AFFFF0000 call 0069.09F4h ;...fire this routine :82.0825 83C40A add sp, 000A :82.0828 0BC0 or ax, ax ;and if not zero... :82.082A 7508 jne 0834 ;...then check can use :82.082C C7066E460300 mov word ptr [466E], 3 ;flag=3=VERY BAD :82.0832 EB15 jmp popout :OK_4668_IS_MORE_THAN_10_THEREFORE_CAN_USE_OR_ALMOST: :82.0834 833E6A460A cmp word ptr [466A], A ;is [466A] 10? :82.0839 7E08 jle 0843 ;can use if [466A] = 4.1-4.4: protection schemes based on time), this is done in a very rich number of ways, a double counter being one of the most common. OK, let's resume our findings: 1) We found our good old location [466A] compared to 1E (i.e. 30), which is very interesting to say the least. 2) We know now the meaning of location [466E], which may be either: 3=VERY BAD, DISABLING, or 2=TIME IS OVER or 1=TIME IS ALMOST OVER or 0=OK GO ON USING OUR CRAP So we'll 'name' this [466E] HOWBADAREYOU. Since we know that its value depends on the TWO parameters in [466A] and [4668], let's search for them. If we start with [466A] We land immediately to our 'first' block of code (the one found at the beginning of this lesson, the one inside segment 53, which seems to be an 'initialisation' segment): :FIRST_NEW_OCCURRENCE_OF_gone_days :0053.1162 8956EA mov [bp-16], dx :0053.1165 B81E00 mov ax, 001E ;load 30 **** :0053.1168 2B066A46 sub ax, [466A] ;subtract gone_days :0053.116C 50 push ax And we'll therefore 'name' [466A] GONEDAYS Let's do our first 'HANDS ON' checking. Pick up WEBEXP.EXE with hexworkshop (we cracked it in lesson - 9.3) and substitute (for instance) :0053.1165 B81E00 mov ax, 001E with :0053.1165 B81E1E mov ax, 1E1E This should allow for more than 21 years of undisturbed use of this program (1E1E=7710 days) and if we run the program now we'll see that the 'Evaluation days remaining' of the nagscreen are indeed 7710. This crack will not work (alone), though, because there are, as we saw, other 'crosschecking' locations in play. Let's therefore gather a little more facts about these locations inside our code. :ANOTHER_OCCURRENCE_OF_[466A]_gone_days :0082.074E E843FC call 0394 ;SHELL calls :0082.0751 83C406 add sp, 0006 :0082.0754 A36846 mov [4668], ax ;UPDATE [4668] :0082.0757 6A03 push 0003 :0082.0759 6A00 push 0000 :0082.075B 6A00 push 0000 :0082.075D 0E push cs :0082.075E E833FC call 0394 ;SHELL calls :0082.0761 83C406 add sp, 0006 :0082.0764 A36C46 mov [466C], ax ;save ax here :0082.0767 8B46FA mov ax, [bp-06] ;get param :0082.076A 2B066046 sub ax, [4660] ;sub ax with [4660] :0082.076E A36A46 mov [466A_GONEDAYS], ax ;UPDATE GONEDAYS! :0082.0771 8B46FC mov ax, [bp-04] :0082.0774 8B56FA mov dx, [bp-06] :0082.0777 3B066646 cmp ax, [4666] :0082.077B 7506 jne 0783 :0082.077D 3B166446 cmp dx, [4664] :0082.0781 742F je 07B2 :0082.0783 FF066846 inc word ptr [4668] ;INCREASE [4668]!! ****************** THE WHAT_THE_CUCKOO_PROBLEM *************** We better -first of all- have a closer look at this 'double' call 394 for learning purposes, coz here hides a very common 'mistake' of Wdasm: a problem that you may not be aware of: DISASSEMBLER OFTEN MISS THE BEGINNING OF THE ROUTINES. Look! Our listing does not seem to report any :0082.0394 routine at all! :WHAT_THE_CUCKOO?_NO_ROUTINE_AT_82.0394? :0082.038A 91 xchg ax,cx :0082.038B 029B02AF add bl , [bp+di-50FE] :0082.038F 02A502D2 add ah, [di-2DFE] :0082.0393 028CD090 add cl , [si-6F30] :0082.0397 45 inc bp :0082.0398 55 push bp ... But since missing the start of routines is a 'routinely' mistake for all disassemblers we can repair 'by hand' this piece of code, which in reality should read, once you rearrange the same bytes: :EVERYTHING_OK_AT_394 82.0394 8CD0 mov ax, ss 82.0396 90 nop 82.0397 45 inc bp 82.0398 55 push bp 82.0399 8BEC mov bp, sp 82.039B 1E push ds The above listing comes from WCB, which is a much older disassembler than W32dasm, but which DOES NOT miss the beginning of the routines. ... For now, just remember -always- that 8CD090 is a common start for routines and that you should -never- completely trust your disassembler (or you debugger, or anybody for that matter) Work always cum grano salis! ****************************************************** What IS interesting in the ANOTHER_OCCURRENCE routine above is that we have our GONEDAYS correlated to an increase of [4668], a parameter whose meaning we do not yet know. Let's also notice that location [4660] is a 'gone days' basher, i.e. a location that 'remembers' how much must be 'diminished' from GONEDAYS, let's call it [4660_BASHER]. And now we would search for these locations and so on and so on, sinking deeper and deeper in our shadowy codewoods, always (well, almost always :=) knowing what we are doing. We could continue like this in order to completely reverse engineering this application. But all these paths have been showed for your 'homework', and you should -obviously- use the help of Winice for such examinations. I wanted with all this cracking WITHOUT Winice (once more) just show you the untarnished POWER of the dead listing approach. Now let's go on to the real crack, which we'll do still only looking at our listings, without even a glimpse at Winice (no debugger in my hands, ladies and gentlemen! Only three or four sheets of printed paper). As we saw before, clearly the protection scheme acts inside the call to 0EF6 at the beginning of the BE_NAGGED_INFIDEL? routine... what happens to our beloved flag ax, then, inside the 82.OEF6 'deciding' routine? Routines inside routines... like the Russian Mathrioskas dolls... this kind of fishing is part of the sublime art of reverse engineering a program, a sport that requires some feeling, some luck and some experience. Let's have a close look at this routine. :DECIDING_IF_BE_NAGGED_INFIDEL... DECIDING_ROUTINE! :0082.0EF6 8CD0 mov ax, ss :0082.0EF8 90 nop :0082.0EF9 45 inc bp :0082.0EFA 55 push bp :0082.0EFB 8BEC mov bp, sp :0082.0EFD 1E push ds :0082.0EFE 8ED8 mov ds, ax :0082.0F00 33C0 xor ax, ax :0082.0F02 9AFFFF0000 call 0001.517Fh ;call ubiquitous :0082.0F07 A19846 mov ax, [4698] ;HERE!!*** :0082.0F0A EB00 jmp 0F0C ;therefore :0082.0F0C 1F pop ds ;everything :0082.0F0D 5D pop bp ;depends :0082.0F0E 4D dec bp ;from location :0082.0F0F CB retf ;[4698]! Here we call once more this ubiquitous 1.517Fh routine, which -being at segment one- is probably one of the main display routines... we do not have necessarily to care... let's just check that 1.517F does not modify our TREASURE, i.e. location [4698], which is the location moved in AX. How will we check it? It's easy: just search for [4698] inside the listing... Whoa! No problem! The first occurrence of [4698] found is already inside our 'protection segment' 82... and it's a most interesting piece of code indeed from our cracking perspective... :82.01FB 9AFFFF0000 call USER.LSTRCMPI ;call LSTRCMPI :82.0200 0BC0 or ax, ax ;same strings? :82.0202 750B jne 020F ;no, so go flag1 :82.0204 C70698460000 mov word ptr [4698], 0 ;flag0=samestrings :82.020A B80100 mov ax, 1 ;ax = 1 :82.020D EB0A jmp 0219 ;continue :82.020F C70698460100 mov word ptr [4698], 1 ;flag1=stringsdiffer :82.0215 33C0 xor ax, ax ;ax = zero :82.0217 EBF4 jmp 020D ;goto continue I assume you all know that the function int lstrcmpi (LPCSTR lpszStr1, LPCSTR lpszStr2) makes a non case sensitive comparison of two null terminated strings... a zero return value indicates that the two strings where identical. A negative value means that string1 < string2 and a positive one means that string1 > string2. OK, it's MADE! The above piece of code represents obviously the final comparison between the user input and the registration key (what else?). THEREFORE the crack can be made with a very simple modification of the DECIDING ROUTINE... we must ensure that location [4698] is always flagged TRUE (i.e. zero) and therefore we modify :0082.0F07 A19846 mov ax, [4698] with :0082.0F07 B80000 mov ax, 0 That's all we need to crack completely this program. No more nagscreens, (all three fetch the value of 4698 with a call to the same routine 82.EF6, all three will not snap any more now) should we really use this program, and we have made the first steps towards higher cracking. A word about it: higher cracking is something more than just defeating a protection, it's understanding what's going on in ANY part of a program we may wish to modify. Say you hate (just kidding) Microsoft enough to distribute cracked copies of their (awful slow) proggies where there is NO Microsoft logo whatsoever, or that you fancy a pink wordprocessor... go ahead and crack all the applications you use! And then distribute everything on the web for free! BTW, you should NOT believe that the two approaches I have shown you ('live' cracking through Winice, i.e. examining the protection scheme when it snaps, and the examining of the 'dead' listing as we are doing here) are the only methods to crack such protection... many more possibilities are open... just to give you an example, the (very old) utilities that show the 'imported' API functions of a program from its *.DLL and from KERNEL, USER and SHELL are a formidable cracking tool for windows programs... if you for instance search for KEYBOARD, you'll find the following occurrences... 59.1354 9AFFFF0000 call KEYBOARD.ANSITOOEM 79.1F7A 9AFFFF0000 call KEYBOARD.OEMTOANSI 79.1FCB 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.13DA 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.1550 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.1588 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.1599 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.15D7 9AFFFF0000 call KEYBOARD.ANSITOOEM 82.1629 9AFFFF0000 call KEYBOARD.OEMTOANSI 82.16D5 9AFFFF0000 call KEYBOARD.OEMTOANSI 83.063A 9AFFFF0000 call KEYBOARD.ANSITOOEM 83.06B2 9AFFFF0000 call KEYBOARD.OEMTOANSI 102.0721 9AFFFF0000 call KEYBOARD.ANSITOOEMBUFF 102.074C 9AFFFF0000 call KEYBOARD.OEMTOANSIBUFF ...and even lower beings would notice that segment 82 has SEVEN occurrences of KEYBOARD out of 14 and would smell a rat... KEYBOARD.DRV is a windows device driver, i.e. a DLL with another name, which is extensively used by the USER module. I hope you will not ask for the 'meaning' of the various KEYBOARD functions... you should know them by heart! Suffice to say that all ANSI APIs have MUCH to do with protection schemes, and than therefore the calls to KEYBOARD 5,6,134 and 135 are INDEED important from our point of view. Applications use the AnsiToOem(const char_huge* hpszWinString, const char_huge* hpszOEMString) function to convert a string stored in the windows character set into one stored in the specified OEM character set (in WinNT/32 there is a macro that calls the CharToOem() function)... As a matter of fact the USER.LSTRCMPI API from 82.01FB uses -in our case- these Keyboard functions. Are we finished with 'alternative' cracking approaches? Nooo! There are zillion cracking ways... say you use WRT (WIndows Resources Toolkit, a BEAUTIFUL Borland utility which is of UTMOST interest in our trade)... there you'll immediately find out that the Menu option 'Register' corresponds to 164. Decimal 164 is A4h... have a search for it... you'll land to 82.1575! As you have seen, we could have located the protection segment of our target using a completely different approach... but let's go back to our VERY POWERFUL dead listing... just a moment! A cool breeze outside my windows... say, do you know names of the winds? Boreas (Aquila), Notus (Auster), Eurus and Zephyrus (Favonius) are the basic North, south, east and west ones... you may add Thrascias (NNW), Libs (WSW), Corus (Caurus or Argestes) (NW), Volturnus (SE), Africus (Afer ventus) (SW)... you did read Milton's Paradise, didn't you... how can you hope to crack if you did not? Back to our target, now. Let's have a look at the protection scheme itself... let's see how the comparison between user input and serial number is made. Here the relevant part of the routine: :CHECK_IF_USER_CHEATS :0082...01A2-01B2... ;prepare for REGNAME :0082.01B3 E84AFE call 0000 ;call SHELL.REGOPENKEYetc :0082.01B6 0BC0 or ax, ax :0082.01B8 7455 je 020F ;you are BAD, beggar off :0082.01BA 1E push ds :0082.01BB 687046 push 4670 :0082.01BE 9AFFFF0000 call 1.4590h :0082.01C3 83C404 add sp, 4 :0082.01C6 3D0400 cmp ax, 4 :0082.01C9 7244 jb 020F ;you are BAD, beggar off :0082...01CB-01DC... ;prepare for REGKEY :0082.01DD E820FE call 0000 ;call SHELL.REGOPENKEYetc :0082.01E0 0BC0 or ax, ax :0082.01E2 742B je 020F ;you are BAD, beggar off :0082.01E4 1E push ds :0082.01E5 687046 push 4670 :0082.01E8 16 push ss if we redirect this to :0082.020A? Then having already cracked instruction 20F in order to have our necessary 0 inside [4698], we would now 'redirect' a correct 1 inside ax AFTER having already had the bad guy 0 there at line 215. Therefore, let's 'redirect' this jump: :0082.0217 EBF4 jmp 020D ;NO GOOD, continue with :0082.0217 EBF1 jmp 020A ;get_da_good_flag But Hey! Just a moment... What's the point of having loaded OURSELF a zero inside [4698] in the first time? WE DO NOT NEED IT! Let's use for the same aim the stupid protection itself... let's redirect FURTHER, DEEPER, BETTER. There is -indeed- a final cracking solution for this program (and a much more ELEGANT one: I still grudge the criticisms I suffered on the ground I used simple and 'unelegant' cracks in this tutorial). Let's redirect 82.217 to instruction 82.204 and let's merryly forget the whole previous cracking of instruction 82.020F... I mean... who cares if the protection, there, loads one in the [4698] and flags to 0 our sad ax? As soon as our last redirection snaps, the OTHER PART of the same protection scheme, the 'good guy' one, will snap and 'cover' the badflagged [4698] with TRUE zeros and will flag to 1 our beloved, but unfortunately zeroed, ax. Therefore forget ALL the previous cracks, this is the last but not least one (I mean, do not forget them... just fetch a new original nagged copy of webex.exe and start anew) and crack with that unnatural elegance that should always characterize all crackers from my school... solid crackers, old red's ones. I'll leave to you the obvious disassembly solution: if EBF4 jumps to 020D and EBF1 jumps to 020A, what will land our cracked copies to 0204? Ebbene? :=) Now, you see, we have gone a long way cracking our silly Webexpress... as you saw, we could have cracked this target in quite a lot of different ways, but eventually the best (and less intrusive) crack required indeed a slight knowledge of the working of this program. Once more we worked on a 'dead' application... and once more we have demonstrated that Winice, though a splendid tool, is NOT the 'only' or 'absolute' cracking tool... Often a good disassembler, a wordprocessor and a hexeditor (and a good cocktail) are more than enough to crack every single application you can think of. I will tell you something you may already have supposed: in order to prepare this lesson I originally cracked this Windows' application without EVER FIRING WINDOWS... using WCB (100.294 bytes which -unlike W32dasm, did not miss any routine), List (26.507 bytes... a quick 'lister' which is a *.com... not even an *.exe!) and PSEDIT (which is a very powerful, 65.862 bytes long hexeditor), all DOS quick application (to work REALLY you cannot use windoze)... but many of my readers will probably have to crack inside Microsoft's slow abomination... using W32dasm, Word and Hexworkshop and wasting time... after all... why not? The results will be the same, it's only a matter of -good or bad- taste. Now that you (begin to) understand re-direction cracking, you are ready to step over to 'real' higher cracks: what we call 'crackpatching'. Well, that's it for this lesson, reader. Not all lessons of my tutorial are -or will be- on the Web. You'll obtain the missing lessons IF AND ONLY IF you mail me back (via anon.penet.fi) with some tricks of the trade I may not know that YOU discovered. Mostly I'll actually know them already, but if they are really new you'll be given full credit, and even if they are not, should I judge that you "rediscovered" them with your work, or that you actually did good work on them, I'll send you the remaining lessons nevertheless. Your suggestions and critics on the whole crap I wrote are also welcomed. Do not annoy me with requests for warez, everything is on the Web, learn how to search, for goddess sake.
"If you give a man a crack he'll be hungry again
tomorrow, but if you teach him how to crack, he'll
never be hungry again"
+ORC na526164@anon.penet.fi