+ORC Tutorials


Lesson 9 (4): How to crack Windows, Hands on
'Dead listing' approach - second part

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
     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,
     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
This application is

     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!
: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
     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

: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):
: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
: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

: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
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):
: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
: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.
: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
: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
Look! Our listing does not seem to report any :0082.0394 routine
at all!
: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:
 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.
: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
: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]
: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:
: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
: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-
     Now that you (begin to) understand re-direction cracking,
you are ready to step over to 'real' higher cracks: what we call

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

+ORC contents