MultiSMS Express v6.0.9 Retreiving a valid serial and algorithm explained. by L!M!T [The Exterminators] March 1999 ------------------------------------------------------------- Program info for MultiSMS Express v6.0.9 Available @ : http://tele-servizi.com/multisms/Index.html Size : 2.73 Mb Language : Italian Get the VB6IT.dll too just in case. ------------------------------------------------------------- Tools used: SmartCheck v6.01 ------------------------------------------------------------- The First Encounter ------------------- Install MultiSMS Express v6.0.9. Just answer 'Esci' to the questions during the installation procedure, I believe it means 'OK'. Well.. from the information displayed during the install, we could see that the MSVBVM60.DLL and other Visual Basic runtime files were copied. In other words, this utility is programmed in Visual Basic, therefore we're gonna use SmartCheck to try to get our serial and understand the algorithm used to calculate a valid serial. Let's go... When the main window appears, press 'Sistema' and choose 'Registrazione programma'. Another window pops up with some kind of EULA in Italian. Press 'Accetto', and you're at the registration window. In the first field you see a 'Numero di serie:' (serial number) and in the other field you are supposed to enter your 'Numero di registrazione' (registration number). Just enter a number and hit 'Registra' (Register) and a window will bark at you in Italian saying that the number you entered was incorrect. I don't understand Italian so good, so we'll let our good friend SmartCheck do the translation for us. The Dissecting -------------- Start SmartCheck, and make sure it is configured as below; Program Settings; Error detection - Check all boxes except 'Report errors immediately' Advanced - Check the 4 first boxes. Make sure that 'Suppress system API and OLE calls' is NOT checked. Reporting - All boxes checked, except for 'Report MouseMove events from OCX controls' Make sure to visit Eternal Bliss at http://crackmes.cjb.net for more SmartCheck usage and configuration. Load MultiSMS into SmartCheck by choosing 'File', 'Open' and choose 'MultiSMS.exe'. Start it by pressing F5. Once you can see the main window of MultiSMS, press the button with the red square (STOP) to terminate MultiSMS as we don't need to do anything more with MultiSMS. Otherwise you'll have zillion's of lines in SmartCheck with Timer1_Timer. This Timer handles the rotation of the picture in the top right corner in MultiSMS and that is not interesting. Why we terminate MultiSMS so early in the process is, that your serial is calculated at startup. Normally (read: other VB prog's) you would have to click your way to the registration window, enter a fake serial and then terminate the program to be able to see the routines in SmartCheck. In SmartCheck again, go to 'View' and make sure that the following are 'checked'; 'Arguments', 'Sequence Numbers' (not necessary, but it adds some orientation) and 'Suppressed Errors'. Now, go to 'View' again and choose 'Show specific errors and events' if it's not checked already. The left window of SmartCheck is the 'Thread' of the program. It's here you see what the program is doing. The right window displays arguments, values, strings and so on. Now, in the left window, look for 'MultiSMS_Load' and click the plus sign next to it. If you can't see that, make sure that 'Show specific errors and events' in the 'View' menu of SmartCheck is checked. When you've clicked that, a huge amount of lines suddenly were added. Loads of Chr$ commands and further down, some GetPrivateProfileString commands. Then, a shitload of Double, DoEvents and Timer commands. Not interesting. Anyway, continue down until you see 'Registrazione_Load' and click the plus sign to expand the branch. All those 'Form1_Load', 'Registrazione_Load' and 'MultiSMS_Load' are forms (windows) that is displayed as the program loads or when you click a button and a new window appears. The first 750 lines in this branch calculates the 'Numero di serie' by getting your ProductId, ProductIdKey of the Windows installation and the volume information from your harddrive. Since the serial number is based on the sum from this algorithm (Numero di serie), the only thing we need is the result of this calculation. That's why we're not interested in it. But feel free to take a look at it. Almost directly after the GetVolumeInformation is a 'Str$' command, move on to the next 'Str$' further down in the branch. This should say something like x.xxxx+00e where the x's are numbers. If you click on this 'Str$' command, the value will be displayed in the right window. Do you recognize that sequence of numbers? You are absolutely correct. It's the first 10 numbers in our 'Numero di serie:'! After this follows some 'Mid$', 'Asc$' and a few 'Val$' commands and after the last 'Val$' in this sequence there is a 'Str$' command with a 'ByRef' value. Click that line and watch the right window. There, my friend, is your 'Numero di registrazione'! Don't type the dot in the end of the number when you register. The registration number has been calculated... So, how is this done? Algorithm Explained ------------------- What you see in the left window now, is that some 'Asc$' commands are executed. The 'Asc$' command in Visual Basic gets the ASCII value from a given character. The problem now, is that you can't 'see' what's happening with those values that are extracted from the 'Numero di serie:' To get a better view, do this; Click the SECOND 'Str$' command AFTER the GetVolumeInformation command. Yes, we're back at the first ten numbers of our 'Numero di serie:'. The line should have turned blue. Now, go to 'View' and choose 'Show all events'. The screen changes slightly and SmartCheck is working... I hope you clicked the line, otherwise you could be lost... Really lost. Hopefully, you can still see the same numbers in the right frame and the blue line over the 'Str$' command in the left frame. The screen has changed quite much now, and what you see now is the calls to MSVBVM60.DLL and which functions that are called. The 'Numero di registrazione' calculation begins at the FIRST 'Mid$' command AFTER the 'Numero di serie' 'Str$' command. Mid$(String:"1990944400", long:1, VARIANT:Integer:1) (1990944400=I'm using this Numero di serie for explanation, you'll have a diff. one) This means, what is the first (long:1) char in the String:"19909..." ? How many chars do you want from position 1 in the string (VARIANT:Integer:1) One char from position 1, result is 1 The __vbaStrMove put's this char away for later use. Asc$(String:"1") returns Integer:49 This means, what is the ASCII value for the string "1" The answer is 49 (returns Integer:49) __vbaVarMove moves the result (49) for later use __vbaVarAdd tries to add our result to the prior one. Since this was our first char, the formula is 0 + 49 = 49 (prior char+present char) __vbaVarMove moves the result (49) for later use __vbaVarForNext I believe this is a loop function (For, Next) moving to the next char in the 'Numero di serie' __vbaI4Var Don't know what this one does.. Next char; Mid$(String:"1990944400", long:2, VARIANT:Integer:1) What is the second (long:2) char in the String:"19909..."? We want one char this time too (VARIANT:Integer:1) Take one char from position 2 in the String:"19909..." Result is "9". .... .... Asc$(String:"9") returns Integer:57 The ASCII value for string "9" Result is 57. (returns Integer:57) __vbaVarMove moves the result (57) for later use __vbaVarAdd adds our prior ASCII result (49) to the present (57) __vbaVarMove moves the result (106) for later use __vbaVarForNext Moves to the next loop function This is done for the ten first numbers (chars) in the 'Numero di serie' string. It retrieves the ASCII value for each char, adding it to the next char's ASCII value, and so on, through the ten first chars in the 'Numero di serie' string. Further down, you'll come across some __vbaVarMul functions. The 'Mid$' prior to this __vbaVarMul function call takes the first NUMBER in the 'Numero di serie' (1990944400), which is 1, and moves (__vbaStrMove) it for later use. Now check the sequence of the __vbaVarMul functions and what they do; __vbaVarMul(VARIANT:Double:1.99094+00e, VARIANT:Integer:520) | The sum of the ASCII values------------------------------^ This takes our 'Numero di serie'(1.99094+00e) and multiplies it with the sum of each char's ASCII value from 'Numero di serie', char by char (520) __vbaVarMul(VARIANT:Double:1.03529e+012, VARIANT:Double:1) | | Value has changed!-------------^ | (this is the result from the prior __vbaVarMul) | | The first NUMBER in the 'Numero di serie'---------------^ (1990944400, The '1') This takes the result of the prior __vbaVarMul (1.99094+00e * 520 = 1.03529e+012) and multiplies it with the first NUMBER (not ASCII value) of the 'Numero di serie' sequence. Hence the 'Mid$' prior to the first __vbaVarMul. Next line; ---------- __vbaR8Var(VARIANT:Double:1.03529e+012) This takes the result from the last __vbaVarMul and multiplies it with 5. The next 'Str$' command; ------------------------ Str$(VARIANT:ByRef Double:5.17646e+009) __vbaStrMove(String:"5176455440" ......) Moves the result of the __vbaR8Var and saves it for further use The next command; ----------------- Trim$(String:"5176455440) Trims the string. Here is the 'Numero di registrazione'! Algorithm... ------------ a = ASCII value of char[1]+char[2]+char[3]......+char[10] b = a * Numero di serie's FIRST TEN NUMBERS! b = b * First NUMBER in 'Numero di serie' code = b * 5 You might want to remove the three last digits from [code] to get a valid 'Numero di registrazione'. Example: 1990944400 * 520 * 1 = 5176455440000 Remove the three zero's at the end and this is a valid 'Numero di registrazione'! (for the 1990944400 Numero di serie...) 'Knowledge is neither given nor taken. It is earned.' Regards, L!M!T [TEX]