First time I download SOFTICE was from CRACKSTORE's page, I spent hours and hours just to get this BEAUTIFUL DEBUGGER, my MOM could kill me if she knew that I was still hanging around on the NET at 3:00 AM, anyway that was my first sacrifice to become a CRACKER. Then I started to SETUP this prog and got the SN# from someone called FOSI. I was very happy that time, just like all of you MEN !!!

The next day I tried to update my copy at NUMEGA's PAGE (still with the SN# that I received from CRACKSTORE's PAGE)

Then guess what happened ?

There has been a problem processing your request because the file has been downloaded an excessive amount of times.
Error 100
Please contact Customer Service

Maybe I needed to fill up the form registration first to update SOFTICE, but when I did it this message appeared:

NuMega Product Registration
You have used a test serial number.
Please use your back button to return to the form.

Yeah ... what a STUPID message. Maybe NUMEGA has BLACKLISTED that SERIAL NUMBER.

After thinking for quite a long time, I figured out that SOFTICE SETUP file can create you a bunch of SN#,

Let's tell our new SLAVE to do his work and UPDATE our beloved SOFTICE at NUMEGA !


OK let's start to install SOFTICE,
... bla ...bla ...bla clicking this and clicking that what a boring job, now InstallShield is asking your NAME, COMPANY and SN#, you can enter the NAME and COMPANY with anything you like and the DUMMY CODE with : 1234-567890-AB (or anything else).

Now I'm thinking what breakpoint should work ....
After trying some breakpoint I figured out that BPX SENDDLGITEMMESSAGEA work well.

Let's take a look how SENDDLGITEMMESSAGEA is declared :

LONG SendDlgItemMessage(

HWND hDlg,    // handle of dialog box
int nIDDlgItem,    // identifier of control
UINT Msg,    // message to send
WPARAM wParam,    // first message parameter
LPARAM lParam     // second message parameter

The SendDlgItemMessage function sends a message to the specified control in a dialog box.

If you want the WINAPI references try to get it at

First of all you must find where the PROTECTION is located and if you wanna find that CRAP then be PATIENT coz this time is a VERY VERY LONG JOURNEY BUDDY.


Ok you've found it, you learn quickly pal, I like that, let's continue and analize what's going on. But do you know where you are right now ? No ? Do you see NMINST32! .text+0E44 in SOFTICE ?

That means you're in NMINST32.DLL. :) OK continue ...

:10001E44 FFD5                    call ebp                            
:10001E46 8D7C2418                lea edi, dword ptr [esp+18]


:10001E87 8D442410                lea eax, dword ptr [esp+10]          
:10001E8B 50                      push eax
:10001E8C 6800620110              push 10016200                        SAVE FIRST TABLE
:10001E91 E81A800000              call 10009EB0
:10001E96 83C408                  add esp, 00000008                    CORRECT THE STACK
:10001E99 85C0                    test eax, eax
:10001E9B 7542                    jne 10001EDF
:10001E9D 8D442410                lea eax, dword ptr [esp+10]
:10001EA1 50                      push eax
:10001EA2 68A0620110              push 100162A0                        SAVE SECOND TABLE
:10001EA7 E804800000              call 10009EB0
:10001EAC 83C408                  add esp, 00000008
:10001EAF 85C0                    test eax, eax
:10001EB1 752C                    jne 10001EDF
:10001EB3 8D442410                lea eax, dword ptr [esp+10]
:10001EB7 50                      push eax
:10001EB8 6850620110              push 10016250                         NO TABLE
:10001EBD E8EE7F0000              call 10009EB0
:10001EC2 83C408                  add esp, 00000008
:10001EC5 85C0                    test eax, eax
:10001EC7 7516                    jne 10001EDF
:10001EC9 8D442410                lea eax, dword ptr [esp+10]
:10001ECD 50                      push eax
:10001ECE 68B0610110              push 100161B0                         NO TABLE
:10001ED3 E8D87F0000              call 10009EB0
:10001ED8 83C408                  add esp, 00000008
:10001EDB 85C0                    test eax, eax
:10001EDD 740F                    je 10001EEE

:10001EDF 68D0660110              push 100166D0

You can see that there is a four same call, the call 10009EB0 and before that call there is two parameters being pushed, let's figured out.

First Parameter

lea eax, dword ptr [esp+10] ----------> EAX will contain some address
push eax

After EAX has the address let's see what is eax containing.

Now DUMP EAX in SOFTICE, you'll see :

D'ya see that ......?
They only take our first three char, 11th & 12th char , the 8th, 9th and 10th char for the first parameter.

[The rest is nothing than a SILLY GARBAGE.] .......... WRONG if you are thinking like that, coz the others are needed for generating the REAL CODE !

Second Parameter

THE PUSH 10016200 instruction saves the FIRST TABLE on the stack, PUSH 100162A0 saves the SECOND TABLE.

FIRST TABLE will look like this :

190 400 401 410
411 420 421 430
431 480 481

The second TABLE is the same as the first one but only the 190 is change to 191. That mean you have TWELVE option for your first three chars, pick up your favourite one OK. 

Anyway ......  400x-xxxxxx-xx  belongs to the NUMEGA CODE REVIEW v5.01 serial number, coz when I tried to Decompiler the code review script file, I figure out that the table is almost identical, so if you create a SN# in SOFTICE setup file with 400 it front of it, then that's the SN# for CODE REVIEW (.... he he he he .... in one product contain a lot of SN# for the other products). Your homework is to try each number and figure out yourself, I'm sure they will work for the other NUMEGA products.

NOW the CALL 10009EB0, What d'ya think of that ?

The important thing is, we don't want EAX containing ZERO when returning from the CALL, coz you'll miss the JNE 10001EDF(Another part of the protection after TRACING it for along time.)


:10009EB0 8B4C2408                mov ecx, dword ptr [esp+08]           ECX = 123.....AB.890..
:10009EB4 57                      push edi
:10009EB5 53                      push ebx
:10009EB6 56                      push esi
:10009EB7 8A11                    mov dl, byte ptr [ecx]               | our first char to DL
:10009EB9 8B7C2410                mov edi, dword ptr [esp+10]          | EDI = FIRST TABLE
:10009EBD 84D2                    test dl, dl                          | 
:10009EBF 7469                    je 10009F2A                          | 
:10009EC1 8A7101                  mov dh, byte ptr [ecx+01]            | our second char to DH
:10009EC4 84F6                    test dh, dh                          |
:10009EC6 744F                    je 10009F17              ____________|If our first & second 
                                                                        char = 0 then GETOUT
                                                                        from the CALL.                                                          
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:10009F02(C), :10009F15(U)
:10009EC8 8BF7                    mov esi, edi
:10009ECA 8B4C2414                mov ecx, dword ptr [esp+14]
:10009ECE 8A07                    mov al, byte ptr [edi]
:10009ED0 46                      inc esi

:10009ED1 38D0                    cmp al, dl
:10009ED3 7415                    je 10009EEA                 ---------> If equal then
                                                                         compare the next char.


When you enter your SERIAL with some dummy code like 1234-567890-AB then your first three char (in this case 123) are compared with 190, if not equal compared with 400, if not equal compared with 401 etc, until 481 (or whatever inside the TABLE)
If it still not EQUAL then a TERRIBLE thing happens

the MIGHTY XOR EAX, EAX instruction ----> EAX = 0

Yes you're right, that means our first three chars must be EQUAL to one of those in the TABLE. Let's change our DUMMMY CODE to 1900-123456-78 (Pick up your favourite one from the TABLE !)

* Each Number from the TABLE has each own meaning, try to all of them coz it's very interesting.

[JNE 10001EDF]

Ok you've passed the first PROTECTION let's JUMP to 10001EDF

:10001EDF 68D0660110              push 100166D0
:10001EE4 E8C77B0000              call 10009AB0                         ??????????????
:10001EE9 83C404                  add esp, 00000004
:10001EEC 8BF0                    mov esi, eax                          
:10001EEE 85F6                    test esi, esi                           
:10001EF0 7549                    jne 10001F3B                            

We still don't want EAX containing 0 after the CALL 10009AB0, coz if EAX = 0 then ESI = 0 too, so we don't JUMP to 10001F3B, that mean a STUPID MESSAGE will appears.

The JNE 10001F3B is the FINAL CHECK if you PATCH this ONE, then everything is FINE, but that's not our purpose isn't it, we want a REAL SERIAL NUMBER so we can register it at NUMEGA's PAGE (that is what we really want).


:10009AB0 83EC34                  sub esp, 00000034
:10009AB3 33C0                    xor eax, eax


:10009B0F 83C408                  add esp, 00000008
:10009B12 85C0                    test eax, eax
:10009B14 7408                    je 10009B1E

A very long long TRACE MAN and I'm tired with this one !!! Anyway the JE 10009B1E is a USELESS checking, you'll jump right here, right now:

:10009B1E 6840630110              push 10016340

* Reference To: KERNEL32.LoadLibraryA, Ord:018Eh                  ___
                                  |                                  |
:10009B23 FF15D4E10110            Call dword ptr [1001E1D4]          | Checking for UTILITY.DLL
:10009B29 8BF8                    mov edi, eax                       |  
:10009B2B 85FF                    test edi, edi                      |
:10009B2D 752F                    jne 10009B5E                     __|

When you are in SOFTICE you'll get a message like this : WINICE:Load 32 ........ bla bla bla bla ........ Mod=UTILITY


If you wanna get more information about the DLL that's being loaded, type MOD UTILITY you'll see the PATH of that DLL and some usefull INFO. So that's only a checking whether your DLL exist or not. If NOT you'll get a messagebox with the ERROR VALUE.
Coz we have the DLL sitting down nicely at our HD so let's continue.

* Possible StringData Ref from Data Obj ->"DigitCheck"

:10009B5E 68AC3F0110              push 10013FAC
:10009B63 57                      push edi

* Reference To: KERNEL32.GetProcAddress, Ord:0115h
:10009B64 FF15C4E10110            Call dword ptr [1001E1C4]
:10009B6A 85C0                    test eax, eax
:10009B6C 740E                    je 10009B7C
:10009B6E 8D4C2408                lea ecx, dword ptr [esp+08]    
:10009B72 51                      push ecx
:10009B73 FFD0                    call eax                    --------->  The last CALL 
:10009B75 83C404                  add esp, 00000004
:10009B78 8BF0                    mov esi, eax                          
:10009B7A EB2D                    jmp 10009BA9                         RETURN from CALL

The CALL EAX is a CALL to UTILITY.DLL, we are now inside that DLL. This is where the comparison is located.


Exported fn(): DigitCheck - Ord:0001h

:10001110 56                      push esi
:10001111 B9FFFFFFFF              mov ecx, FFFFFFFF                                 


:1000113D E87E010000              call 100012C0               GENERATE THE REAL SN#
:10001142 33C0                    xor eax, eax                --->EAX = 0 (Begin with first one)
:10001144 8A8814B30010            mov cl, byte ptr [eax+1000B314]             |ROUTINE to
:1000114A 328810B30010            xor cl, byte ptr [eax+1000B310]             |GENERATE THE REAL
:10001150 0A0D17B30010            or cl, byte ptr [1000B317]                  |SN# AGAIN and
:10001156 888818B30010            mov byte ptr [eax+1000B318], cl             |save them at
:1000115C 80C930                  or cl, 30                                   |[1000B318]
:1000115F 888818B30010            mov byte ptr [eax+1000B318], cl             |   
:10001165 80F939                  cmp cl, 39                                 |Is it a Number ?        
:10001168 7609                    jbe 10001173                               |No, then convert       
:1000116A 80C107                  add cl, 07                                 |to Alphabet             
:1000116D 888818B30010            mov byte ptr [eax+1000B318], cl      ______|Save them.      					                                      

:10001173 8A90E8B20010            mov dl, byte ptr [eax+1000B2E8]    OUR DUMMY CODE
:10001179 8A8818B30010            mov cl, byte ptr [eax+1000B318]    REAL 
:1000117F 3AD1                    cmp dl, cl                         COMPARE them. EQUAL ?
:10001181 740C                    je 1000118F                        ______   
:10001183 80C920                  or cl, 20                                |IF not EQUAL
:10001186 A30CB30010              mov dword ptr [1000B30C], eax            |compare in lowercase
:1000118B 3ACA                    cmp cl, dl                               | 
:1000118D 7513                    jne 100011A2                       ______|BAD JUMP.    

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|                                                                     ___
:1000118F 40                      inc eax                                |  ONLY 4 times 
:10001190 A30CB30010              mov dword ptr [1000B30C], eax          |  comparison
:10001195 83F804                  cmp eax, 00000004                      |  for the PROTECTION
:10001198 7CAA                    jl 10001144                          __|

You can see that the REAL SN# we're looking at is saved at [1000B318] and OUR DUMMY CODE is at [1000B2E8], you must remember that your DUMMY CODE is 1900-123456-78 the comparison only COMPARES your last four char (in this case 5678) with the REAL ONES, If not EQUAL maybe in lowercase ...? , compare them in lowercase ...? still not EQUAL then XOR EAX, EAX and get out from the CALL. (Very BAD !)

The REAL SN# is generated from your other DUMMMY code, so you are wrong when thinking our rest CODE is GARBAGE.

In the comparison routine EAX is just a pointer: its job is to point at the NEXT char, you can see that INC EAX instruction in line 1000118F.



REGISTERING your copy at NUMEGA's Page


You must fill up the form with your new SN# at
then you'll see a BEAUTIFUL message like this :

NuMega Product Registration
Thank you, OCHE SATRIANI, for registering your NuMega solution. As a registered user, look forward to exciting updates and announcements.


Now you can UPDATE your SOFTICE at

I've concluded that the SN# 1900-xxxxxx-xx is only for UPDATING SOFTICE to version 3.24 but there is a GORGEOUS thing happen when I tried the SN# 4xxx-xxxxxx-xx.

Update Status
The following component versions are available:

* I have told you before that each number from the TABLE has its own meaning, so TRY IT or LOOSE IT!


Better be QUICK don't let NUMEGA recognize your PIRATE SN# again, coz it's

OE'97 ITS 4397100xxx