Reverse Code Engineering For Beginners
For Education Use Only

Date : 15th June 2000

 

Home                    

Tools

About Target

Essay

WorkShop

About Us

Contact Us

Solution By: meRlin 

                               Run Singularity and enter your Name, No. of Licensed Copies and a fake Serial No. Let's say:

Name: LCNS

No. Of License Copies: 99999

Serial No: 12345678

        The program checks every digits with the one which it expect to be. If any of the digits failed to pass the jump then it'll show bad guy message. Now, when you replace the first four digits with the real one at first CALL, then you have to enter second CALL to check the remaining digits. Let's suppose you changed 8 with the valid one. Then you have to again change the first four digits because the first four digits are based on last two digits which are 7 and 8 respectively. Don't get confused why this. You'll understand it when you read the tutorial.  

 

        First let's check what is the maximum no. of licensed copies supported by the program. We know that minimum is 1 don't we? Fire-up S-Ice and put BPX GetWindowtextA. Press F11 one time. Now, we are inside the program's routine. Press F10 until you reach at following address.

 

* Reference To: Sing32.?RCDlg_GetUserCount@@YAHPAUHWND__@@HPAGH@Z
|
:10011C8B E810FEFFFF    call 10011AA0-----------Checks the no. of licensed copies you entered with the maximum supported by the program.


:10011C90 83C410        add esp, 00000010
:10011C93 85C0          test eax, eax-------------Return eax=1 if good guy.
:10011C95 0F846E010000  je 10011E09-----------------If not then Bad Guy Message.

 

Let's get inside the Call 10011AA0 and see what it actually does. When you are at 10011C8B press F8 and keep on pressing F10 until you reach at:


* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10011ACF(C)
|

:10011AD5 3DFF7F0000    cmp eax, 00007FFF--------What's this.. Do ?eax you'll see 99999 and do ? 7FFF you'll see the maximum no. of licensed copies supported by the program. It's 32767

 
:10011ADA 770B          ja 10011AE7-------------------Jump is above to Bad Guy Message.


Now, exit S-ice and change the no. of licensed copies to 32767.

-------------------------------------------

OK! Now, let's go to the real thing. Fire up SoftICE, BPX GetWindowTextLengthA (or GetWindowTextA). Do F11 one time and you land at :10011A6B. We are inside SING32.dll. Do BC* to clear the BPX. Trace with F10 beyond the ret (ret to: 10011C6C). Before going any further we suggest you do a deadlisting of the Sing32.dll in Wdasm and save it as a text file then come back reading! (check out Import functions)

* Reference To: USER32.GetWindowTextLengthA, Ord:015Fh
|
:10011A65 FF15E4020210  Call dword ptr [100202E4]
:10011A6B 3B4514        cmp eax, dword ptr [ebp+14]
-----We Land here! 
:10011A6E 7C1D          jl 10011A8D-------------------------------------Jump if Name is less than 20h. Name must be less than 20h characters. 

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10011A6E(C)
|
:10011A8D FF7514        push [ebp+14]
:10011A90 FF7510        push [ebp+10]
:10011A93 56            push esi

* Reference To: USER32.GetWindowTextA, Ord:015Eh
|
:10011A94 FF15E0020210  Call dword ptr [100202E0]
:10011A9A 6A01          push 00000001
:10011A9C 58            pop eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10011A8B(U)
|
:10011A9D 5E            pop esi
:10011A9E 5D            pop ebp
:10011A9F C3            ret
---------------------------Return To :10011C6C

 

 -----------------------------------------------

:10011C6C 83C410        add esp, 00000010
:10011C6F 85C0          test eax, eax
:10011C71 0F8492010000  je 10011E09

 

.........More Codes Follows Here!...........

 

---------Keep on pressing F10 until you reach here!---------

 

* Reference To: Sing32.?il2@ri2@@QAEHXZ
|
:10011CB5 E872100000   call 10012D2C
-------------Registration check
:10011CBA 85C0         test eax, eax-------------If success eax=1
:10011CBC 0F8583000000 jne 10011D45---------------If not jump->Wrong number 

-----------------------------------------------------------------------

This is the main routine, you will always get out of this one (ret to :10011CBA) with eax containing either 0 or 1 depending upon registration fail or success! Here, we want esi+64 to be 1 (and it is if we registered already!)

* Referenced by a CALL at Addresses:
|:10010F62 , :10011CB5 , :100127E7 
|
Exported fn(): ?il2@ri2@@QAEHXZ - Ord:04D4h
:10012D2C 56           push esi
:10012D2D 6A00         push 00000000
:10012D2F 8BF1         mov esi, ecx
:10012D31 6A00         push 00000000

* Reference To: Sing32.?gt2@ri2@@QAEGPADI@Z
|
:10012D33 E854000000   call 10012D8C
------------------Get date and time etc..
:10012D38 6685C0       test ax, ax
:10012D3B 7525         jne 10012D62
:10012D3D 8BCE         mov ecx, esi

* Reference To: Sing32.?iv1@ri2@@QAEHXZ
|
:10012D3F E8ECFDFFFF   call 10012B30
-----------------Validation routine of the first 4 digits)


:10012D44 85C0         test eax, eax
:10012D46 7416         je 10012D5E
--------------------Jump away bad guy
:10012D48 8BCE         mov ecx, esi

* Reference To: Sing32.?iv2@ri2@@QAEHXZ
|
:10012D4A E8FBFDFFFF   call 10012B4A
----------------Validation routine of the remaining digits)


:10012D4F 85C0         test eax, eax
:10012D51 740B         je 10012D5E
-------------------Jump away bad guy 
:10012D53 8BCE         mov ecx, esi

* Reference To: Sing32.?iu2@ri2@@QAEHXZ
|
:10012D55 E8AAFFFFFF   call 10012D04
---------------Check if it is  “Old Regcode”
:10012D5A 85C0         test eax, eax
:10012D5C 7404         je 10012D62
-------------------Jump if it’s not

 

The simplest way to crack this program is to change this: xor eax, eax to xor al, 01
in this way you got eax=1 and then you change the jmp 10012D65 to jmp 10012D62.
If you do! Make the 3 key’s in registry and type anything you want ;-) (With one exeption!!
you need to change it so it look like this:

HKEY_LOCAL_MACHINE\SOFTWARE\WinAbility\Singularity\Setup\1 <-!!!

Better to sniff the valid code!! So press F8 when you are at the CALL 10012B30.
-------------------------------------------------------------------------

Follow the registration calculation to sniff real regcode for your name and number of copies entered. There is a lot of pointer’s moving around with our number, try to follow them 

 

* Referenced by a CALL at Addresses:
|:10011CF5 , :10012B70 , :10012D3F 
|
Exported fn(): ?iv1@ri2@@QAEHXZ - Ord:04D6h

:10012B30 8B4170        mov eax, dword ptr [ecx+70]
:10012B33 83C142        add ecx, 00000042
--------------------(Do d ecx and you'll see the number you typed)


:10012B36               FF7038 push [eax+38]
:10012B39 FF7034        push [eax+34]
:10012B3C 8A4028        mov al, byte ptr [eax+28]
-----Important value(53h=S)


:10012B3F 50            push eax---------------------------------------Push 53h 
:10012B40 51            push ecx---------------------------------------Push Regnumber

* Reference To: Sing32.?riivc2@@YAHPBDDHH@Z
|
:10012B41 E8A6F8FFFF    call 100123EC
-----------------------------First checking
:10012B46 83C410        add esp, 00000010
:10012B49 C3            ret


Here is the first checking done at :100123F5 the first typed is compared

 with (53h=S), is it not the same then xor eax, eax =0 ,else go on and check

 next digit at :10012413 call 100122EB

* Referenced by a CALL at Address:
|:10012B41 

Exported fn(): ?riivc2@@YAHPBDDHH@Z - Ord:04EDh
:100123EC               55 push ebp
:100123ED 8BEC          mov ebp, esp
:100123EF 83EC20        sub esp, 00000020
:100123F2 8B4508        mov eax, dword ptr [ebp+08]
:100123F5 8A08          mov cl, byte ptr [eax]
–-------Depence what you typed as first digit. But in our case 1

:100123F7 3A4D0C        cmp cl, byte ptr [ebp+0C]----It’s compared with ebp+0C which is equal to 53h=S. Do ? *(ebp+0C).

:100123FA 7549          jne 10012445------------------------------Jump away if it’s not. Exit Softice and change first digit to S and again follow till here.

:100123FC 8D4DE0        lea ecx, dword ptr [ebp-20]
:100123FF 6A20          push 00000020
:10012401 51            push ecx
:10012402 6A00          push 00000000
:10012404 6A00          push 00000000
:10012406 50            push eax
:10012407 E836FFFFFF    call 10012342
:1001240C FF7510        push [ebp+10]
:1001240F 8D45E3        lea eax, dword ptr [ebp-1D]--Regnumber
:10012412 50            push eax
:10012413 E8D3FEFFFF    call 100122EB
--------------------------------Calculation
:10012418 83C41C        add esp, 0000001C
:1001241B 3845E1        cmp byte ptr [ebp-1F], al
--------2nd digit. Do ? *(ebp-1F), you'll see 5432 and do ? al you'll see the no. that should be put in the place of 2. Exit S-Ice and change 2 with the value inside al and follow till here.

:1001241E 7525          jne 10012445---------------------------------Jump away if it’s not 

:10012420 FF7514        push [ebp+14]
:10012423 8D45E3        lea eax, dword ptr [ebp-1D]
----Regnumber
:10012426 50            push eax
:10012427 E8BFFEFFFF    call 100122EB
--------------------------------Calculation 
:1001242C 3845E2        cmp byte ptr [ebp-1E], al--------3rd digit. Do ? *(ebp-1E), you'll see 6543 and do ? *al you'll see the no. that should be put in the place of 3. Exit S-Ice and change 3 with the value inside al and follow till here.

:1001242F 59            pop ecx
:10012430 59            pop ecx
:10012431 7512          jne 10012445
----------------------------------Jump away if it’s not 


:10012433 807DE339      cmp byte ptr [ebp-1D], 39--------Is the 4th digit = 9
:10012437 7410          je 10012449-----------------------------------Jump if it is!
:10012439 807DE338      cmp byte ptr [ebp-1D], 38-------Is the 4th digit = 8
:1001243D 740A          je 10012449-----------------------------------Jump if it is!
:1001243F 807DE337      cmp byte ptr [ebp-1D], 37-------Is the 4th digit = 7
:10012443 7404          je 10012449-----------------------------------Jump if it is!
    

    The four digit must be equal to either 9, 8, or 7. So change it to the no. you like.

 

* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:100123FA(C), :1001241E(C), :10012431(C)
|
:10012445 33C0           xor eax, eax
--------------------------------This is not good!!
:10012447 C9             leave
:10012448 C3             ret (eax=0)


* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:10012437(C), :1001243D(C), :10012443(C)
|
:10012449 6A01           push 00000001
-------------------------------Yes this OK!
:1001244B 58             pop eax
:1001244C C9             leave
:1001244D C3             ret (eax=1)

-------------------------------------------------------------------------------

Ok the first is done! Now the name, number of copies and some number of regcode is brought together and calculated again. So let's go inside the second CALL 10012B4A. Press F8 when you are at 10012D4A. Now, you should see following:

Exported fn(): ?iv2@ri2@@QAEHXZ - Ord:04D7h

:10012B4A 8B4170         mov eax, dword ptr [ecx+70]
:10012B4D 8D5142         lea edx, dword ptr [ecx+42]
:10012B50 FF7030         push [eax+30]
:10012B53 6A01           push 00000001
:10012B55 FF702C         push [eax+2C]
:10012B58 6A00           push 00000000
:10012B5A 52             push edx
:10012B5B 668B5140       mov dx, word ptr [ecx+40]
:10012B5F 52             push edx
:10012B60 FF7024         push [eax+24]
:10012B63 51             push ecx

* Reference To: Sing32.?riivn2@@YAHPBD0G0HHHH@Z
|
:10012B64 E8E5F8FFFF     call 1001244E
----------------This is place where the remaining digits are compared with the valid digits. So let's go inside this CALL press F8 when you are at 10012B64.


:10012B69 83C420         add esp, 00000020
:10012B6C C3             ret

 

Now, you'll be here!

 

* Referenced by a CALL at Addresses:
|:10012B64 , :10012BA0 
|
Exported fn(): ?riivn2@@YAHPBD0G0HHHH@Z - Ord:04EEh
:1001244E 55              push ebp
:1001244F 8BEC            mov ebp, esp
:10012451 83EC64          sub esp, 00000064
:10012454 56              push esi
:10012455 57              push edi
:10012456 8D45DC          lea eax, dword ptr [ebp-24]

------------More Codes Follows Here!-----------

 

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001248A(C)
|
:1001248F 8A45E0           mov al, byte ptr [ebp-20]
:10012492 6A40             push 00000040
:10012494 8845FC           mov byte ptr [ebp-04], al
:10012497 8A45E1           mov al, byte ptr [ebp-1F] ----Here
:1001249A 8845FD           mov byte ptr [ebp-03], al
:1001249D 8D459C           lea eax, dword ptr [ebp-64]
:100124A0 50               push eax
:100124A1 8D45FC           lea eax, dword ptr [ebp-04]
:100124A4 50               push eax
:100124A5 FF7510           push [ebp+10]
:100124A8 56               push esi
:100124A9 E894FEFFFF       call 10012342
:100124AE FF751C           push [ebp+1C]
:100124B1 8D459C           lea eax, dword ptr [ebp-64]
:100124B4 50               push eax
:100124B5 E831FEFFFF       call 100122EB-----------------Here it puts some of the number to our name and then calculate them again.(registered copys+two of regcode digits)

:100124BA 8B4D18           mov ecx, dword ptr [ebp+18]
:100124BD 83C41C           add esp, 0000001C
:100124C0 38440DE2         cmp byte ptr [ebp+ecx-1E], al--Compare again. Do ? *(ebp+ecx-1E) you'll see 87 and do ? al you'll see the valid digit. Exit S-ice and replace 7 with the valid digit.


:100124C4 5F               pop edi
:100124C5 5E               pop esi
:100124C6 7404             je 100124CC--------------------Jump if nice guy for the last check or no jump for bad cracker!


:100124C8 33C0             xor eax, eax-------------------If we NOT passed all the checking we got 0 in al=no good ;-)


:100124CA C9               leave
:100124CB C3               ret (eax=0)

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100124C6(C)
|
:100124CC FF7524           push [ebp+24]
:100124CF 8D459C           lea eax, dword ptr [ebp-64]
:100124D2 50               push eax
:100124D3 E813FEFFFF       call 100122EB--------------Calculation
:100124D8 8B5520           mov edx, dword ptr [ebp+20]
:100124DB 59               pop ecx
:100124DC 59               pop ecx
:100124DD 33C9             xor ecx, ecx
:100124DF 384415E2         cmp byte ptr [ebp+edx-1E], al---Compare again. Do ? *(ebp-edx-1E), you'll see 8 and do ? al you'll see the valid digit. Exit S-ice and replace 8 with the valid digit.


:100124E3 0F94C1           sete cl-------------------------If we passed all the checking we got 1 in cl=Good ;-)

:100124E6 8BC1             mov eax, ecx
:100124E8 C9               leave
:100124E9 C3               ret-----------------------------(eax=1)

We have traced through the codes and passed all checking. Now, EAX=1 then ret to :10012D5A . The value in esi+64=1 futher away and ret to :10011CBA
This is where we came from (from the beginning) test eax, eax and we will pass with a valid number for our Name, Number of licensed copies and Registration Code.
Singularity is now cracked ;-)

---------------------------------------------------------------------------

 

Let's collect more information about the program.

 

Calculation routine:

 

    When you are at:

 

:10012413 E8D3FEFFFF       call 100122EB

Press F8 to go inside the CALL.

* Referenced by a CALL at Addresses:
|:10012413 , :10012427 , :100124B5 , :100124D3 
|
:100122EB 660FB6542408     movzx dx, byte ptr [esp+08]
:100122F1 56               push esi
:100122F2 8B742408         mov esi, dword ptr [esp+08]
:100122F6 8BCA             mov ecx, edx
:100122F8 8A06             mov al, byte ptr [esi]
:100122FA 84C0             test al, al
:100122FC 7434             je 10012332
:100122FE 57               push edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001232F(C)
|
:100122FF 8BFA             mov edi, edx
:10012301 0FAFF9           imul edi, ecx
:10012304 660FBEC0         movsx ax, al
:10012308 46               inc esi
:10012309 8D4C07E1         lea ecx, dword ptr [edi+eax-1F]-Compare again


:1001230D 84C9             test cl, cl
:1001230F 750A             jne 1001231B
:10012311 33C0             xor eax, eax
:10012313 8AC5             mov al, ch
:10012315 33C9             xor ecx, ecx
:10012317 8AE8             mov ch, al
:10012319 0BCA             or ecx, edx

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:1001230F(C)
|
:1001231B 33C0             xor eax, eax
:1001231D 8AC5             mov al, ch
:1001231F 84C0             test al, al
:10012321 7508             jne 1001232B
:10012323 33C0             xor eax, eax
:10012325 8AE2             mov ah, dl
:10012327 8AC1             mov al, cl
:10012329 8BC8             mov ecx, eax

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:10012321(C)
|
:1001232B 8A06             mov al, byte ptr [esi]
:1001232D 84C0             test al, al
:1001232F 75CE             jne 100122FF
:10012331 5F               pop edi

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:100122FC(C)
|
:10012332 0FB7C1           movzx eax, cx
:10012335 6A0A             push 0000000A
:10012337 99               cdq
:10012338 59               pop ecx
:10012339 5E               pop esi
:1001233A F7F9             idiv ecx
:1001233C 8BC2             mov eax, edx
:1001233E 83C030           add eax, 00000030------------eax now contains the number which is Valid! to go on
(loop along with all the numbers through this place)


:10012341 C3               ret

If you want to see the Valid number for your name, check out the value of eax!

Singularity is now fully cracked!

 

 

© 2000 "Learn Cracking In New Style". All Rights Reversed.