HOW TO CRACK, by +ORC, A TUTORIAL


Lesson 9 (3): How to crack Windows, Hands on
Nagscreens galore (B): The 'Dead listing' approach


[HEXWORKSHOP][PaintShopPro]


  

  (Hic sunt tabulae: Best viewed with good old Courier 10)



     In this lesson I'll teach you another cracking technique

known as "dead listing" approach, in opposition to the "live"

cracking (through Softice/Winice) that we have used (and we'll

use) most of the time.

     Since this approach requires a good Hexeditor and a good

disassembler (and a good Wordprocessor), it suits us well to

begin the 'hands on'  part cracking what we need: a good

Hexeditor.

     I'll crack here the nagscreens out of Hexworkshop, Version

2.10 (32 bit version). A good and relatively quick (for Windoze's

standards) application by Breakpoint software. Many among you

will already have this hexeditor inside their Software

collection, if not find it on the Web through an Archie search

and download it through ftpmail... searching through the archies

will give you something like this: 



Host ftp.loria.fr    (152.81.10.10)

Last updated 11:25 23 Oct 1996

Location: /pub1/pc/win95/programr

FILE -r--r--r-- 707906 bytes  02:00 13 Aug 1995 hworks32.zip



The exact NAME of this hexediting program is HWORKS32.EXE, it is

524288 bytes LONG, and its DATED 2 February 1996. This program

has many little nag annoyances:

-    shows a nagscreen reminding you how many days you have used

the program;

-    keeps a nag_string "unregistered version" on the main screen

of the program;

-    has, inside help, a "registration serial number form"...

this is the number you could get registering... and should digit

inside the HELP/ABOUT HEX WORKSHOP window form.



     Elsewhere in this tutorial we have already learned how to

defeat this type of protection: through Winice breakpoints.

Basically we would type a fake registration number (say

'121212121212') and then look for the occurrences of our string

in memory, and then search and investigate the manipulations

undertaken by the protection scheme. In this way we would finally

be able to crack the nagscreen procedure. 

     Fine, fine... this would indeed work, but I want to teach

you through this lesson ANOTHER, completely different approach

to cracking, which is and will be especially useful for

'nagscreen' and 'time-limit' cracking... i.e. the "dead listing"

approach. This approach is a much more "relaxed" sort of crack,

which  will work flawlessly most of the time. 

     This approach is particularly easy with Windows programs,

since -as I have already told you a hundred times- the modularity

of this overbloated atrocity makes it particularly easy for us

little crackers to track back the -mostly primitive- protection

methods utilized by the commercial programmers.

     I remember older times, when programming was still an art

for intelligent (not mercantile) beings, cracking the old (and

sometime beautifully crafted) Z-80, CP/M and DOS programs. In

those time 'a byte was a byte'! And good programmers found funny

tricks in order to write 'tight' code. We old crackers used the

'dead listing' approach sitting (or snoozing) in pleasant (albeit

a little battered) armchairs, inside a huge university library,

drinking very good Martini Wodka (you would be well advised to

use only Moskowskaja, coz non Russian Wodkas are repugnant). Four

of us at a time, each one just looking at his paper listings. You

cannot imagine how many little (unrelated) tricks we found inside

the code cracking in that way! A hacker, a cracker (me), a 'real'

programmer and an encryption specialist, all four sitting in the

same room, exchanging pretty clever findings and sipping (much

too many) good cocktails... it's long ago, those times (and

societies) are gone for ever! Microsoft's abomination has

unfortunately created this overbloated world of huge 'programs'

which perform more slowly (and much more awkwardly) what the old

programs did quickly and flawlessly.

     You don't believe me? Why don't you just install Linux on

your harddisk and see for yourself the difference between a good

OS and Windoze? Just try it... you'll be amazed and you'll never

go back... well, you'll actually do... only in order to crack the

hell out of Windows: We'll never damage enough Microsoft's

interests to compensate for this moronic situation: millions of

stupid users have to wait hours (and this with microprocessors

that are 1000 times quicker than the old 8086) to perform with

MS_Word -slowly- what they could have done immediately with an

old copy of Wordperfect for Dos. 

     Anyway, the huge dimension of all Windows' programs forces

us to abandon the printed "dead listing" approach... printing in

extenso the listing of a Windows program would consume a couple

of ink cartridges and could easily take ages... therefore we can

indeed still crack with the "dead listing" method, and we can

indeed still drink our Martinis (and we do, Oh Yessir), but we

must keep the overbloated listings off page, on our PC, printing

only the small part of them that are relevant to our crack.



     As I said at the beginning, for this art of cracking you'll

need basically only two programs (and you will NOT need

Softice/Winice).



1)        A disassembler like W32DASM (or another good one) in

order to find the protection scheme.

You will probably already possess it (else how did you crack

until now?)... if not find the last version on the Web -through

an Archie search- and download it -through ftpmail-, Searching

the archies will give you something like this:



Host ftp.funet.fi    (128.214.248.6)

Last updated 07:57  1 Jan 1997

Location: /pub/mirrors/ftp.cdrom.com/pub/simtelnet/win3/prog

FILE    -rwxrwxr-x  650327 bytes  23:25 28 Oct 1996  w32dasm6.zip



2)        An hexeditor (Use Hexworkshop version 2.10 itself,

since we are already cracking it :=) in order to defeat the

protection scheme as soon as you have found it. OK, enough, let's

crack.



Here is how the "dead listing" approach works:

1)   Run the program you want to crack, in this case Hexworkshop,

look at all the nag_strings and write them down (I mean snap them

down -automatically- from screen... see elsewhere in my tutorial

how to get and crack snap32);

2)   Wdasm the file (that means: 'open' it inside the

disassembler in order to get the listing).

3)   Transfer the listing to your favorite wordprocessor (we will

not need Wdasm any more, bye)

4)   Search (Find) inside your wordprocessor the nag_references,

say, in our case, the string "unregistered version"



You'll immediately land inside following piece of code:

:MAIN_NAG_ROUTINE

:00415732 CC              int 03

:00415733 CC              int 03

:00415734 CC              int 03

:00415735 CC              int 03

:00415736 CC              int 03

:00415737 CC              int 03

:00415738 CC              int 03

:00415739 CC              int 03

:0041573A CC              int 03

:0041573B CC              int 03

:0041573C CC              int 03

:0041573D CC              int 03

:0041573E CC              int 03

:0041573F CC              int 03

:00415740 55              push ebp

:00415741 8BEC            mov ebp, esp

:00415743 6AFF            push FFFFFFFF

:00415745 6873584100      push 00415873

:0041574A 64A100000000    mov eax, fs:[00000000]

:00415750 50              push eax

:00415751 64892500000000  mov fs:[00000000], esp

:00415758 81EC0C020000    sub esp, 0000020C

:0041575E 53              push ebx

:0041575F 56              push esi

:00415760 57              push edi

:00415761 898DE8FDFFFF    mov [ebp-00000218], ecx

:00415767 8B450C          mov eax, [ebp+0C]

:0041576A 50              push eax

:0041576B 6A73            push 00000073

:0041576D 8B8DE8FDFFFF    mov ecx, [ebp-00000218]

:00415773 E87EFC0100      call 004353F6

:00415778 C745FC00000000  mov [ebp-04], 00000000

:0041577F 8B8DE8FDFFFF    mov ecx, [ebp-00000218]

:00415785 83C144          add ecx, 00000044

:00415788 E84EF40100      call 00434BDB

:0041578D C645FC01        mov [ebp-04], 01

:00415791 8B85E8FDFFFF    mov eax, [ebp-00000218]

:00415797 C70028AE4500    mov dword ptr [eax], 0045AE28



*StringData Ref from Data Obj->"An unregistered version of Hex"

                             ->"Workshop has been on"

                            |

:0041579D 68085B4600      push 00465B08

:004157A2 8D85F4FDFFFF    lea eax, [ebp-0000020C]



Good, we immediately see that the above routine starts at

instruction

:00415740 55              push ebp

Therefore now we'll search our listing for following string:

call 00415740                 (that is: who calls here?).

The reason we must search for the caller is very simple: there

is no conditional jump inside the piece of code above... and

therefore it'll very unlikely hide a protection and/or a check

time or nag routine. If we do perform our search for the caller

we'll immediately land inside following routine: 



: CALL_NAG_ROUTINE

:00415DAC 55              push ebp          ;pusha lotta values

:00415DAD 8BEC            mov ebp, esp

:00415DAF 6AFF            push FFFFFFFF

:00415DB1 68045E4100      push 00415E04

:00415DB6 64A100000000    mov eax, fs:[00000000]

:00415DBC 50              push eax

:00415DBD 64892500000000  mov fs:[00000000], esp

:00415DC4 83EC54          sub esp, 00000054

:00415DC7 53              push ebx         

:00415DC8 56              push esi

:00415DC9 57              push edi

:00415DCA 894DA0          mov [ebp-60], ecx

:00415DCD 6A00            push 00000000

:00415DCF 8B4508          mov eax, [ebp+08]

:00415DD2 50              push eax

:00415DD3 8D4DA4          lea ecx, [ebp-5C]  ;for the call

:00415DD6 E865F9FFFF      call 00415740    ;*** HERE !!! ***

:00415DDB C745FC00000000  mov [ebp-04], 00000000

:00415DE2 8D4DA4          lea ecx, [ebp-5C]

:00415DE5 E804F70100      call 004354EE

:00415DEA C745FCFFFFFFFF  mov [ebp-04], FFFFFFFF

:00415DF1 E805000000      call 00415DFB

:00415DF6 E913000000      jmp 00415E0E

:00415DFB 8D4DA4          lea ecx, [ebp-5C]

:00415DFE E8FD000000      call 00415F00

:00415E03 C3              ret



Good, OK. Now -once more- who calls this function? As -here too-

we don't have any conditional jumps, we are compelled to look

further inside the green branches of our code_tree.

Let's go on: searching for

call 00415DAC       (the beginning of the above function)

we will land inside following code:



:WILL     _I_CALL_THE_CALL_NAG_ROUTINE_?

:0040254C 6808414500      push 00454108           

:00402551 8D8568FEFFFF    lea eax, [ebp-198]

:00402557 50              push eax

:00402558 E893460200      call 00426BF0

:0040255D 83C408          add esp, 8

:00402560 0FBF0508414500  movsx word ptr eax, [00454108]     

:00402567 85C0            test eax, eax

:00402569 0F8586000000    jne 004025F5  ;jump 1 over CALL_NAG

:0040256F 8B8D40FEFFFF    mov ecx, [ebp-1C0]

:00402575 E8D3350100      call 00415B4D

:0040257A 85C0            test eax, eax

:0040257C 0F841B000000    je 0040259D

:00402582 8B8D40FEFFFF    mov ecx, [ebp-1C0]

:00402588 E866360100      call 00415BF3

:0040258D 8B8D40FEFFFF    mov ecx, [ebp-1C0]

:00402593 E8DF360100      call 00415C77

:00402598 E953000000      jmp 004025F0  ;jump 2 over CALL_NAG

:0040259D 8B8D40FEFFFF    mov ecx, [ebp-1C0]

:004025A3 E83D370100      call 00415CE5 ;(month year routine)

:004025A8 898570FFFFFF    mov [ebp-90], eax

:004025AE 83BD70FFFFFF00  cmp dword ptr [ebp-90], 0

:004025B5 0F8417000000    je 004025D2    ;jump 3 over CALL_NAG

:004025BB 8B8570FFFFFF    mov eax, [ebp-90]

:004025C1 50              push eax

:004025C2 8B8D40FEFFFF    mov ecx, [ebp-1C0]

:004025C8 E8DF370100      call 00415DAC ;HERE! CALL_NAG! *

:004025CD E91E000000      jmp 004025F0

:004025D2 8D8D7CFFFFFF    lea ecx, [ebp-84];jump 3 lands here

:004025D8 E88C420200      call 00426869

:004025DD 85C0            test eax, eax

:004025DF 0F840B000000    je 004025F0

:004025E5 8D8D7CFFFFFF    lea ecx, [ebp-84]

:004025EB E8FE2E0300      call 004354EE

:004025F0 E91E000000      jmp 00402613     ;jump 2 lands here

:004025F5 8D8D7CFFFFFF    lea ecx, [ebp-84];jump 1 lands here

:004025FB E869420200      call 00426869



Now have a good look at the code above: As you can see there are

only three possible jumps which will NOT call the CALL_NAG

routine. The one at

:00402598 E953000000          jmp 004025F0 (Jump 2)         

is not conditional, and therefore very rarely used for nagscreens

protections. Besides, it links to another unconditional jump and

it's most probably a "Quick_out" way... let's eliminate it, at

least for now.

We remain with only two jumps over the NAG_SCREEN call routine:

00402569 0F8586000000         jne 004025F5 (jump 1)

and

004025B5 0F8417000000         je 004025D2      (jump 3)



     You may investigate both of them, but, hey, you could

eliminate one more jump, again, just using a little Zen code

feeling): see how the jump condition for jump_3 is a base pointer

value [ebp-90], while the one for jump_1 is a memory fixed

location [00454108]... this sort of condition is usually a green

light, for compiler reasons I'll not delve inside here. Therefore

let's have a closer look at it and let's forget jump 3, at least

for now.



:JUMP_1_UNDER_THE_LUPE

:0040254C 6808414500      push 00454108 ;values for         

:00402551 8D8568FEFFFF    lea eax, [ebp-198]

:00402557 50              push eax      ;the following

:00402558 E893460200      call 00426BF0 ;call

:0040255D 83C408          add esp, 8 ;modify stack

:00402560 0FBF0508414500  movsx word ptr eax, [00454108] ;HERE 

:00402567 85C0            test eax, eax ;conditional test

:00402569 0F8586000000    jne 004025F5  ;jump over CALL_NAG



What will then this mysterious [00454108] location be? Don't you

feel it? It's the ACTIVATOR! The location with the flag, which

sets the whole nag screen galore for Hexworkshop! Our cracking

job is already finished! 

     We don't need anything more: we don't need any fiddling with

breakpoints, nor to examine hundreds of irrelevant calls... with

Windows this kind of "dead listing" cracks works so smooth I

could shriek!

     But, hey, OK, we will continue our snooping, for the sake

of it and just in order to be completely sure... it's not

necessary, but let's do it anyway... check a little more

around... search, inside your huge listing, all the other

occurrences of the same [00454108] location... you'll get no more

than 5 hits. The most striking one from our cracking point of

view being the following occurrence:



:00402770 898574FFFFFF   mov [ebp-8C], eax ;save old eax

:00402776 0FBF0508414500 movsx word ptr eax, [00454108];FLAG*

:0040277D 85C0           test eax, eax     ;flag is zero?

:0040277F 0F8528000000   jne 004027AD    ;nope, so we won't

:00402785 8B4DEC         mov ecx, [ebp-14]             

:00402788 E883280000     call 00405010   ;call this, nor

:0040278D 898574FFFFFF   mov [ebp-8C], eax ;write



* Possible StringData Ref from Data Obj ->"Unregistered

Version"  

                     |

:00402793 6854494600    push 00464954   ;on the screen

:00402798 685C800000    push 0000805C   ;& we'll jump over

:0040279D 6800400000    push 00004000   ;these pushes

:004027A2 8B8D74FFFFFF  mov ecx, [ebp-8C]

:004027A8 E823280000    call 00404FD0   ;and this call



* Possible StringData Ref from Data Obj ->"ControlBars"

                  |

:004027AD 686C494600   push 0046496C     ;directly here



Well, yes, now it's more than enough, thanks... location

[00454108] seems indeed to be the flag we are searching.

Confirmed. Struck and sunk! Now let's quickly crack Hexworkshop:



*** CRACK FOR HEXWORKSHOP VERSION 2.10 by +ORC (January 1997) **

Use hexworkshop itself (no more debug/symdeb, coz we are working

with the overbloated Microsoft monstrosity) and search inside the

code of the copy on your harddisk for the hex sequence:

     08414500

that's the code for our flag_location, duh?



****(a short digression): BE CAREFUL SEARCHING FOR BYTES ***** 

Be careful with instructions you try to search for. You should

only search for instructions that don't change the bytes they

assemble to, depending on their location in memory. For example,

searching for the following instructions presents no problem:

PUSH      DX

POP       [DI+4]

ADD       AX, 100

but searching for the following instructions CAN cause

unpredictable results:

JE        123

CALL      MYFUNC

LOOP      100

**** (end) ********************************* **** **** ****



Searching for the byte sequence 08 41 45 00 you will obviously

find the several occurrences of it we have seen before... you

have to modify only one location though, the one followed by the

two bytes

0F85...  (jne after CALL_NAG)

at the FIFTH (and sixth) position after the search string,

because that's the location we are looking for.

Once you found it, write over the byte

85

the byte

84

and now you'll have modified the jne in a (je after CALL_NAG).

     We'll now jump if equal (as all men should be, by the

way)... Look!... no more nagscreens to annoy our proven aesthetic

perception, no more silly protections to blemish our suave future

hexediting around :=)

I almost forgot... that's obviously not enough... you must as

well modify the location at :0040277F



:0040277F 0F8528000000   jne 004027AD   ;jump over 'unregistered'

to

:0040277F 0F8428000000   je 004027AD    ;jump equal!



in order to have a well cracked copy of our target.



[PSP 32]

Can we apply this 'dead listing' approach to other programs? Can

we use the same strategies for other protection schemes?

Sure! Let's remain a little more inside the nagscreens

protections. 

     A logical step, after the invention of the nagscreen itself,

has been the "mingling" of the nagscreen calling routine. In this

kind of protection the nagscreen routines are 'amalgamated' with

other routines, which cannot be skipped as they are essential for

the working of the program. The main disadvantage of this

approach, for the mercantile protectionists, is that they have

therefore to prepare TWO different versions of their programs:

a 'nagscreened' one and a 'clean' one, since else we would

immediately be able to transform the crippled program in a fully

functional one using the same approach they would use to

'uncripple' it.

     Such mingling is therefore only used by major programs which

are well established on the market and can afford the 'doubled'

approach. This is the case of the last versions of PaintShopPro

(PSP).

     Even in this case, though, we can crack nice enough, as I

will now demonstrate you with PaintShopPro version 3.2 (a 32 bit

program for Windows 95).

     You will probably already possess it, if not find the last

version on the Web -through an Archie search- and download it

-through ftpmail-, Searching the archies will give you something

like this:



Host ftp.mds.mdh.se    (130.238.252.239)

Last updated 08:10  4 Dec 1996

Location: /pub/windows/win95/graphic_utils/paintshop

FILE  -rw-r--r--  311542 bytes  15:11 27 Jul 1996  psp32bit.zip



     We have seen in the preceding lesson (-> lesson 9.2) how to

disrupt, through the usual Winice 'live' approach, the

PaintShopPro nagscreens for Windows 3.1., cracking the older

versions of this program. Instead we will now try our 'dead

listing' approach for PSP 32 and PSP Version 4.1 (both 32 bit

programs).

     Let's fire PSP32 (I am using here the shareware version with

a PSP.EXE of 1.042.944 bytes, dated 27 December 1995). Let's have

a good look at the nagscreen (snapping it), OK, that's enough.

     Now load the target inside Wdasm32 (I am using here version

5 of Wdasm, you'll find cracked versions of it everywhere on the

Web).

     As soon as you have the complete (huge) listing of PSP.EXE

use the option "Save disassembly to text file"... you'll get a

huge text file (with 12.590.025 bytes, gosh). 

     Load it inside a (good and quick, i.e. not Microsoft's)

Wordprocessor and let's first of all have a look at the code

preceding and following our nagscreen (at this point -if you are

not completely imbecile- you should already have grasped the

foundation techniques of my "dead listing" cracking approach).

     You will see that in the code of PSP we have a lot of USER

calls. Therefore we cannot use the same easy 'find the caller'

approach used before (more about code mingling later).

     Have a look at the following piece of code (the Stringdata

for the Shareware notice has landed us there) there is a

GetDlgItem(), which is User32.EB and a EnableWindow(), which is

User32.AB.

     GetDlgItem(), as you should know, returns the handle of the

specified ID control (or zero if error). The ID number is the

parameter passed, the returned value is the hdlg (handle of the

dialog box of ID).



:0041DB69 891D38A04B00    mov [004BA038], ebx     ;ebx in here

**

:0041DB6F 6A6C             push 6C

:0041DB71 881DF4134C00    mov [004C13F4], bl      ;bl in here **

:0041DB77 56               push esi



* Reference To: GetDlgItem, Ord:00EBh in USER32.dll

                                |

:0041DB78 FF154C5A4C00    call dword ptr [004C5A4C]   ;callnag-1

:0041DB7E 50               push eax



* Reference To: EnableWindow, Ord:00ABh in USER32.dll ;callnag-2

                                |

:0041DB7F FF15DC594C00    call dword ptr [004C59DC]



*StringData Ref from Data Obj->"Paint Shop Pro Shareware Notice"

                           |

:0041DB85 6820174C00      push 004C1720

:0041DB8A 56              push esi



Now follow me closely:

1)   Since the following code pushes two locations (one with bx

and the other with bl) just before calling the  GetDlgItem and

EnableWindow routines for the "PaintShopPro Shareware Notice"

Window...

2)   ...we just need to search these locations ELSEWHERE,

"around" the above section of the code. Let's do it... Searching

the STRING "[004BA038]" we'll fetch inside our wordprocessed

listing two more occurrences: Let's look at the first one: this

piece of code compares to 1 our location just after enabling a

Window:



:REFERENCE_1_OF_OUR_[004BA038]

* Reference To: EnableWindow, Ord:00ABh in USER32.dll

                           |

:0041DA41 FF15DC594C00   call dword ptr [004C59DC]

:0041DA47 C605F4134C0002 mov byte ptr [004C13F4],2

:0041DA4E 833D38A04B0001 cmp dword ptr [004BA038],1 ;HERE!! **

:0041DA55 7510           jne 0041DA67 ;and the conditional jump!

:0041DA57 6A00           push 00000000 ;If equal (Zero flag), 

:0041DA59 6A6C           push 0000006C ;push these parameters 

:0041DA5B 6811010000     push 00000111 ;for the PostMessage

:0041DA60 56             push esi     ;function...



* Reference To: PostMessageA, Ord:01A3h in USER32.dll

                          |

:0041DA61 FF155C594C00   call dword ptr [004C595C] ;...call)

:0041DA67 B801000000     mov eax, 1        ;our jump here: flag=1

:0041DA6C E9EE030000     jmp 0041DE5F  ;end of code snippet, this



jumps to the "popping away" part of the code...

:0041DE5F 5D                  pop ebp

:0041DE60 5F                  pop edi

:0041DE61 5E                  pop esi

:0041DE62 5B                  pop ebx

:0041DE63 81C434050000        add esp, 00000534

:0041DE69 C21000              ret 0010



     AhHa! The value 111! (at :0041DA5B). You know what that

means, don't you? For the newbyes among you that don't, learn it

here (the others can skip): 

************ THE 111 WM_COMMAND RELEVANCE, by +ORC ********

The function PostMessage() has following structure:

PostMessage(HWND hWnd, UINT uMsg, WPARAM wMsgParam1, LPARAM

lMsgParam2)Where hWnd is the receiving Window, UINT is TRUE or

FALSE WPARAM is a 16 bit value and LPARAM a 32 bit one! 

Windows' applications use PostMessage() to deliver WM_Message

requests... and parameter 111 is WM_COMMAND!

Write it on your cracking notes and underline it! 1 is IDOK, 2

is IDCANCEL and 111 is WM_COMMAND.

     WM_COMMAND is extremely important for understanding the

behaviour of the application you want to crack, because the

handler for WM_COMMAND is where that application deals with user

commands, such as menu selctions, dialog push button clicks,

etcetera. In other words all what makes the 'guts' of an

application.

     An application can tell wich command a user gives through

the wParam parameter to the WM_COMMAND message.

     These values are (almost) always part of the application's

menu resources, and it is easy to get the menu ID values through

any utility for resources dumping.

************ (end) **************

     OK, so the above listed piece of code has a jump over the

PostMessage routine which (probably) disables the nag screen (6C

is the same ID, for both pieces of code we have seen)...let's try

a "weak" crack on it:



***** WEAK CRACK FOR PSP32, by +ORC, January 1997 ********



1)   Use Hexworks32

2)   Load PSP.EXE

3)   Search for the bytes sequences of the instructions

:0041DA4E 833D38A04B0001      cmp dword ptr [004BA038],1    

:0041DA55 7510                jne 0041DA67   

which are followed by the pushes:

:0041DA57 6A00                push 00000000 ;zero

:0041DA59 6A6C                push 0000006C ;ID

:0041DA5B 6811010000          push 00000111 ;WM_COMMAND



And as a quick crack (but there are more elegant ways) we can

4) substitute the byte '75' at :0041DA55 with a 74, transforming

the jne in a je, as usual, inverting the jumps. Jump if equal!



Since I have been (blandly) critized by fellow scholars for

speaking all the time of more elegant ways and yet presenting

only simple ways, here IS a more elegant crack for this code:



4)   Substitute with a new ONE the first TWO instructions:

:0041DA4E 66C70538A04B000100   mov word ptr [004BA038],1

and leave all the rest unchanged:

:0041DA57 6A00                push 00000000 ;zero

:0041DA59 6A6C                push 0000006C ;ID

:0041DA5B 6811010000          push 00000111 ;WM_COMMAND

*****************************

As you can see, we have just moved the flag '1' inside our

location, instead of comparing and jumping away as in the

original code and in the quickly cracked one. Estilo muchissimo

elegante.



Since this lesson was thought as +HCU material, here is the

result of the work on it made by (some of) my students:



JANUARY 1997: THIS PART OF LESSON 9.3 HAS BEEN MODIFIED (OR

ADDED) BY THE +HCU STUDENTS OF UNIT 4



 Let's finish our cracking of the nagscreens of the

whole PaintShopPro family with version 4.1, which is the most

recentwe know of. 

I am using here PSP.EXE 1.151.488 bytes from 1 Sep 1996, fetch

it through the archies.

We will crack this shareware program BETTER than the registered

version, since we will completely eliminate any nagscreen and

we'll not ever have the welcome screen that REMAINS inside the

registered version. We'll do this 'in a hurry', since it is not

+ORC speaking, but some of his students... you already know

enough about the 'dead listing' method to be able to follow. No

Winice in our hands, Ladies and Gentleman, We never used it on

this program. (Well... we actually did, before reading 9.3, but

it brought us nowhere, for this crack we (almost) DID NOT,

following +his instructions)

1) Get the 'dead listing' of psp.exe (it's huge)

2) Load it inside a fast wordprocessor

3) Find the string 'Purchasing' at :00406710

4) short after 'Purchasing' the only location compared and loaded

is location [004BC218]. Let's call it 'BINGO' and let's hope

it'll work.

5) this location is handled inside a small part of the code

:00406290 to :004067B5, this reduces the more than one million

bytes to 1317 bytes we'll have to examine, not bad.

6) Let's print this nagging part of the code and let's feel it

a little

7) Let's see the possible cracks we could think of (we repeat,

here is not +ORC's but his students at work, we are not perfect).

You'll see this piece of code

:FIRST_ATTEMPT (NOT SO GOOD)

:004065D0 50                  push eax

:004065D1 64892500000000      mov fs:[00000000], esp

:004065D8 81ECB4000000        sub esp, 000000B4

:004065DE 833D18C24B0000      cmp dword ptr [004BC218], 0 ;Is

BINGO zero?

:004065E5 56                  push esi

:004065E6 57                  push edi

:004065E7 0F85A0010000        jne 0040678D ;not really

this is 'pentium optimised' code, with a couple of pushes

'inside' the two logically consecutive instructions following the

double 80586 fetching... on a 80486 you would have had:

push esi; push edi; cmp dword ptr [004BC218], 0; jne 0040678D

We may just try substituting a 0F84 at :004065E7 (that is a jump

equal instead of the jne) and BOUM! We get an 'inamovible'

nagscreen, No way to click it away, it covers the main program

PaintShopPro for the eternity. This confirms that we are on the

right track (it's a green light). Uncrack the code (or reload the

original nagged program). Now look here:

:SECOND_ATTEMPT (NOT SO GOOD)

:00406495 E95AEA0900         jmp 004A4EF4

:0040649A 33F6               xor esi, esi

:0040649C C745FCFFFFFFFF     mov [ebp-04], FFFFFFFF

:004064A3 893518C24B00       mov [004BC218], esi ;load esi in

BINGO

Since :00406495 jumps away, it would be interesting to know who

the cuckoos lands at :0040649A. You'll quickly discover that

there are two jumps in this area. One 'xores' the esi before

loading it in our location, the other one does not:

:0040641C 747C       je 0040649A        ;xores esi

:0040646F EB2B       jmp 0040649C  ;does not xore esi

So you may be tempted to try 'áa passe ou áa casse' following

cracks:

:0040641C 747E       je 0040649C  ;no xoring even if it should

(THIS DOES NOT CHANGE ANYTHING)

:0040646F EB19       jmp 0040649A ; xoring even if it should not

(THIS CRASHES)

Bad score: a frozen nagscreen, a nothing and a crash. Three to

zero for our enemies. Let's look a little more around our 1317

bytes listing.



Well, what else?

The following code refers THREE TIMES to our location, that's a

lot, let's hope it does not suck:

:THREE_SISTER_BINGOS

:00406547 33C0            xor eax, eax  ;xor

:00406549 85C0            test eax, eax ;test ax

:0040654B 7513            jne 00406560 ;don't move in cx

:0040654D 8B0D18C24B00 1! mov ecx, [004BC218] ;move in cx

:00406553 85C9            test ecx, ecx ;test cx

:00406555 7418            je 0040656F  ;don't call Updatewin

:00406557 6A01            push 1

:00406559 8B01            mov eax, [ecx] ;move cx in ax

:0040655B FF5004          call [eax+04]  ;and call here

:0040655E EB0F            jmp 0040656F   ;don't call Updatewin

:00406560 A118C24B00  2!  mov eax, [004BC218]  ;move in ax soon

:00406565 8B4820          mov ecx, [eax+20]

:00406568 51              push ecx

:00406569 FF15C4014C00 call dword ptr [004C01C4] ;call

Updatewindow

:0040656F 6A00            push 0

:00406571 A118C24B00  3!  mov eax, [004BC218]  ;move in ax later



Well, something fishy here, don't you feel it? Who comes in here?

From where? Let's have a GOOD look at the 'preamble', i.e. the

part of the code that 'switches' to our THREE_SISTER_BINGOS block

above:

:PREAMBLE_TO_THREE_SISTER_BINGOS

:004064DD FF15BCF24B00    call dword ptr [004BF2BC] ;check this

loc

:004064E3 85C0            test eax, eax       ;test

:004064E5 744E            je 00406535              ;zero, go 6535

:004064E7 B896000000      mov eax, 96              ;load par 96

:004064EC 3945E0          cmp [ebp-20], eax     ;compare this

:004064EF 7C44            jl 00406535              ;lower, go

6535

:004064F1 3945E4          cmp [ebp-1C], eax     ;compare that

:004064F4 7C3F            jl 00406535             ;lower, go 6535

:004064F6 8B4508          mov eax, [ebp+08]     ;load this

:004064F9 85C0            test eax, eax         ;test it

:004064FB 7504            jne 00406501          ;do not xor

and...

:004064FD 33C0            xor eax, eax          ;xor and

:004064FF EB03            jmp 00406504          ;do not

:00406501 8B4020          mov eax, [eax+20]     ;...load this

:00406504 6A00            push 0                ;push

:00406506 8B4DE0          mov ecx, [ebp-20]     ;load ecx

:00406509 6A00            push 0                  ;push



Let's have a look at the 6535 routine of the switch PREAMBLE:

:00406535 E836560100       call 0041BB70

and

:41BB70 A118C34B00         mov eax, [004BC318]

:41BB75 85C0               test eax, eax

:41BB77 7407               je 0041BB80

:41BB79 50                 push eax

:41BB7A FF1530F54B00       call dword ptr [004BF530] ;globalFree

:41BB80 C70518C34B00       mov dword ptr [004BC318], 0

:41BB8A C3                 ret



Well, let's try along, what happen if we substitute a ret at

:00406535?

:00406535 C390909090     ret and nops

Nothing at all.

And what if we substitute here

:004064F6 8B4508                  mov eax, [ebp+08]

:004064F9 85C0                    test eax, eax

:004064FB 7504                    jne 00406501

:004064FD 33C0                    xor eax, eax

:004064FF EB03                    jmp 00406504

:00406501 8B4020                  mov eax, [eax+20]

:00406504 6A00                    push 00000000

... the instruction

:004064FB 7504                    jne 00406501

with the instruction 7500 (or 90 90)?

MOST BRILLIANT!

Now we XOR ANYWAY THIS AX without caring for ax+20. The nagscreen

is defeated? Not really... the nagscreen has been passed ON THE

BACKGROUND, where it still remains when you shut the 'main'

window of the program... the nag protection is somewhere there,

looking at us square in the faces... but where?

+gthorne here: since i had already seen the production version

of paint shop pro, i realized that it also had a nag screen - not

per se, but a splash screen (the very same screen without the

buttons to push and the 'number of days elapsed' warning). what

this means is that it is very possible that the screen

(regardless of what version we are running) could be intermingled

with the rest of the code, and not fully existing within a 

call. This does not proved it, just allowed the possibility.



Poking around, and being playful, i fired up snap32 and grabbed

the nagscreen window and saved it for future reference.



The next thing i did was check into the help screen area of Paint

Shop Pro. Often in shareware programs there is a HELP ABOUT, or

a HELP REGISTER section. Sometimes those places give away good

info needed (or just plain useful) in the crack routine.



Something that stood out in the help area was the paint shop pro

version statement. It seemed to be identical to the printed

version as seen on the nag screen. That means one of two things:

either the version number string was just typed in twice, or more

likely, just another call to a function: PSP_VERSION() or

somesuch.



What that means for the crackist should be pretty clearly a way

to locate the protection routine. Since the word SHAREWARE shows

up in both version calls, it can be scanned for pretty easily

with either that or the word VERSION itself.

            

Then, once i felt i had done enough scouting the territory, I ran

WDASM and grabbed myself a dead listing. Scanning for SHAREWARE,

I found a couple easy references to it... one being a data string

that I promptly blanked out and the other being in the text that

comes up on the nagscreen itself. WELL WELL... 



  This is the nagscreen result here:



* StringData Ref from Data Obj ->"This is a shareware version 

                                of "Paint Shop Pro."

                                  |

:00406B64 6810A34B00              push 004BA310

:00406B69 8D4DEC                  lea ecx, [ebp-14]



Okay, running the program again, and firing softice (old friend)

i immediately saw that the version checking routine no longer

tacked on the word SHAREWARE in either the nagscreen or in the

help box.. thus proving the version call to be just that.. a call

(as suspected).



Immediately, something else came up that I was not expecting, the

location of most of the program in memory was exactly the same

as seen with softice that it was hardcoded into the disassembly.

What i mean by that is that where softice was reporting

0137:0043FAD1 for a location in memory, identical data was

reported at location :0043FAD1 on the disassembly.



Now, talk about convenient!



Simply enough, i breakpointed in softice with a few locations i

had located in the disassembly, and voila... landed smack in the

middle of the nagscreen data.



It was do-able with soft-ice alone, but tracing into the maze of

nested calls in PSP really wasn't worth my time.



Line-by-line'ing it, it was simple to watch the nagscreen build

itself call by call, and NOP or alter JZ's & JNZ's to JMP's (74's

and 75's become EB's) so that the nagscreen lost more and more

functionality.



Then came a little work - not too much, but some things were a

little funny. Notice the BITBLT in the nagscreen creation code.

I had tried to scan for some of the standard SHOWWINDOW calls

with softice and in the disassembly, but not one was to be found

where it needed to be. Apparently PSP was using some other method

of showing the screen... and a simple graphics memory copy (known

to those who follow Micro$oft as a BitBlt) was apparently the

modus operandi.



Some of the text was already in place before the BitBlt, so here

is our reason that some of the nagscreen was not being done as

we watched with the debugger... it was being written to a

backbuffer before being copied as a whole window before being

blitted to the screen. This, for those of you new to graphics

programming, is how people make smooth animation that does not

flicker... all of the animating is done in the background and a

whole screen is blitted at one time rather than by bits and

pieces (you can tell which programs do not do this very easily

since they have images that seem to disappear or flicker wrong

in odd places on the screen)



There were not many calls in that area, and only the ones that 

referenced string data or the bitblt itself could be effectively

nop'ed out.



Here is where i basically stopped the work, since i was having

trouble locating what CALLED the nagscreen area.



The reason we are getting the ghost window in the back (notice

it's size is EXACTLY the same as the nagscreen, is that windows

is being instructed by some window create command to block off

the rectangular space for the screen even though the graphic

interior does not get written.



The backgrounding code is invaluable here since the ghost window 

does not have a way to be removed without paint shop pro closing 

(which cleans up nicely for itself on exit).



Now we need to locate the call that creates the window in the

first place and nop it or whatever... there is probably a nicer

way to do all this (if you work at it, you can probably jmp past

all the functions i nop'd - taking care not to leave unmatched

pushes or pops which ruin the flow of the program - at some point

in the nagscreen area



The funny part of all this is that our cracked version will be

better than the registered version since the registered version

has a splash screen anyway - and ours does not :)



Using all of this knowledge later can actually benefit us in a

different way... we can actually use all of the techniques (since

we already know where the nagscreen is) on the executable of the

full version as well. 

Since it has no nag functions, it is a smaller executable and

cracking it will give is a nagless, splashless (eg. screenless)

version of paint shop pro that is smaller (i.e. better and more

functional) than by just cracking the shareware version.



I find that funny somehow :)



So here is all the rest you need: 



Let's have a look at the VERSION subroutine that is called both

in the nagscreen and the HELP screen:



* StringData Ref from Data Obj ->"4" ;FIRST DIGIT OF VERSION 4.01

                                  |

:004350E4 6874AE4B00              push 004BAE74

:004350E9 8B3D90004C00            mov edi, [004C0090]

:004350EF C645FC07                mov [ebp-04], 07

:004350F3 C706F0A54A00            mov dword ptr [esi], 004AA5F0

:004350F9 FFD7                    call edi

:004350FB 83C404                  add esp, 00000004

:004350FE 8BD8                    mov ebx, eax

:00435100 C1E310                  shl ebx, 10



* StringData Ref from Data Obj ->"0"    ;SECOND DIGIT OF 4.01

                                  |

:00435103 6860A64B00              push 004BA660

:00435108 FFD7                    call edi

:0043510A 83C404                  add esp, 00000004

:0043510D 0BD8                    or ebx, eax

:0043510F C1E308                  shl ebx, 08



* StringData Ref from Data Obj ->"1"   ;THIRD DIGIT OF 4.01

                                  |

:00435112 685CA64B00              push 004BA65C

:00435117 FFD7                    call edi

:00435119 C1E010                  shl eax, 10

:0043511C 83C404                  add esp, 00000004

:0043511F 0BD8                    or ebx, eax



* Possible StringData Ref from Data Obj ->"2"

                                  |

:00435121 68C4A14B00              push 004BA1C4

:00435126 FFD7                    call edi

:00435128 83C404                  add esp, 00000004

:0043512B 0BD8                    or ebx, eax

:0043512D 899ED4000000            mov [esi-000000D4], ebx



* Possible StringData Ref from Data Obj ->"0"

                                  |

:00435133 6860A64B00              push 004BA660

:00435138 FFD7                    call edi

:0043513A 83C404                  add esp, 00000004

:0043513D 50                      push eax



* Possible StringData Ref from Data Obj ->"1"

                                  |

:0043513E 685CA64B00              push 004BA65C

:00435143 FFD7                    call edi

:00435145 83C404                  add esp, 00000004

:00435148 50                      push eax



* Possible StringData Ref from Data Obj ->"4"

                                  |

:00435149 6874AE4B00              push 004BAE74

:0043514E FFD7                    call edi

:00435150 83C404                  add esp, 00000004

:00435153 50                      push eax



* Ref from Data Obj ->"%i.%i%i"  ;PRINT 3 INTEGERS: N.NN (4.01)

                                  |

:00435154 686CAE4B00              push 004BAE6C

:00435159 8D86CC000000            lea eax, [esi-000000CC]

:0043515F 50                      push eax



* Reference To: n/a, Ord:09A7h in MFC40.DLL

                                  |

:00435160 E815FF0600              call 004A507A

:00435165 83C414                  add esp, 00000014

:00435168 8D8ECC000000            lea ecx, [esi-000000CC]



* StringData Ref from Data Obj ->" Shareware"  ;PRINT SHAREWARE

                                  |

:0043516E 6860AE4B00              push 004BAE60



The first BitBlt routine of the program puts the screen on!



it is at:



* Reference To: BitBlt, Ord:000Ah in GDI32.dll

                                  |

:00406917 FF15B4F24B00            call dword ptr [004BF2B4]

:0040691D B800000000              mov eax, 00000000

:00406922 85FF                    test edi, edi

:00406924 7403                    je 00406929

:00406926 8B4704                  mov eax, [edi+04]

:00406929 50                      push eax

:0040692A 8B45B4                  mov eax, [ebp-4C]

:0040692D 50                      push eax



and here some other annoying pieces of code: The red bar as soon

as you use the program more than 30 days...



* Reference To: n/a, Ord:0970h in MFC40.DLL

                                  |

:00406BE3 E836E60900    call 004A521E ;DRAW RED BAR

:00406BE8 6801080000    push 00000801

:00406BED 8D45A0        lea eax, [ebp-60]

:00406BF0 50            push eax

:00406BF1 8B4DEC        mov ecx, [ebp-14]

:00406BF4 8B853CFFFFFF  mov eax, [ebp-000000C4]

:00406BFA 8B51F8        mov edx, [ecx-08]

:00406BFD 52            push edx

:00406BFE 51            push ecx

:00406BFF 8D8D3CFFFFFF  lea ecx, [ebp-000000C4]

:00406C05 FF5070        call [eax+70] ;BOTTOM WINDOW TXT+RED BAR

:00406C08 53            push ebx

:00406C09 8D8D3CFFFFFF  lea ecx, [ebp-000000C4]



Once found all the above, the rest is pretty obvious... here all

the necessary crackcodes: bytes to find and change. This is a

weird, non-elegant crack, but kinda funny, so i had to write it

down until i discover a better one (+gthorne speaking) note:

i gave good search strings so lamers don't get confused with

similar patterns in the software:



8B450885C07504 to 8B450885C07500 -  screen backgrounding

3CFFFFFFFF5070 to 3CFFFFFF750090 - do not draw lower text in box

3CFFFFFFFF5064 to 3CFFFFFFEB0090 - do not report version number

83FF1E7E1E to 83FF1EEB1E         - do not draw red bar

000083FFC07403 to 000083FFC0EB03 - turn nagscreen invisible

53686172657761726500 to 20202020202020202000 - disable shareware

notice writing phisycally some spaces over it



final note: since psp closes the nagscreen when the program

exits, all is now cleaned up.



 FF15B4F24B00 to 750090750090 (bitblt) seems to not do anything

the above cracks dont do.



 Time to explain BitBlt... isn 't it? BitBlt copies

a bitmap from the device context sopecified by hdcSource to the

device context specified by hdcTarget performing a block copy.

On success the function returns not zero. 

It is called with the handle hdcTarget, int nTargetX and nTArgetY

(upper left coordinates of the point at which the bitmap will be

copied... a 'pixel point' locator may be very useful in our

trade) int nWidth and nHeight of the region, the handle hdcSource

and then, finally the upper left coordinates IN the bitmap, the

two int nSourceX and nSourcey. Is it all? NO! The final

parameter, DWORD dwRaster determines HOW the bit-by-bit contents

of the bitmap will actually be copied (black, inverted, ANDed,

ORed, XOred...etc.).



Lotta things to learn if you want to crack a lot...

THE STUDENTS OF UNIT 4 (+HCU, January 1997)

*******************************************



As a matter of fact both cracks here, mine for PSPS32 and my

student's VERY smart one for PSP41 are 'weak', though: they will

not eliminate the nagscreen (you should search for the remaining

occurrences of our locations and work from them inwards, if you

really want to crack completely this scheme, but in this case it

would be better to work more with Winice95, in my opinion. But

I hope I have made the point about "dead listing" cracking: It

works! Quick and placid! In the PSP32 case the protection will

still show you the nagscreen, which will "automatically"

disappear, though, leaving you with no annoyance (in nuce: you

cracked the return button), in the other case you have physically

eliminated all possible annoyances. The nagscreen is still there,

but it does not 'harm' you any more.

Anyway I wanted only to show you the POWER and the CHILD'S PLAY

working of this "dead listing" approach (that you may combine

with some quick winice probes if you really think you need it

anytime).

     You'll agree with me, though, that this quick "weak" crack,

made with the "dead listing" method is far less tiresome than a

'live' crack with our beloved SoftIce/WinIce.

     Now, in life, I believe, you should always search to obtain

the maximum giving the minimum. There is no point in being

altruistic or excessively honest in a society where the tiny

minority that profits most keeps getting richer and richer and

the overwhelming majority that lives with meager earnings keeps

getting poorer and poorer (and -moronized by TV-watching and

other Pavlovian propagandistic sources of misinformation- keeps

voting the same rich bastards that keep it enslaved under the

whips of publicity, as if the slaves of ancient Egypt would

happily vote for their Pharaohs). I abhor and despise the society

I am compelled to live in... but this does not mean that I

renounce to anything. I am (pretty) rich, (yet do not exploit

anybody), eat very well, have a big nice house with all the

useless objects and cars and garages and terraces and futile

gadgets you are supposed to enjoy in this moronic society (I

enjoy foremost my spacious library) and I drink my regular bottle

of (Moskowskaja) Wodka every week. My liver (and my nice family)

do not seem to complain :=)



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