查看原文
其他

记一次逆向FreeRes0.94注册过程及注册机

2018-04-06 MTRush 看雪学院


1、用PEiD检测,发现加了壳:ASPack 2.001 -> Alexey Solodovnikov,用esp定律脱了并修复IAT。 继续用PEiD检测,发现是用”Borland Delphi”写的。


2、根据Delphi的特点,定位到注册界面的”确定”按钮响应函数在位置:0x004C2D68

       

      

用IDA分析这个注册函数

      

      

发现除了把注册名字和注册码写入注册表之后就没干其他事情了,然后继续找检测注册码的关键点。刚好用到“建立可编辑资源“这个功能的时候出现了如下的提示框:


      

      

通过这个现象说明在这个功能上做了注册的检测,根据上面找”确定”按钮同样的方法找到”建立可编辑资源”这个菜单的响应函数在:0x004CD2D0


      

      

继续用IDA分析这个函数,定位到sub_4BBC00为检测注册码的函数

      


3、分析地址0x004CD332处调用的 CheckCode_4BBC00 这个检测函数     

     

    


4、注册机,注册机用一个类简单的封装了一下,代码如下,完整源码在附件


class KeyGen
{

public:
   KeyGen();
   ~KeyGen();

public:
   int ReverseRegCode(const std::string &strUser, const std::string &strMachine,
       DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, std::string &RegCode)
;
   
protected:
   int Format_Name(const std::string &strUser, const std::string &strMachineCode, std::string &str_user_mc);
   int Calc_Name(const std::string &str_user_mc, DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34);

   /*
   int Format_Calc_Name(const std::string &strUser, const std::string &strMachineCode,
       DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34);
   int Calc_Name_Again(unsigned char *pc_in, unsigned char *&pc_out);

   //IDA里面的Calc_RegCode,反算注册码部分算了两轮,分别是下面两个函数
   int CalcRegCodeFirstRound(const std::string &strRegCode, unsigned char*&pc_out);
   int CalcRegCodeSecondRound(DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_in, DWORD dw_8C34, unsigned char *&pc_out);


   int sub_4BB780(unsigned char c);
   int sub_4BB794(unsigned char c);

   int Calc(const std::string &strUser, const std::string &strMachineCode);
   */


   bool DfsRegCode(DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, int index);
   int ReverseOneChar(unsigned char fc, unsigned char sc, unsigned char &c_out);
   
private:
   unsigned char *m_VisiableChar;
   unsigned char *m_pName;
   unsigned char *m_RegCode;
   unsigned int  m_vc_len;
   unsigned int  m_name_len;
};

int KeyGen::ReverseRegCode(const std::string &strUser, const std::string &strMachineCode,
   DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, std::string &RegCode)
{
   std::string str_user_mc = "";
   
   Format_Name(strUser, strMachineCode, str_user_mc);

   unsigned char *pName = NULL;
   Calc_Name(str_user_mc, dw_3D6, dw_3183, pName, dw_8C34);

   unsigned char *pRegCode = new unsigned char[0x29];
   memset(pRegCode, 0, 0x29);

   unsigned char visiable_char[] = {
       'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z',
       'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
       '1','2','3','4','5','6','7','8','9','0','~','`','!','@','#','$','%','^','&','*','(',')','-','_','=','+',
       '[','{',']','}',';',':','\'','\"','\\','|',',','<','.','>','/','?',' ','\0' };
   

   m_VisiableChar = visiable_char;
   m_pName = pName;
   m_RegCode = pRegCode;

   bool b_find = false;
   m_name_len = strlen(str_user_mc.c_str());
   m_vc_len = strlen((char*)visiable_char);


   b_find = DfsRegCode(dw_3D6, dw_3183, dw_8C34, 0);

   if (b_find)
   {
       RegCode = (char*)pRegCode;
   }
   
   delete[] pName;
   pName = NULL;

   delete[] pRegCode;
   pRegCode = NULL;
   
   return 0;
}
int KeyGen::Format_Name(const std::string &strUser, const std::string &strMachineCode, std::string &str_user_mc)
{
   str_user_mc = strUser.c_str();
   str_user_mc += strMachineCode.c_str();

   size_t len = strlen(str_user_mc.c_str());
   
   if (len <= 0x12)
   {
       char cb = str_user_mc[len - 1];
       char var_D = cb;
       int var_14 = 0;
       if (cb <= 0x7F)
       {
           var_14 = 1;
       }
       else
       {
           var_14 = -1;
       }

       int var_15 = 0x12 - len;
       for (size_t i = 0; i < var_15; i++)
       {
           cb += var_14;
           str_user_mc.insert(str_user_mc.begin(), 1, cb);
       }

       str_user_mc.insert(str_user_mc.begin(), 1, var_D);
   }
   else
   {
       unsigned char cb = str_user_mc[0x12];
       if (len >= 0x14)
       {
           unsigned char cd = '\0';
           int var_15 = len - 0x14 + 1;
           int pos = 0x14;
           for (size_t i = 0; i < var_15; i++)
           {
               cd = str_user_mc[pos - 1];
               if (cb > cd)
               {
                   cb -= cd;
               }
               else
               {
                   cd -= cb;
                   cb = cd;
               }

               pos++;
           }
       }

       str_user_mc = str_user_mc.substr(0, 0x12);
       if (cb==0)
       {
           cb = 0xFF;
       }

       str_user_mc.insert(str_user_mc.begin(), 1, cb);
   }

   if (len > 0xFF)
   {
       len = 0xFF;
   }

   char var_28 = len;
   str_user_mc.insert(str_user_mc.begin()+1, 1, var_28);

   return 0;
}

int KeyGen::Calc_Name(const std::string &str_user_mc, DWORD dw_3D6, DWORD dw_3183, unsigned char *&pc_out, DWORD dw_8C34)
{
   pc_out = NULL;
   int len = strlen(str_user_mc.c_str());
   if (len <= 0)
   {
       return -2;
   }

   pc_out = new unsigned char[0x29];
   memset(pc_out, 0, 0x29);
   int var_9 = len;
   unsigned char c = 0;

   DWORD var_3D6 = dw_3D6;
   DWORD var_tmp = dw_3D6;

   for (size_t i = 0; i < len; i++)
   {
       c = str_user_mc[i];
       var_tmp = var_3D6;
       var_tmp >>= 0x8;
       c ^= (var_tmp & 0xFF);
       pc_out[i] = c;

       var_3D6 += pc_out[i];
       var_3D6 *= dw_3183;
       var_3D6 += dw_8C34;
   }

   pc_out[len] = '\0';

   return 0;
}

bool KeyGen::DfsRegCode(DWORD dw_3D6, DWORD dw_3183, DWORD dw_8C34, int index)
{
   if (index == m_name_len)
   {
       return true;
   }

   bool b_find = false;
   unsigned char c_out = 0;
   unsigned int var_3D6 = dw_3D6;
   for (size_t i = 0; i < m_vc_len; i++)
   {
       for (size_t j = 0; j < m_vc_len; j++)
       {
           ReverseOneChar(m_VisiableChar[i], m_VisiableChar[j], c_out);

           unsigned int var_tmp = 0;
           unsigned char c_tmp = c_out;

           var_tmp = var_3D6;
           var_tmp >>= 0x8;
           c_out ^= var_tmp;

           if (c_out == m_pName[index])
           {
               m_RegCode[2 * index] = m_VisiableChar[i];
               m_RegCode[2 * index + 1] = m_VisiableChar[j];

               var_3D6 += c_tmp;
               var_3D6 *= dw_3183;
               var_3D6 += dw_8C34;

               b_find = DfsRegCode(var_3D6, dw_3183, dw_8C34, index+1);
               if (b_find)
               {
                   break;
               }
               else
               {
                   var_3D6 = dw_3D6;
               }
           }
       }

       if (b_find)
       {
           break;
       }
   }

   return b_find;
}

int KeyGen::ReverseOneChar(unsigned char fc, unsigned char sc, unsigned char &c_out)
{
   unsigned char cb = '\0';
   unsigned char ca = '\0';
   unsigned char cd = '\0';
   unsigned char cc = '\0';
   unsigned char var_9 = 0;
   unsigned char var_A = 0;

   cb = fc;
   ca = sc;

   cd = ca;
   cd &= 0x4F;
   var_9 = cd;
   
   cd = ca;
   cd &= 0x30;
   cd >>= 0x4;
   var_A = cd;

   unsigned char temp = ca & 0x40;
   if (temp == 0)
   {
       cb = 0;
   }
   else
   {
       if (var_9 < 0x43)
       {
           ca = 0x43;
           ca -= var_9;
           var_9 = ca;
           cc = var_9;
           cb <<= cc;
           cb |= var_A;
       }
       else if (var_9 > 0x43)
       {
           var_9 -= 0x43;
           cc = var_9;
           ca = cb;
           ca >>= cc;
           cb = ca;
       }
       else
       { }
   }

   c_out = cb;

   return 0;
}

//输入注册名字和机器码
int main(int argc, char** argv)
{
   if (argc < 3)
   {
       return 0;
   }

   std::string RegCode = "";

   //第一个参数为注册名字,第二个参数为机器码
   KeyGen kg;
   kg.ReverseRegCode(argv[1], argv[2], 0x3D6, 0x3183, 0x8C34, RegCode);

   printf("regcode=%s\n", RegCode.c_str());

   return 0;
}





本文由看雪论坛 MTRush 原创

转载请注明来自看雪社区



往期热门阅读:


点击阅读原文/read,

更多干货等着你~

扫描二维码关注我们,更多干货等你来拿!


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存