I reverse engineered a program protection algorithm and got the result in this source file I wrote, but I would know this type of protection.Please tell me what is the type of this protection ? And is there any ability to create a keygen of this algorithm ?#include <stdio.h>#include <string.h>char* transformStrip = 123456789ABCDEFGHIJKLMNPQRSTUVWXYZ;char* myusername = MYUSERNAME;char* myserial   = MYSERIAL33222222222222222;//OKint TransformChar(char c){    for(int i=0;i<0x22;i++)    {        if(transformStrip[i] == c)            return i;    }    return 0;}//OKbool MagicCalculator1(char* magicBuffer, int number){    int a = 0;    //int rez = 0;    for (int i=0;i<0x20;i++)    {        int rez = (unsigned char)magicBuffer[i];        rez *= number;        rez += a;        magicBuffer[i] = (unsigned char)rez;        if(rez >= 0x100)        {            a = rez;            if(a < 0)                a += 0xFF;            a >>= 8;        }else            a = 0;    }    return (bool)a;}bool MagicCalculator2(char* magicBuffer, int position){    int a = 0;    for (int i=0;i<0x20;i++)    {        int rez = magicBuffer[i];        a += rez;        rez = position + a;        magicBuffer[i] = (char) rez;        position = 0;        if(rez >= 0x100)        {            a = rez;        }else            a = 0;    }    return (bool)a;}// sizeof(magicBuffer) = 0x20// OKint SerialMagicGenerator(char* serial, char* magicBuffer, int number){    int serialLength = strlen(serial);    if (serialLength <= 0)        return 0;    for(int i=0;i<serialLength;i++)    {        char c = serial[i];        if (c != '\x20' && c != '\x2D')        {            int pos = TransformChar(c);            if (MagicCalculator1(magicBuffer, number))                return -1;            if (MagicCalculator2(magicBuffer, pos))                return -1;        }    }    return 0;}unsigned short MagicValidator(char* combinedBuffer, int number){    int c = 0;    if(number)    {        for(int i=0;i<number;i++)        {            int rez = ((unsigned char) combinedBuffer[i]) << 8;            c ^= rez;            for(int j=0;j<8;j++)            {                if(c & 0x8000)                {                    c += c;                    c ^= 0x1021;                }else                    c <<= 1;            }        }    }    unsigned short s = (unsigned short) ( ((c & 0xFF) << 8) | ((c & 0xFF00) >> 8) );    return s;}bool UsernameMagicVerifier(char* randomizedUsername, char* magicBuffer){    char combinedBuffer[0x20];    memset(combinedBuffer, 0, 0x20);    memcpy(combinedBuffer, randomizedUsername, 0x10);    memcpy(combinedBuffer + 0x10, magicBuffer, 0x10);    unsigned short mustHaveValue = (unsigned short) (MagicValidator(combinedBuffer, 0x1E) & 0x7FFF);    unsigned short foundValue =    (unsigned short) ((*(unsigned short*) (magicBuffer + 0xE)) & 0x7FFF);    return (mustHaveValue == foundValue);}bool FinalizerVerifier(void*a, void*b){    //assuming this always returns true    return true;}char RandomizedUsernameBuffer[0x10];char* RandomizeUsername(char* username){    memset(RandomizedUsernameBuffer, 0, 0x10);    int usernameLength = strlen(username);    if(usernameLength >= 1)    {        if(usernameLength < 0x10)        {            int size = (usernameLength >> 2) * 4;            memcpy(RandomizedUsernameBuffer, username, size);            memcpy(RandomizedUsernameBuffer + size, username + size, usernameLength & 3);            if( usernameLength + 1 < 0x10 )            {                char* ptr;                ptr = RandomizedUsernameBuffer + size + (usernameLength & 3) + 1;                for(int i=0;ptr<RandomizedUsernameBuffer+0x10;ptr++)                {                    if( username[i] != '\0')                    {                        *ptr = username[i];                        i++;                    }else                        i = 0;                }            }        }    }    return RandomizedUsernameBuffer;}bool SerialChecker(char* username, char* serial){    char magicBuffer[0x20];    memset(magicBuffer, 0, 0x20);    char* randomizedUsername = RandomizeUsername(username);    SerialMagicGenerator(serial, magicBuffer, 0x22);    if ( UsernameMagicVerifier(randomizedUsername, magicBuffer) )    {        return FinalizerVerifier(/*?*/NULL, /*?*/NULL);    }    return false;}int main(){    SerialChecker(myusername, myserial);    return 0;}
Can a keygen be created for this protection algorithm?
c;crackme;protection
Short, slightly snarky answer: yes, there must be a way to make a keygen. If there wasn't, the creators of the software themselves wouldn't be able to create keys to sell.Longer answer: If the software vendor wants the encryption to be non-identifiable for people who have reversed the decryption part, they need to use some assymetric key algorithm, where the public key is embedded into the software, and the private key stays with the vendor. There are well-known algorithms, and corresponding libraries, to do that, like RSA. However, those are not used in your program, once because they are too big, and also because they contain lookup tables which make them easily identifiable.From a first glance at your algorithm, there's nothing much happening that's too difficult to reverse. Your RandomizeUserName just seems to shuffle the bits of the user name in the same way that the keygen would; your MagicCalculator functions seem to check if the serial number is well-formed, for some definition of well-formed. Then, MagicValidator calculates what looks like a 16-bit CRC on the 16 bytes username + 14 first bytes of the serial, then compares that to bytes 15/16 of the serial.So, a keygen would have to:- perform the same calculation on a username that your RandomizeUserName does- invent 14 bytes of serial- generate the CRC from the randomized user name + serial, and put it into bytes 15/16- append 16 more bytes to the serial in a way that MagicCalculator1 and 2 are satisfied (return 0), choose any bytes you want to achieve this- undo SerialMagicGenerator to get a serial that includes blanks and dashes just like SerialMagicGenerator does.So, with a bit of experimenting and trial-and-error, it should be very well possible to make a key generator for this.Side note:I pondered for a while if it is morally ok to help someone with what  is clearly a precursor to software theft. Assuming, in the first  place, that the OP hasn't tried to invent a protection algorithm  himself, and opened this question to check how strong his protection  is. Unfortunately, even now in 2016, there seem to be lots of  programmers - and college spits out more of them every year - who  think that shuffle a few bits around, pepper with some self-invented  maths, and compile to machine language makes whatever they want to  achieve hard to crack. Of course, we of RE.SE all know it doesn't.In this case, the OP obviously isn't too experienced in reversing, or  he wouldn't have asked the question; still, he arrived at a point  where he's obviously 1-2 hours away from a working keygen. In  answering the question the way I did, i hope to make it obvious that  all the bit-shuffling in the protection algorithm won't help much.  If you want to prevent people from creating key generators for your software, use asymmetric encryption, and make sure your private key  doesn't get leaked, and if only one future software protection  coder reads this example and learns from it, then my answer will have  served its purpose.