About this tutorial:
Tutorial:Keygenning with SmartCheck:Yam 2.1.0 Target:Yam 2.1.0(Please search on Tucows) Tools:SmartCheck 6.0x Date:10 December 2000 Descriptions&Comments:This is yet another tutorial on keygenning a Visual Basic 5 program with SmartCheck as the main tool. By now, I shall have written a tutorial on how to (perfectly)crack VB programs using SoftICE but since the name/serial protection algo of Yam is (quite)easy, and does not require SoftICE to crack it, I think it is best to be cracked in SmartCheck. Besides showing you the basic power of SmartCheck, in this essay, I hope to show you more about SmartCheck, especially the Show All Events option which was not presented on my previous essay entitled "Keygenning with SmartCheck". Protections:Name/serial, Microsoft Visual Basic 5 Disclaimer:This file is used for educational purposes only. Any misuse of the information presented here is not my responsibility. Copyright information:This tutorial is copyright © ManKind Starting words:
|
The process:
I will not show you how to serial fish, our main purpose here is to keygen. Make sure you have configured SmartCheck correctly for cracking purposes before following this part, you should visit Eternal Bliss's site(http://vipatcher.cjb.net) and get his tutorials if you haven't configured it(well, not only for configuration purpose actually, there are other priceless stuffs there by Eternal Bliss). Use SmartCheck to open(load) Yam's executable file, after which a child window will be minimized at the bottom left of SmartCheck windows by itself, then run(Program -> Start) our executable and another child window shall pop up(by the caption of Program Results), maximize that window because we are going to work with it. Once you run the executable, the register dialog of Yam will pop up, so, you shall immediately try to register with a fake registration information(to pass length check to be able to go to calculation routine, etc.). I use the following fake registration information(of course you can use any other but my explanation will be based on my own registration information):
Name:ManKind
Reg. Number:23199981
After you try to register and have received the bad_boy message, you can terminate Yam because we have already enough information for us(in other cases when you are cracking on your own, you shall investigate first whether you have already have enough information). Look at the left side in the Program Result's window(I want to add something here though probably unappropriate, the left side of the window shows APIs and function calls while the right side of the window will show variables' values, etc.) and find the events done after we pressed the Register button. In this case, it is cmdRegOK_Click(please don't ask me how do I know, it is easy to know), expand it and you shall see the following listing(digitally mastered for as original look as the original listing in SmartCheck with Show Errors and Specific Events option, hehe :D. my comment is preceeded by <-- ):
[-] cmdRegOK_Click | cmdRegOK.Caption | txtName.Text | txtNumber.Text | OnError | Len returns LONG:7 <-- Len is a function to obtain length of a string, 7 is the length of our name | Long (7) --> Integer (7) <-- convert long variable type to integer type | ReDim <-- re-allocate memory or stuffs that's not really important to us | Mid <-- function to extract a char from a string(in this case, our name) | Asc returns Integer:77 <-- Asc is a function to obtain ascii value of a char, 77 is ascii of "M" | Mid | Asc returns Integer:97 <-- ascii of "a" | Mid | Asc returns Integer:110 <-- ascii of "n" | Mid | Asc returns Integer:75 <-- ascii of "K" | Mid | Asc returns Integer:105 <-- ascii of "i" | Mid | Asc returns Integer:110 <-- ascii of "n" | Mid | Asc returns Integer:100 <-- ascii of "d" | IsNumeric returns Boolean:True <-- check if our serial(Reg. Number) is of a numeric value | Len returns LONG:6746716 <-- look at right side child window and you'll see 15264 which is our real serial | Len returns LONG:6746700 <-- do the same as above and you'll see our fake serial |+frmReg.Visible <-- False(Boolean) |Thread 1 [thread id:4290845821 (0xFFC11C7D)] |Thread 0 [thread id:4290961629 (0xFFC2E0DD)] | MsgBox returns Integer:1 <-- bad_boy msg | frmReg.Visible <-- True (Boolean) | txtName.Text <-- "" (String) | txtNumber.Text <-- "" (String) | txtName.SetFocus [-] cmdRegOK_Click
We see nothing about the keygenneration routine over here except that it uses the ascii of our name. Without closing the Program Results window, go to the beginning of the cmdRegOK_Click event(the cmdRegOK.Caption event), choose the Show All Events option(this option is some kind of power-up for SmartCheck to show clearer and more detailed listing, hehe :D ) and the following listing shall be presented to you(some unimportant parts of listing removed):
[-] cmdRegOK_Click | Len returns LONG:7 <-- length of name | Long (7) --> Integer (7) |+ReDim |+Mid | __vbaStrMove returns DWORD:441664 | __vbaStrMove returns DWORD:441664 |+Asc returns Integer:77 <-- ascii of "M" | __vbaVarMove returns DWORD:473264 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 77 is multiplied with 1 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:44169C |+__vbaStrMove returns DWORD:44169C |+Asc returns Integer:97 <-- ascii of "a" | __vbaVarMove returns DWORD:473274 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 97 is multiplied with 2 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:441664 |+__vbaStrMove returns DWORD:441664 |+Asc returns Integer:110 <-- ascii of "n" | __vbaVarMove returns DWORD:473284 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 110 is multiplied with 3 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:44169C |+__vbaStrMove returns DWORD:44169C |+Asc returns Integer:75 <-- ascii of "K" | __vbaVarMove returns DWORD:473294 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 75 is multiplied with 4 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:441664 |+__vbaStrMove returns DWORD:441664 |+Asc returns Integer:105 <-- ascii of "i" | __vbaVarMove returns DWORD:4732A4 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 105 is multiplied with 5 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:44169C |+__vbaStrMove returns DWORD:44169C |+Asc returns Integer:110 <-- ascii of "n" | __vbaVarMove returns DWORD:4732B4 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 110 is multiplied with 6 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 |+Mid | __vbaStrMove returns DWORD:441664 |+__vbaStrMove returns DWORD:441664 |+Asc returns Integer:100 <-- ascii of "d" | __vbaVarMove returns DWORD:4732C4 | __vbaVarMul returns DWORD:66F25C <-- look at right window and you'll see that 100 is multiplied with 7 | __vbaVarAdd returns DWORD:66F24C <-- add the results of multiplication to a variable | __vbaVarMove returns DWORD:66F274 | __vbaVarAdd returns DWORD:66F25C <-- add 12478 to the variable, the value after addition happens to be our real serial | __vbaVarMove returns DWORD:66F294 |+IsNumeric returns Boolean:True | ------------snipped-------------- | ------------snipped-------------- [-] cmdRegOK_Click
Well, what a clear and nice listing. No, not very clear actually, I am able to comment the API function calls and what they are doing is because I have tried to evaluate what it is doing with the help of the right child window(which should be showing the values of variables, constants, etc. as I said earlier, remember?) of Program Results window(you shall do the same when you are cracking on your own in SmartCheck, evaluate it!). I hope you have seen the keygenneration routine based on the above listing and my comments but if you don't yet(which is good because it makes you THINK :D ), the following explanation of the keygenneration routine in plain text and later a small C++ snippet of the keygenneration routine shall help you very much:
First, it initialize a loop to loop as many times as the length of name and in each loop each character's(of name) ascii is multiplied with a value(which increases by 1 in each loop, we regard it as X) and the results of the multiplication is added up in a variable which in the end is again added with a constant value of 12478. Since the value(of X) which was multiplied with every ascii of chars is equal to the value of the counter in each loop, we can safely assume that the value is also the counter(which is used to decide whether to continue looping or not and extract certain chars from name in the Mid function) of the loop(true only in Visual Basic language and not Visual C++ because the first char of name starts at location 0 unlike VB
which starts at 1).
// assuming name is a char variable type which holds our name for (i=0, finalserial=0;i<len;i++) { finalserial += name[i] * (i+1) ; // i have to do i+1 because for Visual C++, name[0] is the first char of name(not name[1] unlike VB) } finalserial += 12478 ;
Well, it is so simple(the keygenneration routine), barely a few lines of code in C++ is enough to calculate our real serial. I will end this essay with a full source of an example keygen in C++(which I compile on my Visual C++ 6, it may work on other compilers too, but none are tested by me :D ):
#include <stdio.h> // printf, gets, etc. #include <conio.h> // getche() #include <string.h> // strlen int main() { char name[255] ; long i, finalserial, len ; printf("++++++++++++++++++++++++++++++++++") ; printf("\n+ KeyGen for Yam 2.1.0 +") ; printf("\n+ by ManKind on 10 December 2000 +") ; printf("\n++++++++++++++++++++++++++++++++++") ; printf("\nName: ") ; gets(name) ; len = strlen(name) ; if (len > 0) { for (i=0, finalserial=0;i<len;i++) { finalserial += name[i] * (i+1) ; } finalserial += 12478 ; printf("Reg. Number: %d", finalserial) ; getche() ; return 0 ; } else { printf("Bad name! Please try again!") ; getche() ; return 0 ; } } |
By the way, try registering it with the keygen and surprisingly it will display this message "Thanks for registering Yam, although I'm sure you didn't pay for it. :)". How did it know we didn't pay for it(hehe :D, ask the author...)? One last thing, the registration information(if valid) is stored in file named yam.reg stored in the same directory as the Yam's executable.
Extra notes:
Recently, I have read a few comments by tutorials' readers concerning the quality of cracking tutorials available. Quite a few of them said that there are some tutorials that are useless as they teach nothing and are just a scratch work by the author and I am greatly disturbed by those statements. I am not sure if my essays fall into that kind of category of useless essays but the truth is that I have tried my best to make every of my essays(at least those of my latest ones) resourceful and not just any essays that teach nothing. So, I will like to call out to all my essays' readers(if there are any, hehe :D ) to send me suggestions, comments, opinions and feedbacks so that I know whether my essay and writing style is acceptable to you(that means, you can understand what I try to present, learn something and not bored by my texts) or do they need some change. I am open to positive remarks, I will like to receive critics and is willing to change and improve if my essays and writing style are really that bad rather than continue writing USELESS essays. Thanks(and hope that I am not one of the authors who write useless essays :D )...
Well, whether or not we crack this program is not important at all here. I just want you to understand the approaches I have taken and the reasons for doing so and to learn from the methods I have shown you. However you must be clever enough to take other approaches and methods(based on your logics) when dealing with other targets. Ability to do so will make you a great cracker as tutorials I believe are not used to teach you how to crack only a specific target, they show you the methods, approaches and logics available while cracking and expect you to apply them on other targets with your own intelligence...
Ending:
Thanks and greetz to:
+ORC, +HCU, Sandman, HarvestR, tKC, ytc_, Punisher, Kwai_Lo, TORN@DO,
CrackZ, cLUSTER, LaZaRuS, mISTER fANATIC, yes123, WhizKiD, Volatility,
ACiD BuRN, Eternal Bliss, R!SC, Kwazy Webbit, +Mammon, MisterE, Shadow, Falcon, ^tCM^, WaJ, egis, Borna Janes, CyberBlade, Sheep140/Reclaim, josephCo, Kathras, +tsehp, Predator, tscube, AB4DS(Death), douby, Steinowitz, Lord Soth, seifer666, Latigo, Dawai, Lucifer48, NoodleSpa, Mercution, NeuRaL_NoiSE, Fravia+, [dshadow], yAtEs, Duelist, Alpine, hutch, flag eRRatum, Nitrus, LiQUiD8, +Frog's Print, Muad`Dib, Acid_Cool_178, Iczelion, Razzia, wOODY^dRN, Warezpup, Bomber Monkey, XMen, llama and other crackers, individuals and organisations who have helped me, either directly or indirectly.
Service for Mankind
ManKind
mankind001@bigfoot.com