Start out by installing Quick View Plus Trial edition; the Install Wizard will guide you through its dismal blue screens and grey dialog boxes. When it finishes, Quick View Plus will run and a small grey window with three buttons ("Purchase", "Uninstall", "Continue") will appear; it is here that the exercise will begin in earnest. 1) Click "Purchase", then "$49", then "Accept", and finally "Unlock by Phone". 2) Press Ctrl-D to bring up Soft-Ice. Our approach is going to be to capture messages to the "Register" window, and to accomplish this we need to do a little scouting: BMSG requires an hwnd parameter, and the HWND command requires a process name. We will therefore first type TASK at the Soft-Ice command line, which shows us the following: Taskname SS:SP StackTop StackBot StackLow TaskDB hQueue Events Order32 0000:0000 005ED000 005F0000 11DE 2EEF 0000 ... There it is, right on top: Order32. The Syntax for HWND is HWND task, so we will now type HWND ORDER32, which will give the following output: Window-Handle hQueue SZ QOwner Class_Name Window Procedure 07A8(1) 2EEF 32 ORDER32 #32770 (Dialog) 173F:00004757 07AC(2) 2EEF 32 ORDER32 Static 173F:000052FA ....... 07DC 2EEF 32 ORDER32 Edit 173F:00000BF4 There are a ton of windows listed, with 07A8 being the main dialog box, but the one we are interested in is the only edit control: 07DC. 3) What we are going to do now is set a breakpoint on window 07DC (the edit control) for the windows message WM_GETTEXT; by only trapping this message (which retrieves text from an edit control), we avoid having to cycle through the various screen-painting and mouse-over routines that Windows processes every millionth of a second. Note that we could instead breakpoint on GetDlgItemText, GetDlgItemTextA, GetWindowText, and GetWindowTextA to achieve the same effect, but it is wise to set only 1 breakpoint instead of 4 (plus the programmer may have written their own "Get Text" routine, in which case these breakpoints would fail us). The command we will type at the Soft-Ice prompt is BMSG 07DC WM_GETTEXT. 4) Now we are ready for action. Enter the Unlocking Code you like best (I lean towards 666111666) and press "OK". You will pop immediately into Soft-Ice, in USER!BOZOSLIVEHERE--Microsoft's little idea of a joke, I guess; press F12 to RET out of the function and you will be in USER!BEAR498, F12 again to USER!GLOBALGETATOMNAME, F12 once again to end up in PROT16 code, another F12 brings you to USER!DIALOGBOXINDIRECTPARAM, and finally one more F12 and you will end up in KERNEL.Alloc. This is fairly important to notice, for in most cases where your breakpoint dumps you into Windows code (and F11 will get you out of only a single layer), you will come across KERNEL.Alloc right before you come back to the application's code. A good rule of thumb is therefore to F12 fanatically until you reach KERNEL.Alloc, then press F12 once to get back to the application. 5) Press F12 that one final time, and you will find yourself in ORDER32!.text 39B9, with the following code: 0137:004049B9 Call [User32!GetDlgItemTextA] 0137:004049BF LEA ECX,[EBP-68] 0137:004049C2 PUSH ECX 0137:004049C3 CALL 004047E2 0137:004049C8 ADD ESP,04 0137:004049CB TEST EAX,EAX 0137:004049CD JNZ 004047E2 004049BF LEA ECX,[EBP-68] is the current line of code; Call User32!GetDlgItemTxtA had just been executed. Looking at the next few lines of code, you will realize that this is all we need: this is a classic TEST/JNZ scheme. The Unlock Code has been stored in EBP-68 by GetDlgItemTextA; it is then moved to ECX and pushed on to the stack as the only parameter to the function at 004047E2. When the program returns from the call, the stack is corrected (ADD ESP,04) and a boolean value (1 or 0, equaling TRUE or FALSE) has been stored in EAX by the function. The value in EAX is then tested to find out if it is TRUE (1) and if so, the program moves on to the"good-unlock-code-now-register-the-poor-fellow" code. In psuedo-C-code, this would look like CHAR UnlockCode; BOOLEAN IsGood; ... GetDlgItemText(hwnd 07DC, int UnlockCodeField, charbuf [EBP-68], int 8); UnlockCode=[EBP-68]; IsGood=ValidateUnlockCode(UnlockCode); if (IsGood) UnlockProgram(); else MessageBeep(); ... Now we must make sure we are right about this code. F8 through the LEA instruction, then type D ECX: at the Soft-Ice command line and there in the data window you will see 013F:005EF604 36 36 36 31 31 31 36 36-00 05 00 00 7F 16 85 63 66611166....^..c OK, so that is our serial about to be manipulated. Look close, what do you see? Our dear little 666111666 (or the first eight digits of it, actually) being loaded into ECX as a parameter to 004047e2 ValidateUnLockCode(UnlockCode). F10 down to the JNZ, but halt there. Notice it says JNZ 00404A29 (NO JUMP) Now we will toggle the zero flag, so that it becomes not-zero, by typing R FL Z. Notice how the code has changed to JNZ 00404A29 (JUMP) At this point we will Ctrl-D to return control back to the program and see if we were right...a new window pops up: Quick View PLus Unlocked Thank you for purchasing ya-di-ya-di-ya.... Press "OK", the lesson is over! To clean up, press Ctrl-D and type BC * to clear all of your breakpoints. The next trick i use, is for NAG SCREENS. This may seem confusing also.. but again, play around with it. You'll get used to using it. When a nag screen pops up, enter sice and type: HWND You should see something similar to: Window Handle hQueue SZ Qowner Class Name Window Procedure ____________________________________________________________________________ 0080(0) 2057 32 MSGSRV32 #32711(switch win) 17ef:00004b6e 0084(1) 2057 32 EXPLORER shell_trayWnd 1487:0000016c ...... ...... What you want to do is scroll down the list of handles, and look at the QOWNER. Find the handle of a process that belongs to your program, and if your nag screen has an OK button, look for a BUTTON under class name. If your nag screen doesn't have one, then anything that has BUTTON after it, won't be the handle you want to break on. This is trial and error untill you get the one you want (explained in a little bit). The list of handles will probably be quite long, but usually the nag screen is amongst the first that belong to your program. Once you think you've found your nag screen's handle, you will want to use the BMSG command. If you want to see the exact paramaters it allows, while in sice, type: HELP BMSG OK, now to our example. Lets assume your nag has an OK button after the handle you want to break on (easier to find), and you think you've found your proper handle. You would want to type: BMSG 0084 WM_DESTROY Where 0084 is the handle of your nag screen. What this basically does, is tell sice to break after the nag screen has been erased from the screen. You will be deep inside of some unknown API, so you will have to F12 (P RET) which stands for Pause on RETurn back you your program's code. At this point you want to find where the initial nag was created (set BPX on most of the calls you come out of). The nag screen was most likely created/destroyed in same call, so if you find the proper one, do whatever you need to do. *NOTE* I'M NOT GOING TO GO INTO DETAIL HERE. IF YOU DON'T KNOW WHAT TO DO WITH A CALL, THEN PRACTICE, AND READ SOME MORE TUTORIALS