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


          LESSON 9 (2) -  How to Wincrack, Hands on 
     Nagscreens galore: The Paint Shop Pro crack (part A)

Merry Xmas. We'll learn, beginning with this lesson, how to
eliminate the "nagscreens", i.e. the protection and or annoying
schemes that many commercial and shareware windows programs use
in order to annoy us and push lusers to buy them.
In order to understand (simple) nag screen deprotection we'll
crack following different approaches Paint Shop Pro, the de facto
standard used to day for graphic manipulation. It's a good
choice, I believe, because
- it's a very widespread application: 
     you'll surely have some copies of it on your CD-ROMs, and
     you'll find many copies on the Web (albeit not cracked ones
     until now: the only cracks I am aware of are patches that
     simulate the user clicking on the OK button of the
     nagscreen, thus closing it, but not eliminating it).
- this application has many older versions:
     I want to teach you here also a "general" approach strategy
     that you should often follow when (and if) you'll start
     higher cracking: the *very* important study of the
     "embryology" of the software you want to crack. The long
     history trail of the "ancient" copies of your target will
     help you a lot to understand its evolution and the parallel
     evolution of its protection scheme ("Historia lux
     veritatis... magistra vitae", hope you did not forget your
     Cicero :=)
The case of the nagscreen evolution of PSP is particularly
1) static nagscreen      ;1993, Ver. 2.0, PSP.EXE = 525.520 bytes
2) daycount added        ;1994, Ver. 3.0, 861.856 bytes
3) delayed OK focus      ;1995, Ver. 3.2-32, 1.042.944 bytes
4) ported to Win95       ;1996, Ver. 4.1, 1.151.488 bytes
In the meantime many functions have been added to the program
whose size has broken all limits.
Let's begin our crack with the oldest copy of Paint Shop Pro i
could find: I want to stress that knowledge of history is very
important (there should be a faculty of "software history" in all
great universities, there will be of course one in my +HCU). 
I'll use the old SHAREWARE version 2.01, whose file PSP.EXE has
a length of 525520 bytes and is dated 15 november 1993.
Just to make a comparison, version 3.0 has a PSP.EXE file of
861856 bytes, and is dated 4 march 1995, version 3.12-32 (Win31)
has a PSP.EXE length of 1.042.944 bytes, and is dated 27 december
1995 and version 4.1 for windows 95 has a PSP.EXE with much too
many bytes which is dated 1 september 1996: a classical example
of overbloated programming language involution.
Version after version JASC incorporated added the "counter" that
reminds you how many days you have been using this program,
telling you to register it after 30 days. This nagscreen is by
far and large not particularly annoying, JASC has been pretty
correct (compared with other nagscreens used by less interesting
but more preposterous software). Nevertheless we do not like
nagscreens all the same, coz we want to enjoy all programs,
commercial or not, without paying any money at all and without
silly nagscreens or reminders of any sort (all sort of goods
should be free in my opinion, not only software: I think I am a
sort of "aristocratic communist": I believe that private property
is a theft -of course- and that everybody should have -at least-
a sail Yacht, good books, a lot of caviar and good Wodka-Martinis
in crystal glasses without paying anything at all: all this
should be completely free in order to allow each one to
concentrate on interesting activities like wind watching, poetry,
micro-ethology, study of the colours, cracking, ancient rhetoric
et cetera). 
Anyway, in this old PSP, version 2.01, there was in the nagscreen
no day counter yet ("you are on day xx of your 30 days..."), a
"static" nagscreen, the whole program is still very "basic",
nobody would have said, looking at this midget, that Jasc could
have evolved this embryo of a program, in three years, in the de-
facto standard graphic manipulation program that we know to day
(december 1996).
Let's crack: We fire our Winice (I will not explain any more why
you should use Winice: buy (or codebar) a "real" copy of it or
else find all three cracked copies, DOS, WIN31 and WIN95, on the
Web. Then learn how to use it well: this tool is the alpha and
omega of cracking... I am using for this lesson a Windows 3.1
computer with my Winice for Windows 3.1, version 1.3, cracked by
the ubiquitous Marquis de Soiree).
We begin now, Winice lurks already behind Windows, Microsoft
abomination has already been started, a cool breeze blows
outside, I fire PSP 2.1.
We'll use in this lesson a couple of different approaches to code
pinpointing: you'll remember that we could have done our three
steps basic approach, as usual (always working, but at times
slower or more inaccurate than other approaches): 
3)bmsg relevant_window wm_gettext 
sequence of commands, as follows
TaskName    SS:SP   StTop StBot StLow TaskDB hQueue    Events
PROGMAN   1727:200A 0936  2070  1426  066F   07F7      0000
PSP     * 1D27:D826 9654  D9BE  D132  11EF   11D7      0000 

:hwnd psp
Window Handle  hQueue    QOwner Class Name   Window Procedure
0EB4(0)        11D7      PSP    #32769       04A7:9E6B
 25B8(1)       11D7      PSP    Histogram    1197:07E8
 2090(1)       11D7      PSP    #32770       1D07:120E
  20F0(2)      11D7      PSP    Static       1D07:38A6
  2138(2)      11D7      PSP    Static       1D07:38A6
  2180(2)      11D7      PSP    Static       1D07:38A6
  21D8(2)      11D7      PSP    Static       1D07:38A6
  2230(2)      11D7      PSP    Static       1D07:38A6
  2298(2)      11D7      PSP    Static       1D07:38A6
  22F0(2)      11D7      PSP    Button       1D07:2876
  2344(2)      11D7      PSP    Button       1D07:2876
  2398(2)      11D7      PSP    Static       1D07:38A6
  23F0(2)      11D7      PSP    Static       1D07:38A6
  2448(2)      11D7      PSP    Static       1D07:38A6
  24A0(2)      11D7      PSP    Static       1D07:38A6
... (and more handles, the segment numbers may obviously differ
from yours)

Since the two "buttons" are the OK and CANCEL buttons inside the
nag screen, we can immediately pinpoint the code with a 
:bmsg 22F0 wm_gettext

command, which would fire back winice as soon as we click the OK
button. You'll please also notice from the hwnd list above that
the window #32770 has 6 small "text" windows inside and two
buttons, that the window procedure for the main nag window is at
1D07:120E, the procedures for text are at 1D07:38A6 and the
procedures for the buttons are at 1D07:2876.

We'll come back on this approach later. It's the typical
pinpointing used for password protection schemes, as we have seen
in the password lessons, but this approach is NOT the best one
for nagscreens. 
Let's follow now another approach: let's find the nagstrings in
the parts of PSP that contains DATA (as opposed to CODE), the
:heap command will help us: it's the standard command to
understand the STRUCTURE in memory of your deployed applications,
you'll use it a lot for nagscreen cracking and for time limits

:heap psp           ; we know from :task that the name is "PSP"
Han./Sel       Address   Length    Owner     Type      Seg/Rsrc
1C37           00027980  00000040  PSP       Alloc     
0876           000279C0  00000020  PSP       Resource  IconGrp
1FFE           806EC760  000010A0  PSP       Code      03
1BA6 LH        806B2000  0000E9E0  PSP       Data      90
2016           807CC340  00003C60  PSP       Code      01
200E           80774780  00002940  PSP       Code      02
... (many more handles)

As you can see doing your listing, there is only one data block, 
E9E0 bytes long, at 806B2000. Have a look at the code blocks,
though, many of them, as you'll see, have a little "D" after the
type CODE, as you'll use often and often this :heap command to
crack protection schemes in the future, you may as well learn 
right now that these are (most of the time) uninteresting for 
cracking purposes.

If we now pinpoint this code with a bpr RW on part of the text
that the nagscreen displays, we'll land in the middle of the
routine that copies this text in various memory locations, each
time PSP runs:

:bpr 30:806B2150 30:806B2170 RW

Let's start PSP once more and we'll land here inside winice:
011F:00007A1B  D1E9           SHR CX,1
011F:00007A1D  F366A5         REPZ MOVSD ;this writes in 806B1250
011F:00007A20  8BC8           MOV CX,AX
011F:00007A22  83E103         AND CX,+03
011F:00007A25  F3A4           REPZ MOVSB

Hope that my readers DO remember that REPZ is repeat string
manipulation until cx=0 and that MOVSD moves strings by
doublewords, from ds:si to es:di, updating si and di.
We are here in the piece of the main windows KERNEL module,
responsible for setting up this part of PSP.
Now things start getting interesting: if you make a search for
the string 'freeware' (contained in the nagscreen of PSP) before
loading psp you'll get as location only the echoes of your own
search string:
:s 30:0 lffffffff 'freeware'
Pattern found at 0030:007DBA58
If you search the same string after the KERNEL's has finished
copying around PSP code (as we saw above) you'll fetch quite a
lot of locations:
:s 30:0 lffffffff 'freeware'
Pattern found at 0030:0066242D
                 0030:007DBA58  ;echo
                 0030:008E107F  ;echo
                 0030:008E1867  ;echo
                 0030:008E601A  ;echo

The last one is the more interesting one, being above 80000000.
But, hey, how comes that the 'freeware' text occurrence at
30:806B2170 (the one we breakpointed into) has not been found?
It's an interesting point, and you could now obviously bpr RW all
the relevant locations to trace backward to the "culprit" code
section of PSP, the one setting up the nagscreen that we want to
But we'll now leave even this second approach and follow a third
and better one for nagscreen deprotection: the "stack_crack"
technique (I want to show you the MANY possibilities that we have
for cracking these programs.

As everybody (should) know, every time a child window (or a pop-
up window) is created, the function that must be invoked is 
HWND CreateWindow, which is called by virtually all windows
programs. This function specifies the window's class, title and
style, and may also determine the window's initial screen
location and size. This function returns the handle to the newly
created window. It's a general purpose API function with this
HWND CreateWindow(LPCSTR lpszClassName, LPCSTR lpszWindowName,
                  DWORD dwStyle, int iX, int iY, int iWidth,
                  int iHeight, HWND hPArent, HMENU hMenu,
                  HINSTANCE hINst, void FAR *lpvData)
And, for those of you that do not know nothing, lpszClassNAme
points to a character string naming the window's class and
lpszWindowName points to a character string identifying the
window by name, which is pretty useful for us little crackers...
you should study a little this kind of stuff, just to make an
example, do you know that EDIT Class control style ES_PASSWORD
displays all typed characters as asterisk symbols? (Whereby
setting EM_SETPASSWORDCHAR to zero will print the password echo
on the display, but this is stuff for another lesson :=)

Let's work with the breakpoint on the CreateWindow function we
have seen above, obviously, now that you know all the parameters,
you could as well change the position of the nagscreen (iX, iY,
iWidth...) instead of removing it.
:bpx CreateWindow
And now let's fire PSP, look at the screen! We pop in winice 5
times before the relevant moment (i.e. just before the
nagscreen). Therefore we change our breakpoint, setting the
occurrence "6" for the counter:
Now we fire PSP once more and this time we look at the stack as
soon as we pop inside Winice, because we know that the last
CreateWindow has created the nagscreen and we want to know where
is the "culprit" section of PSP code:
PSP(05) at 1EF7:00AF [?] through 1EF7:00AF
PSP(05) at 1EF7:1094 [?] through 1EF7:1076
PSP(01) at 1F3F:0598 [?] through 1F3F:0000
PSP(8A) at 1F0F:0024 [?] through 1F0F:0000
USER(19) at 073F:099B [?] through USER!DIALOGBOX
USER(19) at 073F:0A31 [?] through 073F:09A3
USER(19) at 073F:07FC [?] through 073F:0737
PSP(01) at 1F3F:0BC0 [?] through 1F3F:0BC0
PSP(02) at 1F2F:0DF7 [?] through 1F2F:0000
=> USER!CREATEWINDOW at 06B7:0F1B [?] through 1EBF:0052

That's nice music for us! Let's have a deep look at these pretty
data: See! The last CreateWindow occurrence is called by Segment
02 of the PSP code (you remember the :heap PSP command listing,
we made for the first approach, if not do it now: the heap
listing will show you the complete structure in memory of your

and yes, let's have a look at segment 2, the locations around
DF7: here the relevant section of code:
1F2F:00000DEB  90             NOP
1F2F:00000DEC  687A70         PUSH 707A
1F2F:00000DEF  FF36068F       PUSH WORD PTR [8F06]
1F2F:00000DF3  FF36FC70       PUSH WORD PTR [70FC]
1F2F:00000DF7  9A5200BF1E     CALL 1EBF:0052 ;call the bazaar
Following this last call, we land in the USER(19) code section
of windows USER module, which sets up a child window (in this
case the nag screen) and then waits for user's mouse clicks. 

073F:0000083E  56             PUSH SI   
073F:0000083F  6A01           PUSH 01
073F:00000841  9AF20BE706     CALL 06E7:0BF2 ;makes the nagframe
073F:00000846  56             PUSH SI
073F:00000847  9A0444A704     CALL 04A7:4404 ;writes the nagtext
073F:0000084C  3936E200       CMP  [00E2],SI

But USER should obviously not be cracked (well, you could, but
not here... see the lesson about windows "guts": KERNEL, USER and
GDI and the possibilities you get cracking them directly), but
here our culprit protection scheme must of course dwell inside
the PSP code... therefore let's now have another look at the task
list we found breakpointing on CreateWindow.
All the three user(19) codes are USER module's routines, let's
see... where should we cut mustard with our crack? Obviously
BEFORE the call to USER(19), also either in PSP(8A), or in
PSP(01) or in PSP(05).
Three possibilities:
1) Study a disassembled listing.
A nice disassembly listing can be very helpful for our cracks
(through good old WCB or through WDASM, cracked copies of all
these nice disassemblers are on the Web). Useless an d tedious
in this case.
2) Have a direct look. 
There are in this case only three sections of code, just have a
look at them and find in which one triggers the protection.
Useless an d tedious in this case.

3) -Always better- use a little zen.
Relax, sip a Martini-Wodka (be careful: only Moskowskaja will do,
do not exceed the correct amount of Schweppes' indian tonic) and
look once more at the :heap PSP listing. See? Segment 8A of PSP
code is only A0 bytes long, therefore pretty unlikely to yield
a protection scheme.
That leaves segments 05 and 01.
Segment 05 does not have enough "run" to hyde a protection scheme
(yes, this is zen): as you can recall from our stack listing, the
two occurrence of segment 05 have only a zero run (AF-AF) or a
very short one (76-94).
See? Out of the three sections we started with remains only one:
code section 01, which is 3C60 bytes long, has sufficient "run"
(0-598) and will therefore -for sure- hide inside the protection
scheme. Well, 3C60 bytes is quite a long piece of code to examine
(even if we started with more than half a million bytes in the
first place)... but we do not need to look much around, the
protection will be not far away from our call (for reasons I'll
not delve inside here... remember lesson C3 ?). We'll have a look
at fifty bytes, and having to sieve less than 100 bytes do not
seem to me to represent an unreasonable amount of work in order
to eliminate a nagscreen, nicht wahr?
Let's have a look at the code in segment 1, examining -say- 50
bytes around the locations at segment PSP(01), all info we found
using Winice's :heap command:
          PSP(01) at 1F3F:0598 [?] through 1F97:0000
Here the code -through Winice- with my comments:
1F3F:0000056D  0BC0           OR   AX,AX      ;conditional
1F3F:0000056F  740D           JZ   057E       ;jump, if not
1F3F:00000571  9AA802BF10     CALL 10BF:02A8  ;this chooses
1F3F:00000576  50             PUSH AX         ;the hWnd which
1F3F:00000577  6A04           PUSH 04         ;04=activates
1F3F:00000579  9A3E10E706     CALL USER!SHOWWINDOW ;herein
1F3F:0000057E  A1FC70         MOV  AX, [70FC] ;now load AX
1F3F:00000581  A30C6F         MOV  [6F0C],AX  ;save a copy
1F3F:00000584  C706FC700000   MOV  WORD PTR [70FC],0000 ;clean
1F3F:0000058A  682711         PUSH 1127       ;and load the other
1F3F:0000058D  686601         PUSH 0166       ;parameters for the
1F3F:00000590  686B0A         PUSH 0A6B       ;call, which are
1F3F:00000593  FF36068F       PUSH WORD PTR [70FC] ;all pushed
1F3F:00000597  50             PUSH AX         ;on the stack for
1F3F:00000598  9A00005F11     CALL 115F:0000  ;this final call
1F3F:0000059D  83C40A         ADD  SP,+0A     ;Now it's
1F3F:000005A0  0BC0           OR   AX,AX      ;finished
Well, what do we have here? We have the whole nagscreen procedure
at a glance: The call to USER!SHOWWINDOW is a BOOL ShowWindow
(HWND hWnd, int iVisFlag) function, which determines the
specified window's visibility state. hWnd is the handle of the
window and iVisFlag determines how the window is shown. 
This function returns true if the window is already visible,
false if the window was hidden. iVisFlag can be one of
the SW_ constants, number 4 is activate and display.
The program fetches at the previous call the AX parameter and
then calls the routine that prepares the nagscreen. 
OK, we found it (was pretty easy, as you saw). Now, how do we
crack this? There are one hundred thousand ways (an elegant one
would be changing the iVisFlag option).
I would suggest something rock solid: putting a JNZ 059D at line
1F3F:0000056D, replacing the JZ 057E on a "two for two" bytes
basis, a clean crack. 
And loo! It works flawlessly: we fly over the nagscreen. 
Here is the crack with good old symdeb... you may use symdeb but
you may obviously use more "modern" hexeditors, like PSedit (good
old DOS) or Hexworkshop (bloated Windows), you'll find everything
on the Web:
*** cracking PSP 2.1 nagscreen *** by +ORC *** dec 1996 ***
ren psp.exe psp.ded      ;need a "dead" copy for old symdeb
symdeb psp.ded           ;good old symdeb launched
- s (cs+0000):0 Lffff 0B C0 74 0D 9A ;search 1F3F:0000056D etc
xxxx:yyyy                            ;result from debug
- e xxxx:yyyy+2 75                   ;change JZ in JNZ
- e xxxx:yyyy+3 2C                   ;jump after final call
- w                                  ;write back our changes
- q                                  ;bye symdeb
ren psp.ded psp.exe                  ;ok, cracked, restore exe
***** see how easy? ******************************************

But we are not finished yet! Let's now come to the real content
of this lesson: how you should apply what you have learned on an
OLDER copy of the target software to the newer versions of it.
We'll crack now PSP, version 3.0, where the psp.exe file is
861.856 bytes long, this copy dates 4 march 1995, 2 *YEARS* after
the older one, it's a newer and improved program, with a lot of
Now, you would think that we must start anew, breakpointing with
a :bpx CreateWindow C=07 (in this case) command? No. They changed
a little the routines (here you would be advised to use a :bpx
ShowWindow breakpoint following the same approach). The new
nagscreen has been coupled with a daycounter, that reminds your
guilty as the days goes by, but the nagscreen schema has not
changed much: it has been hidden this time in Segment PSP30(07),
and you would find it -of course- following the abovementioned
approach, but what's the point? there is a much quicker way!
I'll never repeat it enough: PROTECTIONISTS ARE STUPID! As usual
with people working for money instead than for pleasure, their
capacity is severely limited, one of the ugly consequences of the
abominable society we are coerced to live in. This overvbloated
monstrosity, PSP30, is nagscreened with the SAME simple schema
used in the older versions, therefore you just search and modify
it using the SAME patterns (and in the same way) as before!
We'll use now PSEDIT in order to modify this file, is
a good tool, but has memory problems when the programs exceed
600.000 bytes (at the times symdeb was made people knew how to
code in assembler and nobody would have ever thought that you
needed so much to perform so little).
**** Cracking PSP version 3.0, by +ORC *** December 1996
ren psp.exe psp.ded ;always good, even if psedit does not care
psedit psp.ded      ;fire your tool
- use F8 (search) to search for hexstring 0BC0740D9A
You'll find three occurrences of it. Looking at the code you'll
immediately realize that the only good one is the third one. Just
modify the JZ 0D sequence in a JNZ 2D sequence (yes one byte more
than in the previous crack, look at the code) and you'll have
done your crack.
F2                  ;quit PSEDIT
ren psp.ded psp.exe ;restore exe
**************** pretty easy, wasn't it? ***********************

A little digression: Why do we search for the hexstring 
and not for a longer string? You may think that a longer search
string would have immediatly given us the correct location, and
you may see no point in using a shorter string, which may
obviously give us many more useless hits. You would be dead
wrong: one byte more (after 9A) and you would not fetch anything
at all!
The problem, for those of you that do not know nothing, is that
same hexcodes are RELOCATED each time an EXE program compiles in
memory (this was true for DOS, for windows there is a real
relocation galore going on behind the scene, one wonders at times
that windows get something accomplished at all, given the huge
amount of relocations that this overbloated pseudo-OS pushes
Choosing a search hexstring you must always be *very* careful:
choose search patterns that DO NOT relocate in memory, like OR
AX,AX, JZ fixed length, ADD SP,+0C, JL fixed length and so on.
Your searches for hexstrings that do relocate will not harvest
anything at all. Never. HAve a good look at the following code
examples, you'll recognize immediately that only the third (and
last) occurrence of our search string is the correct one: it is
the only one that shows "later on" shows the correct instruction
sequence (the later three moves and five PUSHES we have seen in
the listing for PSP 2.1 above).
Let's have a look at the three occurrences of our search string
inside PSP30:
Occurrence 1 of search string 0BC0740D9A inside PSP30:
1CEF:0000B8E3  0BC0           OR   AX,AX ;checks previous call
1CEF:0000B8E5  740D           JZ   B8F4  ;it's zero, forget show
1CEF:0000B8E7  9AE413671C     CALL 1C67:13E4 ;new call to fetch
1CEF:0000B8EC  50             PUSH AX    ;the hWnd for show
1CEF:0000B8ED  6A04           PUSH 04    ;activate
1CEF:0000B8EF  9A3E10E706     CALL USER!SHOWWINDOW ;herein
1CEF:0000B8F4  FF363E46       PUSH WORD PTR [46E3] ;fetch hWnd
1CEF:0000B8F8  9A2D19A704     CALL USER!ISICONIC   ;is iconic?
1CEF:0000B8FD  0BC0           OR   AX,AX     ;check if zero
1CEF:0000B8FF  7537           JNZ  B938      ;it's iconic!
Here you see that after our search string "0BC0740D9A" follows
a "E4" byte.
The function "IsIconic" has nothing to do with our protection
scheme. This function returns non zero if the specified windows
(pointer at location 46E3) is displayed in its iconic form, zero
if it is not. Well it's definitely NOT our protection scheme: we
should find (at least) three MOV instructions and four PUSHES
instructions (see PSP21) after our call to SHOWWINDOW, and our
protection scheme has nothing to do with any call to ISICONIC.

Let's have a look at occurrence 2 of our search string inside the
code of our PSP30 target:
Occurrence 2 of search string 0BC0740D9A:
1CEF:0000B927  0BC0           OR   AX,AX ;checks previous call
1CEF:0000B929  740D           JZ   B938  ;it's zero, forget show
1CEF:0000B92B  9A5817A71C     CALL 1CA7:1754 ;new call to fetch
1CEF:0000B930  50             PUSH AX    ;the hWnd for show
1CEF:0000B931  6A04           PUSH 04    ;activate
1CEF:0000B933  9A3E10E706     CALL USER!SHOWWINDOW ;herein
1CEF:0000B938  FF363E46       PUSH WORD PTR [46E3] ;fetch hWnd
1CEF:0000B93C  9A2D19A704     CALL USER!ISICONIC   ;is iconic?
1CEF:0000B941  0BC0           OR   AX,AX     ;check if zero
1CEF:0000B943  7537           JNZ  B97C      ;it's iconic!
Well, hey, no, we are not yet there... this is just a "mirror"
of the previous occurrence one! That means a complete repetition
of the same code of occurrence one... tehrefore the same as above
yelds true: it is not yet our protection scheme. Here you see
that after our search string "0BC0740D9A" follows a "58" byte.

Let's see the third (and last) occurrence of our search string:
1CEF:0000B96B  0BC0           OR   AX,AX ;checks previous call
1CEF:0000B96D  740D           JZ   B97C  ;it's zero, forget show
1CEF:0000B96F  9A1E958F1C     CALL 1C8F:951E ;new call to fetch
1CEF:0000B974  50             PUSH AX    ;the hWnd for show
1CEF:0000B975  6A04           PUSH 04    ;activate
1CEF:0000B977  9A3E10E706     CALL USER!SHOWWINDOW ;herein
1CEF:0000B97C  A13E46         MOV  AX,[463E]
1CEF:0000B97F  A33A3C         MOV  [3C3A],AX
1CEF:0000B982  C7063E460000   MOV  WORD PTR [46E3],0000
1CEF:0000B988  68EF1C         PUSH 1CEF
1CEF:0000B98B  687C21         PUSH 217C
1CEF:0000B98E  1E             PUSH DS
1CEF:0000B98F  680217         PUSH 1702
1CEF:0000B992  FF36105C       PUSH WORD PTR [5C10]
1CEF:0000B996  50             PUSH AX
1CEF:0000B997  9AA401271D     CALL 1D27:01A4 ;final call
1CEF:0000B99C  83C40C         ADD  SP, +0C ;resume
Here we are! This is obviously our protection scheme, see the
analogies (almost identities) with the older PSP21 nagscreen
protection we found and cracked above! In this third occurrence
you see that after our search string "0BC0740D9A" follows a "1E"
To defeat this protection along the same line of our previous
PSP21 crack, we could jump -here- to the 1CEF:0000B99C (resume
after final call) instruction, modifying the instruction at
1CEF:0000B96D (740D JZ B97C) -exactly as we did in PSP20- to a
nice JNZ B99C 75 2D (that's the distance between the location of
this very JNZ instruction and the location where you want to
jump, coz b99C-(b96D+2) = 2D. This crack requires a byte more (2D
instead of 2C) than in PSP21 to fly over the nagscreen calls, coz
an extra PUSH DS has been added inside this version's nagscreen
protection scheme (a reason more to be careful with "longer"
search strings: if you fetch too many occurences with a short
search string you just "cross check" the same occurrences with
another short search string from a later prortion of the code you
are trying to individuate: write a short program to do it
automatically for you: the best cracking tools, remember, are the
tools that you write yourself).
A last word, should you be interested in the "final call" of this
nagscreen scheme: it's a routine (here inside module PSP30(04)
which calls the two functions KERNEL!MAKEPROCINSTANCE (which must
be called for 16 bits Windows in order to effectuate a call to
Dialogbox) and USER!DIALOGBOX, which is (de facto) the nagscreen

Now let's go over to the last version of PAint Shop Pro for
Windows 3.1 I know of: PSP.EXE version 3.12-32, length: 1.042.944
bytes, 27 december 1995.
Let's bpx on CreateWindow and let's see... We fire PSP and we pop
inside Winice at the *only* occurrence of CreateWindow... MMM!
Something fishy here? When you proceed as above you get only one
break in Winice on bpx CreateWindow, and no stack at all, just
the CreateWindow call! You do not get no heap segments for PSP32
either... how comez?
The fact is, that in order to crack Win32 applications like this
one, we must move over to Winice95, coz Winice for Win3.1 has its
limits. You'll of course find Winice 95 on the Web, there are
always cracked copies roaming around, the best pages offer some
links to them, you should learn HOW TO SEARCH. You'll find
everything on the web for free, as a matter of fact. It's amazing
HOW MUCH you can get from internet, and this could make the Web
potentially dangerous from a "human-social" point of view... how
will we keep social and human contacts if we roam around so much
without ever touching each other? A good idea in order to
re-establish somehow our "humanity" "contact" balance is to seek
physical contact not only with your loved one (which is always
very good) but also with many other human beings: I have for
instance three massage sessions every week with my masseuse,
which is half my age but strong enough to cure my rheumatisms...
just to make another example, I enjoy very much all restaurants
which have the so called "tables d'hote" i.e. where everybody
sits together at a couple of long tables, me, my wife and my kids
exchanging views and opinions with other people, people you never
saw before and will probably never see again, drinking excellent
wines, instead of sitting grimly on the petty, bourgeois, "4
chairs" little tables for stupid greedy families that abound
inside "normal" restaurants... (I'll not ever mention the "fast
food" abominations: I am definitely in favour of "slow food" and
believe McDonald should be hanged for what he has done -in the
whole world- to 4000 years of gorgeous gastronomical
traditions... what's the point of eating quickly (and badly),
unless you are a slave of your time?)... enough: You could crack
Win32 applications even using Winice for Windows 3.1 though,
albeit slowly... you would have to go through Winice's VxD
command, and need a little zen and a deep understanding of
virtual memory management in Windows. Anyway, there is no point
in using wrong tools. Should you however try to crack Win32
applications with Winice 3.1, have a look first of all at the
modules inside windows as soon as winice pops up, using Winice's
command :mod... 
there you'll find the
hmod=1C3F W32SCXXXX      D:\PSP\PSP.EXE
Now :heap w32sxxxx in order to get the heap segments you need to
start your crack with. 
However, as I said, we better crack applications like this one
using Winice for Windows 95 and we'll see together -in the next
lesson- that the nagscreen of the 3.12-32 version AND the one
in the Windows 95 "4.1" version (the last one I know of) can both
be cracked pretty quickly on the same line as the previous ones. 
We will also see that the nagscreen mechanism -believe it or not-
is more or less always the same. The protectionists added a
"delayed" OK button focus and mixed some "alien" (but useful)
routines in-between. This said, it's still always the same soup,
as usual with nagscreens and mercantile programmers.

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 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 goddam 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