ED!SON's Tutorial #1
Graphics Workshop for Windows 1.1u
Tutorial #1 version 1.0
Introduction
This tutorial is made for the beginner Windows cracker. The goal is to find a valid registration code for Graphics Workshop 1.1u. It might/might not work with earlier and later versions. A basic knowledge of cracking and Windows programming is necessary. You will need SoftICE/Windows (I use version 1.31).
The tutorial may seem long, but the crack is easily done. I did it in a few minutes.
Good luck!
.oOOo. ED!SON .oOOo.
an461165@anon.penet.fi - http://www.geocities.com/SiliconValley/2860/
Installing and loading SoftICE
Install SoftICE/Windows in a suitable directory like \WINICE. To load Windows with SoftICE, start WINICE.EXE.
Loading the program to debug
If you haven't previously installed Graphics Workshop for Windows 1.1u, do so now...
To load it, you open the program called WLDR in the SoftICE/Windows program group. Select Browse and find the file GWS.EXE. Press Load to load the program.
Debugging
Bring up the Registration box (File|Setup|Register) and enter some some nice values in the field.
Press OK and you get an error message. Now press Ctrl+D to bring up SoftICE.
Now, how do we find the code that checks the registration info? Windows makes all this easy for us. If you know anything about Windows programming, you will understand this... :-)
Finding the function that checks the registration info
List all window handles owned by GWS with the command HWND gws. It will give a long list beginning somewhat like this:
:hwnd gws
Window Handle hQueue QOwner Class Name Window Procedure
0E8C(0) 282F GWS #32769 0487:9E6B
0F0C(1) 282F GWS #32768 USER!BEAR306
53CC(1) 282F GWS #32770 0717:0429
542C(2) 282F GWS BorShade 14F7:01F3
5474(2) 282F GWS BorBtn 14E7:1012
54C0(2) 282F GWS Static 0717:2313
5508(2) 282F GWS BorBtn 14E7:1012
5554(2) 282F GWS BorShade 14F7:01F3
559C(2) 282F GWS BorBtn 14E7:1012
55E8(2) 282F GWS BorBtn 14E7:1012
4F94(1) 282F GWS #32770 0717:0429
.
.
.
Find the one that probably is the message box by looking at the contents. A lucky guess is the first window, here with window handle (hWnd) 53CC. Ok, now we now this. Time to find the window handler procedure... Type BMSG 53CC WM_COMMAND to make the program break every time a WM_COMMAND window message is sent to window 53CC. Now run the program again by pressing Ctrl+D or F5. Press the OK button and you will get back into SoftICE. Type STACK to see the call stack. It will look very much like this:
:stack
=> USER(19) at 0717:0E22 [?] through 0717:0C23
GWS(07) at 27FF:247E [?] through 27FF:247E
GWS(05) at 2807:357E [?] through 2807:353F
BWCC(0D) at 11EF:0032 [?] through 11EF:0000
USER(19) at 0717:08E3 [?] through USER!DIALOGBOXINDIRECT
USER(19) at 0717:0971 [?] through 0717:08EB
USER(19) at 0717:07E4 [?] through 0717:0737
USER(19) at 0717:0CA7 [?] through 0717:0C23
BWCC(06) at 14E7:1679 [?] through 14E7:1679
=> USER(19) at 0717:0429 [?] through USER!SENDMESSAGE
As you can see, you are now in USER, not in GWS where we want to be (marked with bold text in the list above). So we could just trace back to the GWS code, but it's better to set a breakpoint on the last call in GWS. So we enter BPX 2807:353F in SoftICE. We can also disable or clear the old breakpoint with BD/BC 0 (for breakpint # 0), it's of no use now.
Ok, let's run the program and press OK again. Now you get back to SoftICE before the message is displayed. Now you trace through the code with F10 and see if it looks like GWS checks the code in this procedure. You will notice that it just displays the box and then returns. So the function that called this function would be more intresting. We return to this function and look upwards in the code window (with Ctrl+PgUp), to see where the function begins. At offset 27FF:23C9 we find a retf, so we guess this function begins at the following instruction at 23CC. Time to set a breakpoint there with BPX 23CC, and disable/clear the old one. And we run the program again and we press OK again... But now we return to SoftICE at 27FF:23CC. Let's step it through...
In our function
We soon jump to 23F6 and we see a GetDlgItem call. Because of our Windows programming knowledge, we know that this function gets the hWnd of an item in a dialog box. We continue and we find a GetWindowText call. It looks like this:
PUSH AX ; Store the edit box hWnd
PUSH SS ; Store the buffer segment
LEA AX, [BP+FED8] ; Put offset in AX
PUSH AX ; Store offset
PUSH 0090 ; Store lenght of buffer
CALL USER!GETWINDOWTEXT ; Get text
We can see that the text will be stored at SS:AX when we reach the call. We point our data window there with the command D SS:AX. We step over the call with F10 and we see the registration code we have entered in the data window. This is repeated with the name.
Then, at last, here comes what we have waited for. The validation of the registration code!
Validation...
You see two calls. As you easily find out, the first (at 242F) converts the registration code you used to numerics, the other (at 243F) converts your name to a valid code.
LEA AX, [BP+FF6A] ; load offset to code
PUSH AX ; push offset on stack
242F CALL 281F:671C ; convert text to number => AX
ADD SP, +02 ; restore stack
MOV [BP-04], AX ; store number
LEA AX, [BP+FED8] ; load offset to name
PUSH AX ; push offset on stack
243F CALL 2807:8E82 ; convert text to code => AX
ADD SP, +02 ; restore stack
CMP AX, [BP-4] ; compare values...
So, the valid number is afterwards in AX. The values are compared, and probably your first guess was wrong :-)
But if you wrote down the valid code from AX, you can convert it to decimal system with the Windows calculator or like this in SoftICE: ? 3CB1 (or whatever code you got).
Hey, you have the code!