(Hic sunt tabulae: Best viewed with good old Courier New 8) Well well well, my dear friends, it's April, the "opening" month, when trees unfold and the womb of nature opens with young life... about time we start with the REAL work, and what I mean is that we begin damaging Microsoft interests... the real ones. I will therefore teach you here how to crack Microsoft's ubiquitous "trial version time protection". The typical Micro$oft's trial limit (of three months) is a clever marketing approach per se: I'm speaking of the "trial" version of their programs that you are supposed to use and enjoy for 90 days, until a screen reminds you that you WILL not be able to use it any more, coz the 90 days are over, please pay. Note the clever touch of 90 (instead of 30) days: three months are more than enough to get you real hooked on a program, especially huge monstrosities of the complexity of MS overbloated applications... it's a much better period than the usual "30 days" flavour that we find around in common shareware. Since Micro$oft makes the bulk of its money from software sold to corporate executives, senior sparer and assorted yuppies, it suits us well to crack as first example of this lesson, Microsoft PROJECT, one of those ridiculous "yuppie" programs that allow you to "plan" and "schedule" an activity or a project of your "team"... as if we were all time-slaves like those idiots... besides I may as well use this crap to program the nice "activities" of my +HCU's cracking units :=) I'm therefore cracking here the 90 days trial version of MSOFFICE WINDOWS PROJECT Version 4.1 of august 1995 which has the protection hidden inside the monstrous WINPROJ.EXE (4.240.896 bytes of overbloated bad programming). The error and protection messages dwell inside winproj.DLG (overbloated dialogues of 1.179.822 bytes). We'll begin with this somewhat "older" example of the ubiquitous "MS-trial" protection scheme (from 1995), since, as I have already told you elsewhere, the *history* and the *evolution* of protection schemes are powerful additional WEAPONS, that a cracker can use to defeat more complex schemes that may not be so evident if you cannot recognise their "physiognomy" at the first glance (or if you do not yet "feel" them :=) We'll crack in this lesson a Microsoft program from 1994, another one from 1995 (this first one) and two from 1997. I believe this should give you a wide enough palette of MS-protections, and that with this knowledge you should be able to crack every single piece of software Microsoft may throw at you in the next couple of years (at least :=) You'll see for instance that the "cmp eax,ecx" instruction at the heart of some of these MS-schemes is a constant characteristic, that you'll meet again and again, which differs from the typical "beggar off on bad flag ax" setting that the shareware authors usually use. A SMALL THEORETHICAL DIGRESSION First of all, before entering the guts of MS-cracking, a small "theoretical" digression. From a cracker's point of view, the new "trend" to give away full time limited versions of a software packages is extremely interesting: once you defeat the time checking routines (... plural coz there may be much more than one inside the same program) your work is done and you'll immediately enjoy the full application. The reason behind this trend (from password to time-trial) is quite simple: password-serial number protections are useless on a Web which abounds with free pirated serial number listings (I saw one with 54.000 different serial numbers-registration strings couples!) that anybody with intelligence level "amoeba" can easily find. I do not like serial number collectors: they do not teach anything, in my (admittely biased) opinion they just steal... fact is anyway, that the mere existence of such huge ready-made password listings has nuked any programmer's confidence in the serial/string protection approach (whose cracking techniques I have explained elsewhere in this tutorial), and this is the more true for "commercial" (i.e. "non toy") applications. You will find therefore, for big commercial application, the "Cinderella" protections (you may use this app for 30 days) or the "quiver" protections (you may use this app 30 times), or a combination of these two kinds, or a combination of both kinds PLUS the registration string/serial number protection method. One of the (minor) problems for us nice crackers is that with this kind of protections we may have some surprises later on... i.e. you crack your target and it works fine... well past the date it should have been crippled upon, WHEN YOU SET this DATE INSIDE YOUR OS but -alas!- it stops miserably working WHEN THE REAL TIME "of the world" has passed that cap... this has to do with OTHER protections, checking randomly, for instance, the date of some UNRELATED FILES on your hard disk. Obviously this does not concern us much... as soon as this happen we crack this "second level" protection scheme too, happily drinking another Martini-Wodka (use only Moskowskaja and add some Indian tonic Schweppes and a zest of lemon if you want to taste something that's really good) and forget the whole incident... but I had to mention it right now because I honestly DO NOT KNOW YET if some of the programs that I'll crack in these lessons do have or not such additional protections, nor have I the time to feel if there are other protections inside overbloated 5 million bytes horrors once I have already found the first (and maybe only) one, nor have I envy to wait 90 days just to see if something else snaps... should it happen (which I DO NOT believe, seen how primitive MS-protections look like) I'll then simply add the new crack to this section, we'll see. --------------------------------------------- Some elementary MUST KNOW when you crack time protections: Date and Time stamps in the root directory (old flavour) The root directory (in DOS) is a simple table of 32-byte entries, defining each file on the root directory. Bytes 0-7 have the file name, 8-10 have the file extension, 11 hydes the attribute flags, 12-21 are at times used for other protection tricks, 22-23 have the *TIME* stamp, 24-25 have the *DATE* stamp, 26-27 the starting cluster number and 28-31 the file size. The date and time stamps can record any date from January 1, 1980 through December 31, 2099. The time stamp is accurate to two seconds. The date and time stamps are each 2 byte values that are recorded by using the following equations: DATE = DAY+64*MONTH+512*(YEAR-1980) TIME = SECONDS/2+32*MINUTES+2048*HOURS In the time entry, the hour occupies the first 5 bits, the minutes the next 6, and the second the last 5. The seconds are actually stored as the number of seconds divided by 2, so the clock is accurate to 2 seconds. In the date entry, the year (subtracted from 1980... that is 0x7bc) is stored in the first 7 bits, the month in the next 4 and the day in the last 5 bits. How do we recover these values? Here the commonest tricks: seconds AND byte 22 with 11111; then multiply by 2 Minutes AND byte 23 with 111; then shift left 3 and add byte 23 shifted right 5 Hours Shift byte 23 right 3 Day AND byte 24 with 11111 Month AND byte 25 with 1, Multiply by 8 and add byte 24 shifted right 5 Year Add byte 25 to 1980 (0x7cb) and shift right 1 I hope you have the intelligence to understand by yourself why these methods work... the point is that as soon as you see something like that going on in the code you are examining, you will know that they are fiddling with date or time stamps (may be necessary, for instance, in order to reset the date and time stamps of an opened file without leaving any trace behind). How does a programmer fetch the date? He uses the _dos_getdate function. The _dos_getdate function uses system call 0x2A to get the current system date. The date information is returned in a dosdate_t structure pointed to by date. Synopsis: #include void _dos_getdate( struct dosdate_t *date ); struct dosdate_t { unsigned char day; /* 1-31 */ unsigned char month; /* 1-12 */ unsigned short year; /* 1980-2099 */ unsigned char dayofweek;/* 0-6 (0=Sunday) */ }; ------------------------------------------------------- AND NOW RUB YOUR HANDS: TO WORK! And now rub your hands: to work! Fetch your copy of the time limited version of Winproj.exe (you'll find it on the web... many magazines in Europe have published it on their cover CD at the beginning of this year... The one I use here is taken from a second-hand French magazine I found in Basel some time ago: PCMAG n.108) Well how do we proceed? As usual: Let's dead list everything (but you could get pretty quickly to the "hollow" point of your target through winice, is a matter of aesthetic choice, I prefer dead listing because it is more "relaxed" but you may use a combination of both approaches or whatever you like most). First thing you notice is that the dead listing is HUGE: more than 50 megabytes of text. You'll need a good wordprocessor to handle that... Microsoft's last one, word version 7.0 does not even accept such files, but look! Word 2 (the old version of Word, 1992 vintage) does run them (almost) without problems (you would not -obviously- have such problems under dos or linux). It's quite ironic, I believe, that Word 7 cannot open such a file, but on the contrary Word 2 ('92 version!) is capable of doing it... this confirms what I always supposed: huge overbloated programming is getting worse and worse... humanity has probably already entered one of its many phases of decadence :=) LET'S SURPRISE THE PROTECTION SCHEME FROM BEHIND We can get to the protection scheme of this target in many ways (and there are yet many more... almost as many as you fancy). Usually, to defeat these protections the traditional approach is to set the OS date past the trial period, run the target, individuate the nag screen as soon as it snaps, get the maximuml information about it (comprised its pixel dimensions) and then breakpoint it using some of these data) for instance (with winice) bpx on MessageBox (MessageBoxA to be exact). Remember that with Godot (Winice 3.0), you can use CONDITIONAL EXPRESSIONS! Say that the hwnd command gave you 09017E as handle for the nagscreen (this value will be different EVERY time you run your target), then you can selective breakpoint on it with: :bpx MessageBoxA IF ((ESP->4) == 09017E) since all Win32 applications pass parameters on the stack entering a function and the first parameter has a positive offset of 4 from the ESP register. Then you track back to the responsible code and so on and so on... since the protectionists are aware of these obvious "weak" points in their schemes, their "defences" will be all concentrated on this "path" (encrypted date compares far away from the messagebox call, bogus jumps, fake routines etcetera)... they'll try to defer people reverse backtracing to the protection scheme from the nag screen. We will therefore hack our way to these protections sneaking in from more hidden, less used and and less obvious doors, like (in this example) GetLocalTime or (as we'll see later) through the various "Write and read" file routines (i.e. the _open, _lseek and _read routines that the protection schemes use to fetch from the registry (or from somewhere else) the encrypted date of installation. The point is to take our target's protection schemes by surprise, from "behind" :=) OK: First of all... we have to do with a time protection, duh, therefore GetLocalTime is a first bait we can jolly use, let's see if we fish anything thattaway: ------------------------------------------------ * Referenced by CALLs at Addresses: |:05024FBE, :05024FF0, :05035A05, :0506489C, :0511A2A4, |:05167F6A, :05167FC1, :051F9E77, :05204C54, :05223F14, |:05223F81, :05224013, :05271A72 | :05024E77 55 push ebp :05024E78 8BEC mov ebp, esp :05024E7A 83EC10 sub esp, 00000010 :05024E7D 8D45F0 lea eax, [ebp-10] :05024E80 50 push eax :05024E81 FF15905E3C05 Call dword ptr [053C5E90] *GetLocalTime,(Kernel32-E2h) ;HERE! ------------------------------------------------ PARAMETERS inside Windows' FUNCTIONS After this call the program must save the time parameters: for those of you that do not know anything, the typedef structure is the following one... (VERY IMPORTANT FOR TIME PROTECTIONS! Learn it by heart! It's used in many other various FileTime routines too): ------------------------------------------------ WORD wYear WOED wMonth WORD wDayOfWeek WORD wDay WORD wHour WORD wMinute WORD wSecond WORD wMilliseconds ------------------------------------------------ Why did we seek GetLocalTime? Because the protectionists have to know somehow if the program run over the allowed time and, while there are many other methods to do this, one of the most simple is a check through good humble GetLocalTime... so we'll begin from here, ready to check all other possibilities only if we do not fish anything with this bait. Examining the savings of the return values from this routine, as with many other time routines, you'll find in your dead listing something like this: ------------------------------------------------ CALL [KERNEL32!GetLocalTime] mov dx, [EBP-10] that's the year, will be something like 7CD=1997 mov dl, [EBP-0E] the month... lower part of a register is enough mov al, [EBP-0C] that's the day of the week, ditto mov al, [EBP-0A] that's the day mov dl, [EBP-08] that's the hour mov al, [EBP-06] that's the minute mov dl, [EBP-04] that's the second and if somebody would care, you would have had also mov dx, [EBP-02] that's the millisecond, but few time protections care for that (which is stupid to say the least, since so many ideas come immediately to the mind :=) ------------------------------------------------ I said "something like" the above, but things could differ a little coz the count [EBP-xx] could be flawed by pushes and then you would have something like -say- the year in [EBP-34] and, accordingly, the month in [EBP-32] et cetera... anyway the SERIE will always be respected, therefore you could also crack these protection in a completely different (and easy) way, that good old +ORC will now let you glimpse... simply set a breakpoint on a user routine (study this part of winice documentation WELL... you'll be able to crack almost ANYTHING with your own breakpoint routines)... say when the target loads for instance 7D5h on ax OR on dx (you will not know which of both registers the protection scheme use).. then simply run the program with the changed os date 2005 (which is 7D5h) and see what happens... you'll breakpoint smack in the middle of the protection scheme :=)... Why use 2005 instead of 1997? Easy: we wont use the current year (7CD=1997) nor the next couple of years, because the protectionists oft use other unrelated variables with those same values (say current year of release and a couple year more) *on purpose*, to block these very attempts. But, as I said, we do not need to use winice to crack this cram... bear with me and see. Let's be more technical: you have reached a level where you have the right to UNDERSTAND exactly how to access parameters (i.e. the fixed values that MUST be passed to a function) and local variables (i.e. the values that the protectionists have decided to use, say in order to compare or manipilate) inside windows calls: - If you set a breakpoint at the exact function address, for example, :BPX GetFileTime, use ESP+(param#*4) to address parameters, where param# is 1, 2, 3, or whichever parameter that function calls... Since BOOL GetFileTime(HANDLE hFile, LPFILETIME lpCreation, LPFILETIME lpLastAccess, LPFILETIME lpLastModified) you'll easily know what is what. - If you set a breakpoint INSIDE a function body (after the full prologue PUSH EBP, MOVE EBP,ESP, SUB ESP,size (locals) has been executed)use EBP+(param#*4)+4 to address parameters. - Once the space for local variables is allocated on the stack, the local variables can be addressed using a negative offset from EBP. The first local variable is at EBP-4... with two pointer local variables (typically dword sized) one will therefore be at EBP-4 and the other will be at EBP-8. Comprendes? Enough... back to our calls to GetLocalTime... see how the "centralised" call approach of windows helps us a lot... all the calls of the program to this routine are here under our eyes... look at the 13 CALL references, once more, (THIS IS IMPORTANT) look at WHERE they come from: * Referenced by CALLs at Addresses: |:05024FBE, :05024FF0, :05035A05, :0506489C, :0511A2A4, |:05167F6A, :05167FC1, :051F9E77, :05204C54, :05223F14, |:05223F81, :05224013, :05271A72 | :05024E77 55 push ebp :05024E78 8BEC mov ebp, esp :05024E7A 83EC10 sub esp, 00000010 :05024E7D 8D45F0 lea eax, [ebp-10] :05024E80 50 push eax :05024E81 FF15905E3C05 Call dword ptr [053C5E90] *GetLocalTime,(Kernel32-E2h) A LITTLE ZEN: FEELING THE CALLS OF THE SEA Ok, let's see which sectors of our target do actually call our bait GetLocalTime... look at the call references above! Out of 13 calls, Sectors "024F" and "167F" and "223F" call it twice, whereby Sectors 035A, 0648, 11A2, 1F9E, 204C, 2240 and 271A call it only once. This may not mean anything, of course, but hey! on the other hand it could be very interesting... clearly we'll examine FIRST what happens in these "time-intensive-calling" parts of the code: Let's begin. 1) "Sector 024F" calls GetLocalTime twice, why? :first_call_snippet_(called_from_:0504A3F7)_calls_at_024FBE :05024FA4 55 push ebp :05024FA5 8BEC mov ebp, esp :05024FA7 83EC0C sub esp, 0000000C :05024FAA 53 push ebx :05024FAB 8D45F4 lea eax, [ebp-0C] :05024FAE 8B1D04452C05 *** mov ebx, [052C4504] ;get holyloc :05024FB4 50 push eax :05024FB5 885DFE mov [ebp-02], bl ;create holylow :05024FB8 887DFF mov [ebp-01], bh ;create holyhigh :05024FBB C1EB10 shr ebx, 10 ;create holyshr10 :05024FBE E8B4FEFFFF *** call 05024E77 GetLocalTime ;FIRST CALL :05024FC3 8A45FE mov al , [ebp-02] :05024FC6 3845F6 *** cmp [ebp-0A], al ;month=holylow? :05024FC9 7512 jne 05024FDD ;flag 1 :05024FCB 8A45FF mov al , [ebp-01] :05024FCE 3845F7 *** cmp [ebp-09], al ;day=holyhigh? :05024FD1 750A jne 05024FDD ;flag 1 :05024FD3 66B80000 mov ax, 0000 ;flag 0 :05024FD7 66395DF4 *** cmp [ebp-0C], bx ;year=holyshr10? :05024FDB 7404 je 05024FE1 ;keep flag 0 :05024FDD 66B80100 *** mov ax, 0001 (flag 1: day or month or year differ) :05024FE1 5B pop ebx :05024FE2 8BE5 mov esp, ebp :05024FE4 5D pop ebp :05024FE5 C3 ret :second_call_snippet_calls_at_5024FF0 :05024FE6 55 push ebp :05024FE7 8BEC mov ebp, esp :05024FE9 83EC08 sub esp, 00000008 :05024FEC 8D45F8 lea eax, [ebp-08] :05024FEF 50 push eax :05024FF0 E882FEFFFF *** call 05024E77 GetLocalTime ;SECONDCALL :05024FF5 0FB64DFB *** movzx byte ptr ecx, [ebp-05] ;savepar :05024FF9 0FB645FA *** movzx byte ptr eax, [ebp-06] ;savepar :05024FFD C1E108 shl ecx, 08 :05025000 0BC8 or ecx, eax :05025002 0FB745F8 *** movzx word ptr eax, [ebp-08] ;savepar :05025006 C1E010 shl eax, 10 :05025009 8BE5 mov esp, ebp :0502500B 0BC8 or ecx, eax :0502500D 5D pop ebp :0502500E 890D04452C05 *** mov [052C4504], ecx ;save in holyloc :05025014 C3 ret Quite interesting... a flagging (that could be a green light) and some parameters saved and compared within a holy location... why does this "sector 024F" call? Is it just checking against an holy location IF the time has changed enough to justify the snapping of other routines? Or is it this the part of the code that encrypts the date in the holy location itself?... We could follow this path, and "freeze" the holy location, or explore who calls this code snippets... this would bring us to the protection scheme as well of course... but this kind of work -MADE NOW- would not be methodologically correct... YOU SHOULD INDEED NEVER GO ASTRAY... KEEP YOUR CRACKING APPROACH (as long as you do not get obvious signs that you found what you were looking for), it's like landing a plane... keep the original approach and DO NOT delve inside everything you happen to notice that "might" be a treffer! Here we have something "biting" the hook (our worm is GetLocalTime), but it's not yet time to pull out our fishing line yet.. let's continue... We were investigating all sections of our target's code which effectuate at least a double call to GetLocalTime... let's continue! Let's have a quick look to the other two "twin" occurrences of GetLocalTime (167F and 223F) before delving inside any one of them... maybe we will not need to delve at all. Remember, always concentrate on ONE approach at a time: multa agendo nihil agens! Here the second "twin calls" location area: 2) "Sector" 167F calls GetLocalTime, why? :05167F6A E808CFEBFF call 05024E77 ;CALL GetLocalTime :05167F6F 66817DF4C007 cmp [ebp-0C], 07C0 ;is 1984? :05167F75 722F jb 05167FA6 ;go badflag :05167F77 66817DF40108 cmp [ebp-0C], 0801 ;is 2049? :05167F7D 7727 ja 05167FA6 ;go badflag :05167F7F FF75F4 push [ebp-0C] ;save validyear :05167F82 660FB645F7 movzx byte ptr ax, [ebp-09] ;pushday :05167F87 660FB64DF6 movzx byte ptr cx, [ebp-0A] ;pushmonth :05167F8C 50 push eax :05167F8D 51 push ecx :05167F8E E84EC10B00 call 052240E1 ;call here :05167F93 663B45E4 cmp ax, [ebp-1C] :05167F97 7D0D jge 05167FA6 ;go badflag :05167F99 668B4DE4 mov cx, [ebp-1C] :05167F9D 662BC8 sub cx, ax :05167FA0 66894DF2 mov [ebp-0E], cx :05167FA4 EB06 jmp 05167FAC ;do not badflag * Referenced by a Jump at Addresses:05167E13(C), :05167ED7(C), :05167F1B(C), :05167F64(C), :05167F75(C), :05167F7D(C), :05167F97(C); lotta routines badflag here... this is BADFLAG INTENSIVE :05167FA6 66C745FE0100 mov [ebp-02], 0001 ;BAD FLAG !!!*** :no_bad_flag :05167FAC FF75DC push [ebp-24] :05167FAF FF151C5C3C05 Call dword ptr[053C5C1C];RegCloseKey :05167FB5 EB25 jmp 05167FDC ;jump 2nd getlocaltime :only_5167DE5_calls_this_second_GetLocalTime :05167FB7 66C745EC0000 mov [ebp-14], 0000 :05167FBD 8D45F4 lea eax, [ebp-0C] :05167FC0 50 push eax ;SECOND GetLocalTime :05167FC1 E8B1CEEBFF call 05024E77 GetLocalTime ;call it :05167FC6 66817DF4C007 cmp [ebp-0C], 07C0 ;between 1984... :05167FCC 7208 jb 05167FD6 ;jump flag_unvalid_year :05167FCE 66817DF40108 cmp [ebp-0C], 0801 ;...and 2049? :05167FD4 7606 jbe 05167FDC ;jump_to_valid_year :flag_unvalid_year :05167FD6 66C745FE0100 mov [ebp-02], 0001 ;flag "unvalid_year" :valid_year_almost_everybody_calls_here :05167FDC 66837DFE00 cmp [ebp-02], 0000 ;valid_flag? :05167FE1 755F jne 05168042 ;beggar off:unvalid something :05167FE3 66837DF000 cmp [ebp-10], 0000 ;valid ebp-10? :05167FE8 750E jne 05167FF8 ;jmp unvalid_e10 :05167FEA 66837DEC00 cmp [ebp-14], 0000 ;valid ebp-14? :05167FEF 7451 je 05168042 ;beggar off,unvalid :05167FF1 66837DF000 cmp [ebp-10], 0000 ;sure thatebp-10=0? :05167FF6 7407 je 05167FFF ;continue ifso :unvalid_e10 :05167FF8 66837DEC00 cmp [ebp-14], 0000 ;check if e14valid :05167FFD 7543 jne 05168042 ;no? be damned! :valid_e10_and_e14 :05167FFF 0FBF4DF2 movsx word ptr ecx, [ebp-0E] ;e10 and e14 true :05168003 66833D58192C0501 cmp dword ptr [052C1958], 0001 :0516800B 1BC0 sbb eax, eax :0516800D 83E05A and eax, 0000005A ;pretty obvious :05168010 83C05A add eax, 0000005A ;isnt it? :05168013 3BC1 cmp eax, ecx ;HERE******** :05168015 7C2B jl 05168042 ;beggar off :05168017 66837DF21E cmp [ebp-0E], 001E ;0x1E = 30 :0516801C 7F4A jg 05168068 ;good guy jump :0516801E 8D45F4 lea eax, [ebp-0C] Well, that's was it actually... we notice two consecutive locations with 5Ah (90 decimal) there... as if they had written "OUR TIME LIMIT IS HERE, PLEASE REMOVE AND USE FOR EVER AND EVER". Maybe Micro$oft wants exactly this... I mean, they give away their (bugged) web browser for free just in order to bankrupt Netscape, why shouldnt they as well give every software away for free (bad protecting it on time limits and spreading everything on all cd-rom covers of the planet) until they have bankrupted every concurrent and do effectively held every user on the planet "pillado por los huevos"? Maybe in cracking this protection scheme I'm only helping Gates... the more people use its programs the more they will spread... the more he will dominate the market... yet I could not care less about Micro$oft's own stupid plans... programming the way they do, they will never be able to dominate a portion of halfbacked potatoes in my humble opinion... therefore let's crack this crap black and blue and let's hope Micro$oft loose a lot of money thank us, yeah, that's life! Let's crack a lot of Micro$oft software from now on! A white flower in our mouth, a computer not far away, a cold determination in our fingers. Death to Gates! *** Quick Crack for Micro$oft's Project 95, by +ORC, 04/1997*** search for the string :05167FA6 66C745FE0100 mov [ebp-02], 0001 ;BAD FLAG**** and change it to: :05167FA6 66C745FE0000 mov [ebp-02], 0000 ;always good *** now find some stupid yuppies and give them this app *** JUST A MOMENT (1) Well, just a moment... go back to the code "snippets" above, pupils... why did we not search for :05168015 7C2B jl 05168042 ;beggar off in order to noop everything say with an inc/dec: :05168015 40 inc eax :05168016 48 dec eax Why? Because it would NOT have worked... or, as a matter of fact, it would have worked only in SOME cases... this is an example of a "protectionists' bait", please examine the code. You should -by now- know enough our art to be able to understand by yourself why the crack at 5167FA6 works and the crack at 5168015 (which is indeed part of the protection) will not work... a hint for you: change months and YEARS of your os as you experiment with this stuff. This answer is part of the strainer of this lesson, therefore work on it and understand the problem. And what about the remaining last "double call" location at "223"? Did I not say we should keep steady on our approach before delving inside? Yes and no: "quod satis est cui contingit, nihil amplius optet" (Horatius, emailing his friends, as you can see you can always find a proverb to demonstrate what you are saying, even if you are contradicting yourself :=) But as soon as you SEE the protection there is NO POINT (unless you really have to, in order to understand some weird scheme thoroughly) to continue... the plane is landed, relax, drink something. Anyway for such things there are no fixed rules... do whatever you like and prefer, I personally think that the best approach is a mixture of iron will and extreme flexibility. JUST A MOMENT (2) But wait, since they used the 5Ah byte... could not we have found the protection just searching for 5Ah? Yes, and indeed, we would have found the scheme around it immediately... but that IS NOT the correct approach, since you should NOT always presume that the protectionists behave REALLY always that stupid (even if they almost always do :=) JUST A MOMENT (3) But wait, could we have not just winiced the working of the program in order to backtrace as soon as the protection nag screen snaps? Yes, and it would have worked... but why ruin your eyes on screen in a closed and may be dusty room, getting cramps in your shoulders that not even a good massage will blow away, when you can crack much more relaxed, sitting quiet in a shadowy garden, looking lazily (it's April! A beautiful month! Go outside! What the hell are you doing inside a room?) at a couple of sheets of paper, feeling the wind among the leaves above you, while a cool Martini-Wodka fizzles in your hands? If you want to use the "live" winice approach go ahead... I'll even tell you right now a couple of things that can be useful in order to crack some (other) protections: for Cinderellas schemes bpx MessageBox or bpx GetLocalTime or bpx GetFileTime and look WHO gets the "time" data a little before the nagscreen snaps... I did not check but I'm sure that if you do it here, you'll have quite a lot of calls along the program, whereby the "initializing" calls from our "sector 24F" will snap at the beginning (and at the end) of the target life and our protection call (the one we cracked the bad flag of) i.e.: :05167F6A E808CFEBFF call 05024E77 ;CALL GetLocalTime in KERNEL will happen JUST BEFORE the snap... so you can crack thatta way too... these patterns are always the same. **************** A little icy digression ***************** This is -after all- a tutorial, therefore for those of you that do not know anything, here are some useful (and well known) older winice little tricks and memory addresses discussions. Even if I do prefer to use as much as possible my "dead listing" methods, I realise that at times the help of winice is indispensable... the little tricks below refer to Winice for windows 95 older copy (before Godot, i.e. 3.0) and you may skip this section if you are using winice 3.0. which has the IF feature for conditional breakpoints, the WHAT command and much more. I strongly reccommand using Winice 3.0. In order to learn how to use it correctly your best approach is to find on the web the GOOD documentation of Numega (it's in adobe acrobat's PDFformat) here you have the names you'll need to find it (and NAMES are the MOST important thing on the web): Si30cr.pdf 3.205.000 bytes COMMAND REFERENCE Si30ug.pdf 1.038.000 bytes USING SOFTICE Last time I fetched them they were inside the zipped file Sice3doc.zip, 3.358.000 bytes read these documents thoroughly. Once you read them you (almost) will not need my lessons any more. But some of the simple tricks below can be useful even with Winice 3.0., and anyway I want ALL of the readers of this tutorial to know their tools and to use them in the best way, even those too lazy or too stupid to fetch the above mentioned files... therefore, here you are... some (older) winice's MUST know: BPM DS:xxxxxxxx W GT 1E Breakpoint first time that the byte at location DS:xxxxxxxx has a value written to it that's greater than 1Eh (30) Useful qualifiers are EQ (equal) NE (not equal) GT (greater than) LT (less than) and M (mask) this last one is pretty complicated but allows powerful breakpointing for dongles cracking: after having given your routine command "tss", begin your dongle breakpointing using, for instance: BPIO 3F6 R EQ M 11XX xx00 This defines a byte break point on I/O port read, the first time that I/O port 3F6 is read with ANY value that has the two high order bits set to 1 and the two lower ones to zero, the other bits can be any value. The same is valid for BPM (breakpoint on memory write): BPM CS:802A2D22 W EQ M 0xxx xxxx xxxx xxxx xx11 you dig it? The mask method is even better than the qualifier one if you are NOT sure about which value the protection will load :=) CSIP NOT &F000:0 &FFFF:0 Breakpoint only outside BIOS useful to limit breakpoint snapping Remember that CSIP and BPM (READ/WRITE) can be very USEFUL to slow down the execution of a windows program... if you use "heavy breakpointing" in this way, setting a number of "useless" but heavy breakpoints that winice will monitor, windows will crawl (even on a Pentium 200) and you'll be able to breakpoint MANUALLY exactly at the point where a protection snaps... I still prefer the "dead listing" method of cracking personally, though. BPINT 21 AH=0F Breakpoint on openfile (funny how many INT 21 are execited under windoze) (old style, with Winice 3 it's BPINT 21 IF EAX=0F) BPINT 21 AH=2A Breakpoint on GetDate (old style, with Winice 3 it's BPINT 21 IF EAX==2A) When we are still at it, remember that in 32bit mode there are only TWO selectors (when you search the whole memory for instance): 28:0 and 4 virtual gigabytes of CODE 30:0 and 4 virtual gigabytes of DATA and STACK We saw (cracking DOS) how to get from virtual address to physical address in 8086 style segment:offset code: multiply the segment by 16 and then add the offset. In a "protected mode" selector it's different: linear address is calculated by adding the offset TO THE BASE ADDRESS FOUND IN THE GDT (or LDT, local descriptor table is used if bit TWO of the selector is a 1, global DT is used otherwise... GDT and LDT are "lookup" tables used to calculate addresses). At times you must understand a little the physical addresses structure in order to crack effectively: 00000000 - 000FFFFF Current Virtual Machine (Windows and Windows Programs) 00400000 - 7FFFFFFF Physical memory (contiguous) 80000000 - 803FFFFF Windows' VxDs 80500000 - 80FFFFFF Windows programs 81000000 - FFFFFFFF DOS VMs ...use the commands "page" and "addr" and have a look around. The command addr is also very useful to understand in which context you are when winice pops up. Remember that each 32 bit task is given the address space from 400000 to 7FFFFFFF, which is called an "address context". This virtual address space is reserved for 32 bits applications and private DLLs And now two MUST KNOW winice commands that will spare you a lot of wasted time when you delve inside the huge windows codebulks we have to peruse: P RET (that's F12 most of the time) steps out of the current procedure, may take ages if it's very large that's step until return G @SS:ESP (that's F11 most of the time) throws you at the caller of the procedure you bpxed on (bpx GetLocalTime and execute F11 (or write G @SS:ESP) as soon as winice pops up and you'll see what I mean) A couple of watches like *ds:esi (and ds:esi) and a dex 1 ss:esp in your ini setting of winice would be a good idea too IMO. This said, Winice 3.0 allows POWERFUL breakpointin, like for instance: bpx ntoskrnl!ExAllocatePoolWithTag IF (esp->c == 1) DO "data1;dd eax" (I will explain all this łore thoroughly in the lessons about Windows NT) ********************************************** Back to our time protections cracking (and Micro$oft bashing :=). Once more... there are THOUSAND different ways to crack these applications, and this GetLocalTime "fishing" is only ONE of them... I will teach you -of course- ALL the methods I believe are MOST effective... you must be enough crack-able by now to know when, applying these techniques to OTHER programs (hopefully Micro$oft ones) you'll have to use slightly or substantially different approaches... non semper Saturnalia erunt, as you'll see. Are these protections always so easy to defeat? No and yes, maybe no... yet there are far more complex schemes. But time checking from a CD-ROM code is the ultimate doom of the protectionists... you see: the problem for them is the following: They are protecting using a "write only once" media (a CD-ROM)... therefore every time you put the cd-rom in your driver you are re-installing a perfect "virgin" copy of the protected program... there is no way a recursive message can be placed INSIDE the code, telling it to never execute again... I remeber older nasty "quiver" protections in dos... after the 20ntieth installation the program formatted as bad a sound sector of the diskette... that was clever! But that's impossible on a read only media, therefore let's see... where can they keep track of the eventuality that you used it before? 1) Inside the intricacies of Windows register, this most obscure fat abomination (should I write a scary computer fiction film, I would imagine a windows register growing fatter and fatter, week after week, and then suddenly grabbing the user through the a:\ drive in order to eat him :=) 2) Inside an apparently unrelated file or *.dll that gets "lost" inside the garbage subdirectories c:\windows or c:\windows\system (by the way, that's exactly the same technique you should use in order to protect your files at work from administrator's prying eyes... throw every application inside windows subdirs and give them funny names, like a6JJJK.EXE... no administrator on this earth (and no censorship corporate patrolling software) will come to the idea that that is your beloved chess program :=). 3) Inside small parts of the BOOT sector of your harddisk that can safely be used for this kind of tricks without altering the booting (this is a trick the protectionists have learnt from our fellows viri-writers... see how even the bad ones have a teaching function in this funny virtual world. Once more virus code studying is VERY important in order to crack well. Alas for the protectionists! All these tricks are pretty easy to defeat too, and I will show you HOW to do it :=) For a start here is HOW easily you would have checked your boot sector with an old DOS system... 1) Run debug (or, better, symdeb) 2) -L 100 2 0 1 (that's Load into memory address Ox100 from drive C (that's number 2... 0 is A, 1 is B and 2 is C, duh, starting from sector 0 for 1 sector whatever you find there. Here you have the boot sector of the PC I'm writing on: -L 100 2 0 1 -d 100 L 200 17D3:0100 EB 3C 90 4D 53 57 49 4E-34 2E 31 00 02 40 01 00 k<.MSWIN4.1..@.. 17D3:0110 02 00 02 00 00 F8 9A 00-3F 00 40 00 3F 00 00 00 .....x..?.@.?... 17D3:0120 41 44 26 00 80 00 29 FC-0F 5F 3C 20 20 20 20 20 AD&...)|._< 17D3:0130 20 20 20 20 20 20 46 41-54 31 36 20 20 20 FA 33 FAT16 z3 17D3:0140 C9 8E D1 BC FC 7B 16 07-BD 78 00 C5 76 00 1E 56 I.Q<|{..=x.Ev..V 17D3:0150 16 55 BF 22 05 89 7E 00-89 4E 02 B1 0B FC F3 A4 .U?"..~..N.1.|s$ 17D3:0160 06 1F BD 00 7C C6 45 FE-0F 8B 46 18 88 45 F9 38 ..=.|FE~..F..Ey8 17D3:0170 4E 24 7D 22 8B C1 99 E8-77 01 72 1A 83 EB 3A 66 N$}".A.hw.r..k:f 17D3:0180 A1 1C 7C 66 3B 07 8A 57-FC 75 06 80 CA 02 88 56 !.|f;..W|u..J..V 17D3:0190 02 80 C3 10 73 ED 33 C9-8A 46 10 98 F7 66 16 03 ..C.sm3I.F..wf.. 17D3:01A0 46 1C 13 56 1E 03 46 0E-13 D1 8B 76 11 60 89 46 F..V..F..Q.v.`.F 17D3:01B0 FC 89 56 FE B8 20 00 F7-E6 8B 5E 0B 03 C3 48 F7 |.V~8.wf.^..CHw 17D3:01C0 F3 01 46 FC 11 4E FE 61-BF 00 07 E8 23 01 72 39 s.F|.N~a?..h#.r9 17D3:01D0 38 2D 74 17 60 B1 0B BE-D8 7D F3 A6 61 74 39 4E 8-t.`1.>X}s&at9N 17D3:01E0 74 09 83 C7 20 3B FB 72-E7 EB DD BE 7F 7D AC 98 t..G;{rgk]>.},. 17D3:01F0 03 F0 AC 84 C0 74 17 3C-FF 74 09 B4 0E BB 07 00 .p,.@t.<.t.4.;.. 17D3:0200 CD 10 EB EE BE 82 7D EB-E5 BE 80 7D EB E0 98 CD M.kn>.}ke>.}k`.M 17D3:0210 16 5E 1F 66 8F 04 CD 19-BE 81 7D 8B 7D 1A 8D 45 .^.f..M.>.}.}..E 17D3:0220 FE 8A 4E 0D F7 E1 03 46-FC 13 56 FE B1 04 E8 C1 ~.N.wa.F|.V~1.hA 17D3:0230 00 72 D6 EA 00 02 70 00-B4 42 EB 2D 60 66 6A 00 .rVj..p.4Bk-`fj. 17D3:0240 52 50 06 53 6A 01 6A 10-8B F4 74 EC 91 92 33 D2 RP.Sj.j..ttl..3R 17D3:0250 F7 76 18 91 F7 76 18 42-87 CA F7 76 1A 8A F2 8A wv..wv.B.Jwv..r. 17D3:0260 E8 C0 CC 02 0A CC B8 01-02 8A 56 24 CD 13 8D 64 h@L..L8...V$M..d 17D3:0270 10 61 72 0A 40 75 01 42-03 5E 0B 49 75 77 C3 03 .ar.@u.B.^.IuwC. [MICROSOFT PUBLISHER 1997] Time to bash Microsoft once more... how nice! Let's have a (quick) look at Microsoft Publisher 1997, another "60 days" trial version protection from Microsoft (60 days, because the DTP market moves so quickly that they cannot allow to let it loose for three months)... I'll show you where the protection is, how it snaps and how to crack it... I got my copy from one of the MANY magazines that published the 60 days demo version in April 1997... you should be able to find this one everywhere... here are the relevant data: MSPUB.EXE 2.476.304 19/04/97 19:19 <--- da target MSPUB.ALF 34.054.330 17/04/97 20:18 <--- da dead listing MSPUB.DED 2.476.304 19/04/97 19:19 <--- da copy you need You should always do a copy of the original target BEFORE beginning your work on it, you'l need it a lot when you time deprotect. To crack this target we'll use a slightly different approach... let's call this technique "hit and see"... it's one of the most obvious approaches, and I surely have not invented it... everybody knows it: you run the program, you let the time protection snap, you look at the "hardwired" hex differences inside the body of the target (the "non functioning" copy will slightly differ from the "functioning" one) and you "reverse engineer" your dead listing back to the protection scheme that snapped the differences... pretty easy, isnt'it? -------- digression: words inside targets --------------------- If you are interested in another, COMPLETELY DIFFERENT cracking door, here are the relevant messages inside our target... I used SR32exe to fetch them (a very nice fetcher, thanks fravia! :=), which is much better than my own old C scripts :=( As a small "extra" for this lesson, crack the protection out of this fetcher, a program that I'm sure you'll find VERY useful (I did): ------------------------------------- Funduc Software search application: http://home.sprynet.com:80/sprynet.funduc 102372.2530@compuserve.com SR32 EXE 286.720 13/05/96 0:14 SR32.exe SR HLP 36.830 12/05/96 3:28 SR.HLP SR EXE 170.624 12/05/96 23:58 Sr.exe ------------------------------------ Here the results of this program running on "expir"... ------------------------------------ Processing file : C:\PROGRAM FILES\MICROSOFT PUBLISHER 97\Mspub.exe Offset 0x1ac5e9 - This trial version of Publisher has ed. To order a permanent copy, call 1-800-426-9400 or visit the Publisher site on the World Wide Web at http://www.microsoft.com/publisher/. To uninstall this version choose Add/Remove Programs i Offset 0x1ac6f4 - This trial version of Publisher will e in %d days. For more information about Publisher 97, call 1-800-426-9400 or visit the Publisher site on the World Wide Web at http://www.microsoft.com/publisher/. ----------------- digression end -------------- As I said... there are MANY doors you may trespass to crack this target... let's continue with the simplest one in my opinion: 1) Let's run it... it runs, how nice! 2) Let's move the OS date... say four months ahead. It does not run anymore, this is sad! 3) WHAT HAS CHANGED IN THE FILE? That's the point my reader... Let's compare the two files... the original and the copy after the fatidic message "trial time is out, won't work any more", bye sucker:* FC /b mspub.ded mspub.exe (that's the DOS command FileCompare that you are giving, duh) And this is the result you'll get: "Comparing files mspub.ded and mspub.exe" "000F3703: 75 EB" "000F370C: 75 EB" MMMM! That's interesting! And what do we have there? Let's have a look at our (huge) dead listing (do not forget: 2560 (256*10) bytes difference between REAL AND Wdasm addressing... you just add A00h to the DOS addresses to get your bearings inside the dead listing files... F3703+A00= F4103... F370C+A00=F410C): * Referenced by lotta CALLs at Addresses: |:004014F1, :0040199A, :00401AC6, :00401C37, :00401F6C, ;first calls ... HUNDERT CALLS AND HUNDERT MORE... many many calls I have not reprinted |:0058B1C4, :0058B279, :0058B443, :0058BA9F ;last calls | :004F40FC 8B4C2404 mov ecx, [esp + 04] :004F4100 83F901 cmp ecx, 1 :004F4103 EB09 **** jmp 004F410E ;..... Should be 75, i.e. Jne :004F4105 833DD0225C0000 cmp dword ptr [005C22D0], 0 :004F410C EB06 **** jmp 004F4114 ;..... Should be 75, I.e. Jne :004F410E 890DD0225C00 mov [005C22D0], ecx ;ecx <> 1 flag 22D0 FALSE :004F4114 A1D4225C00 mov eax, [005C22D4] :004F4119 51 push ecx :004F411A 83E840 sub eax, 00000040 :004F411D 890DC4935C00 mov [005C93C4], ecx :004F4123 A3D4225C00 mov [005C22D4], eax :004F4128 83C040 add eax, 00000040 :004F412B 50 push eax :004F412C FF158C085D00 Call dword ptr [005D088C] ;call MSVCRT40.longjmp :004F4132 83C408 add esp, 00000008 :004F4135 C20400 ret 0004 All this means for us only one thing... location [005C22D0] decides a lot. But wait, let's see... What did these assholes do? They "patched" their own program in order to protect it... how funny... time is out, so jmp anyway (instead of jump on not equal) to the evil routines... they know that now we would like to know WHO calls here... and there are (therefore, as dissuasion) hundert of procedures calling this cram... no point in checking all of them... you would sink in a sea of calls... what will we do? Where is the real and only one PROTECTION call to 4F40FC among this bunch of useless calls? We have only ONE way to find it out without losing time... Let's zen a little... you have read this lesson from the beginning... now STOP and think... i.e. use your brain (supposed you have one): do not read any more what follow: STOP NOW and answer this question BEFORE proceeding... really... you are here to learn, NOT TO COPY METHODS THAT OTHERS HAVE FOUND... once more... We know that somebody modified this cram... but HOW DO WE GET BACK (how do we reverse the flow) TO THE CORRECT CALLING ROUTINE AMONG HUNDERT OF THEM calling here? Ok, you did stop and think... you may go on reading (if you did not... be ashamed... cracking is like watching a beautyful picture... you must think a lot, else your watching is useless). OK: We used the GetLocalTime routine as a bait inside my first example... can we apply it here? Let's search for it... HEY! They do not use it at all, there is NO GetLocalTime in this application... how the hell do they know which time is it? Let's search for "time", my friends... here the locations: Processing file : C:\PROGRAM FILES\MICROSOFT PUBLISHER 97\Mspub.alf Line 1340 - Addr:BFF77105 hint(00DB) Name: GetFile