June 99
Cracking SnagIt32 4.3.2
Win '95 Program
Win Code Reversing
 
 
by ViPeR 
 
 
Code Reversing For Beginners 
 
 
 
Program Details
Program Name:SnagIt32 4.3.2
Program Type:Screen Capture Utility.
Program Location: Here 
Program Size: 1.68 meg
 
   
Tools Used:
Softice V3.2 - Debugger
WDASM32 V8.92 - Disassembly
 
Rating
Easy (  )  Medium ( X )  Hard (    )  Pro (    ) 
There is a crack, a crack in everything. That's how the light gets in.
 
  
 
SnagIt32 4.3.2
'Finding the registration key'
Written by ViPeR
 
 
Introduction
 
A powerful Windows IMAGE, TEXT, and VIDEO capture program that allows you a multitude of options.
 
About this protection system
 
You need to enter the correct key base in order to register this program.
 
The Essay 
Start the program, go to the help menu to fill out registration form first. After that, you can enter the registratiron key. I use evc_viper as my name and company name, blah blah blah.

Ok, enter 54545454545454 as the key. Ctrl-D into Soft-Ice and set a breakpoint by typing bpx hmemcpy. Ctrl-D to get out of Soft-Ice and back to SnagIt. Now, press Ok button and you are back to Soft-Ice. Press F11 and then F12 (7 or 8 times) to go back to the SnagIt32 process.

F10 until you arrive at

:
:0041878D 80382D                  cmp byte ptr [eax], 2D ; reg. code contains '-'?
:00418790 7503                    jne 00418795
:00418792 40                      inc eax
:00418793 EBF8                    jmp 0041878D
:00418795 8A10                    mov dl, byte ptr [eax] ; if not, put it in dl
:00418797 8811                    mov byte ptr [ecx], dl ; store dl to the location
                                                         ; that ecx points to
:00418799 41                      inc ecx
:0041879A 40                      inc eax
:0041879B 3BCD                    cmp ecx, ebp
:0041879D 72EE                    jb 0041878D

basically, the above loop just get rid of any '-' in your fake key if there is.
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0041878B(C)
|
:0041879F 802100                  and byte ptr [ecx], 00 ; make sure '0' is at the
                                                         ; end of the fake key
:004187A2 8D6F5C                  lea ebp, dword ptr [edi+5C]
:004187A5 53                      push ebx

type 'd ebp', you will see, in the data window, 4 hex codes in front of your fake key. In my case, it looks like
80 44 06 02 35 34 35 34 35 34 ......
so, let's 'd 02064480' to see what is there. Well, yes, it shows the name in the data window.
* Possible Reference to Dialog: DialogID_00E1, CONTROL_ID:0032, "H&elp"
                                  |
:004187A6 6A32                    push 00000032
:004187A8 8BCD                    mov ecx, ebp
:004187AA E8156D0400              call 0045F4C4 ; convert your name to upper case
                                                ; so, if you 'd eax', you will see
												; EVC_VIPER
:004187AF 50                      push eax
:004187B0 8BCE                    mov ecx, esi
:004187B2 E893C00100              call 0043484A ; (1)
:004187B7 6AFF                    push FFFFFFFF

After return back from 'call 0043484A', EAX=00000A00. Keep this in mind.
 
:004187B9 8BCD                    mov ecx, ebp
:004187BB 89442414                mov dword ptr [esp+14], eax
:004187BF E84F6D0400              call 0045F513 ; (2)
:004187C4 6A01                    push 00000001
:004187C6 58                      pop eax
:004187C7 38442410                cmp byte ptr [esp+10], al ; esp+10 = 0
:004187CB 0F85B4000000            jne 00418885 ; jump if bad reg code

If you F10 004187CB, and keep F10 several times, the nag screen will pup up saying that 'you must enter a valid registration key'. Hence, you know the 'cmp byte ptr [esp+10], al' is the point to decide the input registration key is true or fake. Ok, what should we do know? I have traced this proggy several hours and it seems that it is impossible to sniff out the real registration key (I mean, the real key shows up in the data window for you to see -- like, hey, I am here~~~). But, I am pretty sure (well, my sixth sense) that at some where, our fake key is compared with real one. The question now is : where is the comparision routine? Answer: inside the call in (1) and (2) I marked above. Before we go on, if you trace the code again and d esp+10 at 004187c7, you will see '00 0A .......'. Hmmm...... isn't that something +ViPeR+ want me to keep in mind? Anyway, esp+10 = 0 and al=1, so, jump (not equal) and you are a bad cracker. Ok. I want to check the call labeled (2) first. Why? coz I knew it is short and I want to see if it got something to do with that esp+10.
* Referenced by a CALL at Addresses:
|:004077B9   , :0040C7DD   , :00410DC8   , :004181B7   , :004181F0   
|:004187BF   , :0041B67A   , :0042468A   , :0042A74D   , :0042AA47   
|:0042AAAD   , :0042ADF6   , :0042AE44   , :0042AF0A   , :0042AF55   
|:0042AF76   , :0042B578   , :0043209E   , :004320AF   , :004320C0   
|:004320D1   , :00433938   , :00433A35   , :00433A9C   , :00433AE3   
|:00433BA6   , :00433E84   , :004341B0   , :00436416   , :0045788D   
|:00457DB7   , :00457E29   , :00457EE5   , :00457F72   , :0045C023   
|:0045C086   , :0045F278   , :0045F6EF   , :0045FFC2   , :00460278   
|:0046040A   , :004615CF   , :00461962   , :00461E8F   , :00461F11   
|:00463DE5   , :00463F82   , :004640EF   , :004641CE   , :0046B7C9   
|:0046CF56   , :004709FB   , :0047152A   , :00471632   , :004724ED   
|:00474FCF   , :00476859   , :00477035   
|
:0045F513 56                      push esi
:0045F514 8BF1                    mov esi, ecx
:0045F516 E86EFBFFFF              call 0045F089
:0045F51B 8B442408                mov eax, dword ptr [esp+08]
:0045F51F 83F8FF                  cmp eax, FFFFFFFF
:0045F522 7508                    jne 0045F52C
:0045F524 FF36                    push dword ptr [esi]

* Reference To: KERNEL32.lstrlenA, Ord:0308h
                                  |
:0045F526 FF1554C34700            Call dword ptr [0047C354]

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0045F522(C)
|
:0045F52C 8B0E                    mov ecx, dword ptr [esi]
:0045F52E 8941F8                  mov dword ptr [ecx-08], eax
:0045F531 8B0E                    mov ecx, dword ptr [esi]
:0045F533 5E                      pop esi
:0045F534 80240100                and byte ptr [ecx+eax], 00
:0045F538 C20400                  ret 0004

Well, after return back, esp+10 is still 0. So, I waste a little bit of time. Anyway, the call at (1) is the key to unlock the secret. So, re-do the above trace and F8 into 'call 0043484A' at 004187B2.
:0043484A 55                      push ebp
:0043484B 8BEC                    mov ebp, esp
:0043484D 83EC50                  sub esp, 00000050
:00434850 8365F800                and dword ptr [ebp-08], 00000000
:00434854 8065FE00                and byte ptr [ebp-02], 00
:00434858 53                      push ebx
:00434859 56                      push esi
:0043485A 57                      push edi
:0043485B 6A0F                    push 0000000F
:0043485D 8D45E4                  lea eax, dword ptr [ebp-1C]
:00434860 6A00                    push 00000000
:00434862 8BD9                    mov ebx, ecx
:00434864 50                      push eax
:00434865 C745F401000000          mov [ebp-0C], 00000001
:0043486C C645FF01                mov [ebp-01], 01
:00434870 E8EB2B0100              call 00447460
:00434875 8B7D0C                  mov edi, dword ptr [ebp+0C] ; edi is the fake key
:00434878 8B3554C34700            mov esi, dword ptr [0047C354]
:0043487E 83C40C                  add esp, 0000000C
:00434881 57                      push edi ; fake key
:00434882 FFD6                    call esi ; calculate the length of the fake key

:00434884 50                      push eax ; eax=0000000E
:00434885 8D45E4                  lea eax, dword ptr [ebp-1C]
:00434888 57                      push edi ; push fake key into stack
:00434889 50                      push eax
:0043488A E8312C0100              call 004474C0 ; uppercase the name
:0043488F 83C40C                  add esp, 0000000C
:00434892 8BCB                    mov ecx, ebx
:00434894 FF7508                  push [ebp+08] ; name becomes 'EVC_VIPER'
:00434897 E8B1000000              call 0043494D
:0043489C 8945F8                  mov dword ptr [ebp-08], eax
:
:
After this, you will see a lot of CALL and TEST. But trust me, only the following is the one worth tracing.
:
:
:004348E2 8D45E4                  lea eax, dword ptr [ebp-1C]
:004348E5 50                      push eax
:004348E6 8D45B0                  lea eax, dword ptr [ebp-50]
:004348E9 50                      push eax
:004348EA E8216EFFFF              call 0042B710 ; <-- this is the one we need to get in.
The call at 004348EA is the routine that compare our fake key with the real key. ^_^ So, what are we waiting for, let's dive in right away.
* Referenced by a CALL at Address:
|:004348EA   
|
:0042B710 55                      push ebp
:0042B711 8BEC                    mov ebp, esp
:0042B713 83EC7C                  sub esp, 0000007C
:0042B716 6A30                    push 00000030
:0042B718 33C9                    xor ecx, ecx
:0042B71A 58                      pop eax
Above code is not real interesting.
:0042B71B 0FB7D1                  movzx edx, cx
:0042B71E 41                      inc ecx
:0042B71F 884415EC                mov byte ptr [ebp+edx-14], al
:0042B723 40                      inc eax
:0042B724 663D3900                cmp ax, 0039
:0042B728 76F1                    jbe 0042B71B

Basically, the loop above generate '0123456789' and write it to the location that epb+dex-14 points to.
:0042B72A 6A41                    push 00000041 ; 41(hex)='A'
:0042B72C 58                      pop eax
:0042B72D 0FB7D1                  movzx edx, cx
:0042B730 41                      inc ecx
:0042B731 884415EC                mov byte ptr [ebp+edx-14], al
:0042B735 40                      inc eax
:0042B736 663D4600                cmp ax, 0046
:0042B73A 76F1                    jbe 0042B72D

The same pattern as above, but this time, it generates 'ABCDEF' and appends them to the end of the above '0123456789'.
:0042B73C 53                      push ebx
:0042B73D 56                      push esi
:0042B73E 57                      push edi ; edi contains fake key
:0042B73F 8B7D0C                  mov edi, dword ptr [ebp+0C] ; ebp+c contains another
                                                              ; copy of the fake key
:0042B742 6A02                    push 00000002
:0042B744 894DFC                  mov dword ptr [ebp-04], ecx
:0042B747 8D470C                  lea eax, dword ptr [edi+0C]
:0042B74A 50                      push eax ; 'd eax' and you will see the last two
                                           ; characters of the fake key.
										   ; This is an important hint.
:
:										   
The rest of the code after 0042B74A contains a lot of moving memory location and function call.
'F10' until you reach at
:										   
:0042B79E E88DD9FFFF              call 00429130
:
This call is the one I consider the most important one because it generates the real registration key (based on the last two registration keys you entered if my guessing is right). Don't F10 this call at this moment (if you did already, please re-try this lecture up to this point, sorry). Before this call, there are two instructions involve EAX register, just d eax before you F10 this call and you will see something in your data window.

What this function does is :it generates the 16 hex codes and store them in the memory somewhere. Where? you might wonder. Still remember that memory address the program generates '0123456789ABCDEF'? The 16 hex codes are just above that string.

In my case, since I use Name:evc_viper, key:54545454545454, so why I see on my data window is


:
BF 67 F0 C8 6C DC 55 EF CD A6 30 05 4B CB BF 21
:
Notice the even index hex code, what I mean is BF F0 6C 55 CD 30 4B BF. After this string has been generated, what the program should do? Of course, do the comparision with the fake key and here it is.
:0042B7B5 0FB7F3                  movzx esi, bx
:0042B7B8 8BC6                    mov eax, esi
:0042B7BA D1E8                    shr eax, 1
:0042B7BC 8A0438                  mov al, byte ptr [eax+edi]
:0042B7BF 50                      push eax
:0042B7C0 E834FFFFFF              call 0042B6F9
:0042B7C5 59                      pop ecx
:0042B7C6 8A4C35DC                mov cl, byte ptr [ebp+esi-24]
:0042B7CA 83E10F                  and ecx, 0000000F
:0042B7CD 38440DEC                cmp byte ptr [ebp+ecx-14], al
:0042B7D1 7510                    jne 0042B7E3
:0042B7D3 43                      inc ebx
:0042B7D4 43                      inc ebx
:0042B7D5 6683FB10                cmp bx, 0010
:0042B7D9 72DA                    jb 0042B7B5
:0042B7DB 6A01                    push 00000001
:0042B7DD 58                      pop eax
:0042B7DE 5F                      pop edi
:0042B7DF 5E                      pop esi
:0042B7E0 5B                      pop ebx
:0042B7E1 C9                      leave
:0042B7E2 C3                      ret
Here, I will explain how the comparision work.
(1)move the first fake key in al.
(2)take the first even index real key and put it in cl.
(3)and cl with 0F (hence, for the first key, BC and 0F will get C)
(4)use the value of cx as index to reference the numerical string '0123456789ABCDEF'
(5)so with index c, the real key is just C
(one suggest for the author of SnagIt32 : next time, use string like 'F2845688FE6AD39B' to refer to the real key pick-up)
(6)compare al with the real key
(7)repeat the above step until bx>=10(hex)

Since there are two inc ebx, so, only the first 8 keys will be compared(the key on the even index). But, this is not the end of the story. Ok, suppose that we get our first 8 correct registration keys. what else? of course we return to the calling routine and it is at

:004348EF 59                      pop ecx
:004348F0 85C0                    test eax, eax
:004348F2 59                      pop ecx
:004348F3 7509                    jne 004348FE ; if EAX=1, then you pass the first 
                                               ; phase of checking, and jump to 004348FE
:004348F5 2045FF                  and byte ptr [ebp-01], al ; otherwise, set ebp-01 to 00
:004348F8 C645FE0A                mov [ebp-02], 0A ; set ebp-02 to 0A
:004348FC EB40                    jmp 0043493E
(Do you still remember I have mention at the very beginning something like '.... and EAX=00000A00 keep this in mind.'? or you have already totally lost in my lecture? Anyway, if the first 8 keys is not right, 0A00 is put in EAX. I don't really understand what is the main purpose of 0A. Anyway, let's keep going. Hey, don't fall asleep, go take a coffee and read on. Don't forget you want to be a real cracker not a lamer.

Ok, we have passed the first 8 keys checking, then we jump to 004348FE.

:004348FE 57                      push edi
:004348FF FFD6                    call esi ; string length function
:00434901 83F80E                  cmp eax, 0000000E ; length of registration key should
                                                    ; be at least 14 characters.
													; I enter exactly 14 caracters.
:00434904 7C30                    jl 00434936
:00434906 83C70C                  add edi, 0000000C ; edi=fake key location
                                                    ; so, edi+c points to the last two 
													; fake key (54 in my case)coz I entered
													; 14 characters.
:00434909 6A02                    push 00000002
:0043490B 57                      push edi
:0043490C E8886DFFFF              call 0042B699 ; F10 this call, I saw EAX=00000054
                                                ; 54 is the last two keys in my last fake key
:00434911 59                      pop ecx
:00434912 83F841                  cmp eax, 00000041 
:00434915 59                      pop ecx
:00434916 7304                    jnb 0043491C
:00434918 33C0                    xor eax, eax
:0043491A EB08                    jmp 00434924
:0043491C 83E841                  sub eax, 00000041
:0043491F 83F840                  cmp eax, 00000040
:00434922 7303                    jnb 00434927
:00434924 83C00D                  add eax, 0000000D
:00434927 83F841                  cmp eax, 00000041
:0043492A 7312                    jnb 0043493E
:0043492C 8065FF00                and byte ptr [ebp-01], 00 ; (3) if the program goes here,
                                                            ; you are still a bad cracker
:00434930 C645FE0B                mov [ebp-02], 0B
:00434934 EB08                    jmp 0043493E
:00434936 8065FF00                and byte ptr [ebp-01], 00 ; (4) if the program goes here,
                                                            ; again, you are still a bad 
															; cracker
:0043493A C645FE0C                mov [ebp-02], 0C
:0043493E 33C0                    xor eax, eax
:00434940 5F                      pop edi
:00434941 8A65FE                  mov ah, byte ptr [ebp-02]
:00434944 5E                      pop esi
:00434945 8A45FF                  mov al, byte ptr [ebp-01] ; if you have visited (3) or (4)
                                                            ; then, al=0 and you will be dead
															; soon.
:00434948 5B                      pop ebx
:00434949 C9                      leave
:0043494A C20800                  ret 0008
Therefore, in order to by pasee the above (3) and (4) block, your last two keys in the registration code should be at least 82. So, I change my key to: 54545454545482 and re-trace again.

VERY IMPORTANT NOTE:Since you have change the last two keys and coz the key generation routine is (kind of) based on those two key, so you have to set a breakpoint at 0042B79D, do a d eax, then F10 the real key generation roution and write down the first 8 correct keys.

In my case, it generates
7A 52 88 F6 64 A1 A1 69 C3 79 AD EB D7 06 3F 95
So the first 8 keys are : A8413D7F and my correct key is A8413D7F545482, with name: evc_viper.
 
Final Notes 

 
My thanks and gratitude goes to:-
 
Fravia+ for providing possibly the greatest source of Reverse Engineering
knowledge on the Web.
 
 
Ob Duh 
 
 
Do I really have to remind you all that by buying and NOT stealing the software you use will ensure that these software houses will continue to  produce even *better* software for us to use and more importantly, to continue offering even more challenges to breaking their often weak protection systems.
 
If your looking for cracks or serial numbers from these pages then your wasting your time, try searching elsewhere on the Web under Warze, Cracks etc.
   

 

Essay by: ViPeR
Page Created: 12 June 1999