FullShot99

Reverse Code Engineering For Beginners

For Educational Use Only

Date: 28th May 2000

Project No: 2

This File Escaped From: "Learn Cracking In New Style."

Target: FullShot99 V5.05

Download From: http://www.image123.com/fs99v505.exe (Size: 1.14MB)

Tools Used: SoftICE, W32Dasm and a HexEditor (http://protools.cjb.net)

Rating: It's easy when you know how.

Remember This: It is easy to destroy but hard to create. Software authors work hard to give us good quality software so support shareware. If your intension is of pirating this software then stop reading..... and delete this file immediately. It's better you look for it in some WAREZ sites.


About The Program: FullShot is the complete image capture and screen printing program designed for users who need to work with images from Microsoft Windows screens. FullShot 99 is implemented in 32-bit Windows API, and it is  designed for Windows 95, Windows 98, Windows NT Workstation and Server 4.0 (on Intel or compatible microprocessors).

About Protection Scheme: The program shows a nag-screen at start-up. You can get to the registration box through HELP menu. After successfully registering this software, it stores the user information along with license no. in the license file "Fullshot99.lic". If the software is registered while installing then it saves the license file in "\Fullshot99" directory located in your root directory or if you installed a trial version then it stores the license file in "\Windows" directory.

The Essay

First Approach: I'll explain all the approaches but for now install a Trial Version of FullShot99. Go to Registration Box and enter a fake License no. Let's say 12345556789. Then click OK. Oops... it returned "Invalid License Number". OK. no problem. Create a dead list of this program with W32Dasm and look for "Invalid License Number" in String Data Reference" Remember, the license no. must be of 11 digits. Why? you'll see.

:00415936 6834EB4600         push 0046EB34
:0041593B 50                 push eax
:0041593C E8EF430100         call 00429D30
:00415941 83C40C             add esp, 0000000C
:00415944 85C0               test eax, eax
:00415946 0F84D9010000       je 00415B25
:0041594C 8D45BC             lea eax, dword ptr [ebp-44]
:0041594F 8BCE               mov ecx, esi
:00415951 50                 push eax
:00415952 E81A020000         call 00415B71 ;Call validation routine
:00415957 85C0               test eax, eax 
:00415959 750D               jne 00415968  ;you can force this to jump and it would be cracked, with only one byte. (But if you typed some 5's at the wrong places it is limited to personal edition only! Here 5 means that the digits in license no. lets says if the license no. is 12345556789 then is you put 5 at wrong places then it will be limited to personal edition only. )                                                                            
:0041595B 6AFF               push FFFFFFFF
:0041595D 50                 push eax
* Possible Reference to String Resource ID=33003: "Invalid License Number"
|
:0041595E 68EB800000         push 000080EB
:00415963 E9B6010000         jmp 00415B1E

Now, you know where is the Validation routine is. So, fire-up S-ice and set bpx GetDlgItemTextA =>F5 and then F11 and F8 4 times then into the next call (the offset is not same as when you run it inside s-ice!) or simply after you are inside the program's routine. Do bc* and bpx 00415952 and press F5. S-ice breaks again and press F8.

Validation routine:           
~~~~~~~~~~~~~~~~~~~~            
* Referenced by a CALL at Address:
|:00415952                     
|                            
:00415B71 55                 push ebp
:00415B72 8BEC               mov ebp, esp
:00415B74 83EC24             sub esp, 00000024
:00415B77 53                 push ebx
:00415B78 56                 push esi
:00415B79 8B7508             mov esi, dword ptr [ebp+08]
:00415B7C 57                 push edi
:00415B7D 56                 push esi
:00415B7E E8DD310100         call 00428D60
:00415B83 83F80B             cmp eax, 0000000B   ;Do we have B=11 digits?
:00415B86 59                 pop ecx
:00415B87 0F8502020000       jne 00415D8F   ;If not jump fake reg
:00415B8D 8A06               mov al, byte ptr [esi]   ;1st into al
:00415B8F B139               mov cl, 39
:00415B91 3AC1               cmp al, cl
:00415B93 0F8FF6010000       jg 00415D8F   ;more than 9=jump away
:00415B99 B330               mov bl, 30
:00415B9B 3AC3               cmp al, bl
:00415B9D 0F8CEC010000       jl 00415D8F   ;less than 0=jump away
:00415BA3 8A4601             mov al, byte ptr [esi+01]    ;2nd into al
:00415BA6 3AC1               cmp al, cl
:00415BA8 0F8FE1010000       jg 00415D8F    ;more than 9=jump away
:00415BAE 3AC3               cmp al, bl
:00415BB0 0F8CD9010000       jl 00415D8F    ;less than 0=jump away
:00415BB6 8A4602             mov al, byte ptr [esi+02]    ;3rd into al
:00415BB9 3AC1               cmp al, cl
:00415BBB 0F8FCE010000       jg 00415D8F
:00415BC1 3AC3               cmp al, bl
:00415BC3 0F8CC6010000       jl 00415D8F
:00415BC9 8A4603             mov al, byte ptr [esi+03]    ;4th into al
:00415BCC 3AC1               cmp al, cl
:00415BCE 0F8FBB010000       jg 00415D8F
:00415BD4 3AC3               cmp al, bl
:00415BD6 0F8CB3010000       jl 00415D8F
:00415BDC 8A4604             mov al, byte ptr [esi+04]    ;5th into al
:00415BDF 3AC1               cmp al, cl
:00415BE1 0F8FA8010000       jg 00415D8F
:00415BE7 3AC3               cmp al, bl
:00415BE9 0F8CA0010000       jl 00415D8F
:00415BEF 8A4605             mov al, byte ptr [esi+05]    ;6th into al
:00415BF2 3AC1               cmp al, cl
:00415BF4 0F8F95010000       jg 00415D8F
:00415BFA 3AC3               cmp al, bl
:00415BFC 0F8C8D010000       jl 00415D8F
:00415C02 8A4606             mov al, byte ptr [esi+06]    ;7th into al
:00415C05 3AC1               cmp al, cl
:00415C07 0F8F82010000       jg 00415D8F
:00415C0D 3AC3               cmp al, bl
:00415C0F 0F8C7A010000       jl 00415D8F
:00415C15 8A4607             mov al, byte ptr [esi+07]    ;8th into al
:00415C18 3AC1               cmp al, cl
:00415C1A 0F8F6F010000       jg 00415D8F
:00415C20 3AC3               cmp al, bl
:00415C22 0F8C67010000       jl 00415D8F
:00415C28 8A5608             mov dl, byte ptr [esi+08]    ;9th into al
:00415C2B 3AD1               cmp dl, cl
:00415C2D 0F8F5C010000       jg 00415D8F
:00415C33 3AD3               cmp dl, bl
:00415C35 0F8C54010000       jl 00415D8F
:00415C3B 8A4609             mov al, byte ptr [esi+09]    ;10th into al
:00415C3E 3AC1               cmp al, cl
:00415C40 0F8F49010000       jg 00415D8F
:00415C46 3AC3               cmp al, bl
:00415C48 0F8C41010000       jl 00415D8F
:00415C4E 8A460A             mov al, byte ptr [esi+0A]    ;11th into al
:00415C51 3AC1               cmp al, cl
:00415C53 0F8F36010000       jg 00415D8F
:00415C59 3AC3               cmp al, bl
:00415C5B 0F8C2E010000       jl 00415D8F
:00415C61 8A06               mov al, byte ptr [esi]     ;1st into al
:00415C63 3C38               cmp al, 38                 ;is it an 8
:00415C65 0F8F24010000       jg 00415D8F                ;if greater jump away
:00415C6B 3C31               cmp al, 31                 ;is it one
:00415C6D 0F8C1C010000       jl 00415D8F                ;less than 1 then jump away
:00415C73 384E01             cmp byte ptr [esi+01], cl  ;is 2nd digit=9
                                                        ;(cl=39) this one must be=9

:00415C76 0F8513010000       jne 00415D8F            ;if not equal 9 then jump away
:00415C7C 52                 push edx
:00415C7D E816010000         call 00415D98
:00415C82 8BF8               mov edi, eax
:00415C84 8A4607             mov al, byte ptr [esi+07]    ;8th into al
:00415C87 50                 push eax
:00415C88 E80B010000         call 00415D98
:00415C8D 03F8               add edi, eax
:00415C8F 8A4605             mov al, byte ptr [esi+05]    ;6th into al
:00415C92 50                 push eax
:00415C93 E800010000         call 00415D98
:00415C98 03F8               add edi, eax
:00415C9A 8A4603             mov al, byte ptr [esi+03]    ;4th into al
:00415C9D 50                 push eax
:00415C9E E8F5000000         call 00415D98
:00415CA3 03F8               add edi, eax
:00415CA5 8A4601             mov al, byte ptr [esi+01]    ;2nd into al
:00415CA8 50                 push eax
:00415CA9 E8EA000000         call 00415D98
:00415CAE 03F8               add edi, eax
:00415CB0 8A06               mov al, byte ptr [esi]       ;1st into al
:00415CB2 50                 push eax
:00415CB3 E8E0000000         call 00415D98
:00415CB8 03F8               add edi, eax
:00415CBA 8A4606             mov al, byte ptr [esi+06]    ;7th into al
:00415CBD 50                 push eax
:00415CBE E8D5000000         call 00415D98
:00415CC3 03F8               add edi, eax
:00415CC5 8A4604             mov al, byte ptr [esi+04]    ;5th into al
:00415CC8 50                 push eax
:00415CC9 E8CA000000         call 00415D98
:00415CCE 03C7               add eax, edi
:00415CD0 6A0A               push 0000000A
:00415CD2 99                 cdq
:00415CD3 59                 pop ecx
:00415CD4 F7F9               idiv ecx
:00415CD6 8D45DC             lea eax, dword ptr [ebp-24]
:00415CD9 52                 push edx
* Possible StringData Ref from Data Obj ->"%d"
|
:00415CDA 686CE14600         push 0046E16C
:00415CDF 50                 push eax
:00415CE0 E86D2D0100         call 00428A52
:00415CE5 8A4602             mov al, byte ptr [esi+02]    ;mov 3rd into al
:00415CE8 83C42C             add esp, 0000002C
:00415CEB 3A45DC             cmp al, byte ptr [ebp-24]    ;is it the same
:00415CEE 0F859B000000       jne 00415D8F                 ;if not jump away

more code follow here.......................

* Possible StringData Ref from Data Obj ->"%02d"
|
:00415D6C 6848EB4600         push 0046EB48
:00415D71 50                 push eax
:00415D72 E8DB2C0100         call 00428A52
:00415D77 8A4609             mov al, byte ptr [esi+09]    ;mov 10th to al
:00415D7A 83C41C             add esp, 0000001C
:00415D7D 3A45E8             cmp al, byte ptr [ebp-18]    ;is it the same
:00415D80 750D               jne 00415D8F                 ;if not jump away
:00415D82 8A460A             mov al, byte ptr [esi+0A]    ;mov 11th to al
:00415D85 3A45E9             cmp al, byte ptr [ebp-17]    ;is it the same
:00415D88 7505               jne 00415D8F                 ;if not jump away
:00415D8A 6A01               push 00000001
:00415D8C 58                 pop eax
:00415D8D EB02               jmp 00415D91
:00415D8F 33C0               xor eax, eax    ;If you pass from all cmp and jmp then it returns "Good Guy" else fake registration! Patch it to push 01 and it will always register (any number!)
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:00415D8D(U)
|
:00415D91 5F                 pop edi
:00415D92 5E                 pop esi
:00415D93 5B                 pop ebx
:00415D94 C9                 leave
:00415D95 C20400             ret 0004
End of code snippet.

The summary of this long validation routine is:

1. The license no. must be 11 chars
2. All must be digits, no letters allowed!
3. First digit cannot be  0 or  9
4. Second digit must always be  9.
5. The third digit should always be equal to [ebp-24]
6. The last two digits (i.e. 10th and 11th digits) must be equal to [ebp-18]. [ebp-18] returns two digits which are 10th and 11th digits respectively. The digit returned by [ebp-17] is 11th digit. [NOTE: Do ? *(ebp-17) and the number in ASCII is important.]
 
                                                                                                                                                      End Of First Approach.


Second Approach: This software only allows you to install Two Trial Version. After installing two trial version either you should register it, continue to use Demo Version or delete it from your computer. The choice is up to you. Now, in this second approach I'll teach you how to modify the software so that you could install the Trial Version as long as you wish. . but who wants to anyway, when he can have a real crack? :-). Open "fs99v505.exe" file with WinZip. Now, you should see "505setup.exe" file along with other files. I think it's on top. Extract it to "\Windows\temp" then fire-up W32Dasm and dead list "505setup.exe" file. Click on String Data Reference and look for "You have already have two 30-day free trial..." double click it. Scroll up a bit. Now, you should be seeing;

00401A1C 807DF002          cmp byte ptr [ebp-10], 02 ;compares whether you have already installed two trial version or not.

00401A20 7530              jne 00401A52    ;If yes then it returns "You have already..." else allows you to install another copy of Trial Version. Now what you can do is; change this jne to jmp(i.e change 7530 to EB30) so that either the comparision fails or not it still allows you to install Trial Version as long as you wish.                                                                     End Of Second Approach


Third Approach: In this third approach, I'll teach you to installed a fully functional version of FullShot99 right away. This approach is quite similar to the First one. So, in this you will not have to work too hard. Let's get started. As soon you doubleclick on the compressed zip executable it asks for a license number. Ok 'nuff with words, let's pass to action! OK. run fs99v505.exe and fire S-ICE, let's put a breakpoint on GetDlgItemTextA and leave S-ICE. Edit your fake license number (should be 11 numbers long, till now you should know why, Don't you? If NO! then look above at First Approach). Push the button to confirm, and softice pops , press F11 and you are right at this line:

* Reference To: USER32.GetDlgItemTextA, Ord:0104h
                                  |
:00417739 FF153C034200            Call dword ptr [0042033C]
:0041773F EB10                    jmp 00417751           <-- here.

OK. Let's step inside 505setup.exe and jump to 00417751

:00417751 5D                      pop ebp
:00417752 C20C00                  ret 000C

After the ret you're at 00401F08;

:00401F03 E81B580100              call 00417723           <-- here it calls GetDlgItemTextA.

        
:00401F08 56                      push esi               <-- you're here.

:00401F09 E8D6030000              call 004022E4      <-- this is a function,
                                              and it returns a boolean value
                                              (true or false), according to the
                                              license no. entered before.
                                              Actually it checks if the license
                                              length is 11 numbers and performs 
                                              calculations with every number of the
                                              license. It also checks whether the  ~                                             first number is >=1 and <=8 and the    ~                                             second number must be 9 (better follow ~                                             this)

:00401F0E 85C0                    test eax, eax           <-- this check returns 0.

:00401F10 59                      pop ecx

* Possible StringData Ref from Data Obj ->"TRIAL"
                                  |
:00401F11 BF04814200              mov edi, 00428104
:00401F16 7558                    jne 00401F70            <-- therefore change this                                                                   to jmp 00401F70

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:00401F16(C), :00401F26(C)
|
:00401F70 6A05                    push 00000005           <-- this is TRIAL length                                                                   (5, as you see)

:00401F72 57                      push edi
:00401F73 56                      push esi               <-- this is the fake license

        
:00401F74 E817D50000              call 0040F490 <-- this function returns