HOW TO CRACK, by +ORC, A TUTORIAL







------------------------------------------------------------------------

Lesson 9 (4): How to crack Windows, Hands on







------------------------------------------------------------------------

[WEBEXPRESS] [REDIRECTION]





  'Dead listing' approach - second part







------------------------------------------------------------------------





                          ***********

                  +HCU material FEBRUARY 1997

                        LECTIO IN FIERI

                          ***********                  

  (Hic sunt tabulae: Best viewed with good old Courier 10)
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 the

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

:0082.01E9 8D46AE        lea ax, [bp-52] ;USER INPUT LOCATION

:0082.01EC 50            push ax

:0082.01ED 0E            push cs

:0082.01EE E8E7FE        call 00D8  ;call loadchars and...

:0082.01F1 16            push ss    ;...ansilower and magic

:0082.01F2 8D46D6        lea ax, [bp-2A]     ;MAGIC LOCATION

:0082.01F5 50            push ax

:0082.01F6 16            push ss

:0082.01F7 8D46AE        lea ax, [bp-52]     ;USER INPUT

:0082.01FA 50            push ax

:0082.01FB 9AFFFF0000    call USER.LSTRCMPI  ;check strings

:0082.0200 0BC0          or ax, ax           ;strings differ?
:0082.0202 750B          jne 020F   ;you are BAD, beggar off

:0082.0204 C70698460000  mov word ptr [4698], 0 ;good guy!

:0082.020A B80100        mov ax, 0001        ;flag ax=1,OK

:0082.020D EB0A          jmp 0219            ;continue

:0082.020F C70698460100  mov word ptr [4698], 1 ;beggar off!

:0082.0215 33C0          xor ax, ax          ;flag ax=0

:0082.0217 EBF4          jmp 020D            ;NO GOOD, continue

...

:retf
The above block of code makes EVIDENT how such a protection

scheme works:

1)   first of all it performs the 'usual' checks on the entered

strings (something must be written there, chars must make sense,

minimum length, etc)

2)   after the usual checks the loadchars and trasformchars

routines are fired.

     If you look at the listing, routine 82.00D8 calls among

other things the LPSTR AnsiLower(LPSTR lpszString) function which

under Windows NT/32 does not exist any more and has been

substituted with a macro (Yes, a macro! This should make you

shiver thinking at what for a monstrosity is this Windows OS

swelling towards) that calls the CharLower() function.

3)   as soon as we have in memory our magic string, made

transforming the user name input, we can compare it with the

numbers inside the second inputted string. Should magic number

and magic string differ you beggar off.

Let's crack once more this program, this time we'll crack it

here, i.e. we'll seek a correct registration 'result'

substituting instruction
:0082.020F C70698460100   mov word ptr [4698], 1 ;beggar off!

with instruction

:0082.020F C70698460000   mov word ptr [4698], 0 ;OK, nice sucker
[REDIRECTION] (First elements of)

The above crack solves location [4698], but that is not enough:

WE MUST ALSO MODIFY THE AX FLAG... remember: each routine jumps

back with a flag (mostly in ax) upon which the calling routine

reacts... therefore we must also modify following piece of code:

:0082.0215 33C0           xor ax, ax       ;flag ax=0

in order to substitute it with

:0082.0215 B80100         mov ax,1         ;flag ax=1

But, alas, this crack is a 3 bytes instructions! The original

instruction was only two bytes long! How should we crack?

Independently from the fact that actually there are 2 bytes

instructions that do indeed perform the abovementioned flagging,

I'll teach you here, a simple 'redirection', a method that you'll

use a lot for higher cracking when we will 'patch'

applications... Yeah! Time to leave the ONE BYTE FOR ONE

BYTE petty and miserable cracking, time to insert whole new

PIECES OF OUR code inside the applications we crack... what about

having -somewhere inside a cracked Word for Windows- the string

'Warning: Microsoft can damage your health'? :=)

     You'll learn pretty complicate 'patching' redirection

techniques in my +HCU, for now, let's just understand the

fundament of this method here: the very short block of code we

need to crack inside our target was originally this one:

:0082.0204 C70698460000   mov word ptr [4698], 0 ;good guy!

:0082.020A B80100         mov ax, 0001         ;flag ax=1, OK

:0082.020D EB0A           jmp 0219             ;continue

:0082.020F C70698460100   mov word ptr [4698], 1 ;beggar off!

:0082.0215 33C0           xor ax, ax           ;flag ax=0

:0082.0217 EBF4           jmp 020D             ;NO GOOD, continue

     What about cracking the LAST instruction? Let's see... the

code jumps back FF-F4 bytes (218-(FF-F4))=20d i.e. back to

:0082.020d which is 'continue' (in this case after having being

badflagged).

     Well, what 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"







 



E-mail +ORC





+ORC na526164@anon.penet.fi