一个含有crc32算法的CrackMe分析

exe文件的下载地址为: http://pan.baidu.com/s/1gfw0XKf

启动界面:
一个含有crc32算法的CrackMe分析_第1张图片
大概意思是输入用户名和序列号,检查是否匹配,现在用ida打开分析一下:
一个含有crc32算法的CrackMe分析_第2张图片

msg==0x111位处理传过来的WM_COMMAND消息

一个含有crc32算法的CrackMe分析_第3张图片

一个含有crc32算法的CrackMe分析_第4张图片
一个含有crc32算法的CrackMe分析_第5张图片
下面对关键的地方进行分析,F5大法:

size = GetDlgItemTextA(hWnd, 1004, name, 255);
// 取Name放到name数组里面
        if ( size >= 4 )      // 名字必须大于等于4
        {
          nameSize = size;
          codeSize[0] = GetDlgItemTextA(hWnd, 1005, code, 255);
          crc32Init();
          //对codeSize进行CRC32加密,且必须为0x2f6016f7
          //用python写个爆破脚本可得到codeSize为26
          if ( Funcrc32(codeSize) == 0x2F6016F7 )
          {
            RtlZeroMemory(byte_40347F, 8);//初始化0x40347f的8个字节
            byte_40347F[0] = code[8];           //取第9位  
            byte_40347F[1] = code[17];//取第18位
            crc32Init();
            //将第9位和第18组成的字节数组进行CRC32加密,且必须为0x242C1465
            if ( Funcrc32(byte_40347F) == 0x242C1465 )
            {
              //用python写个爆破脚本可得到9位和18位都为'-'
              //可得到Serial的格式为12345678-12345678-12345678
              RtlZeroMemory(&buffer1, 10);
              RtlZeroMemory(&buffer2, 10);
              cnt = 0;
              while ( 1 )
              {
                t = code[cnt];
                if ( t > '9' && t < 'A' )
                  break;
                if ( t < '0' || t > 'F' )       // 16进制检查
                  break;
                if ( ++cnt == 8 )
                {
                  count = 0;
                  v10 = 0;
                  buffer1_1 = &buffer1;
                  do
                  {
                    v10 *= 16;
                    v12 = code[count];
                    *buffer1_1 = v12;
                    if ( v12 < 'A' || v12 > 'F' )
                      v13 = v12 - '0';          // 不正常
                    else
                      v13 = v12 - '7';          // 正常
                    LOBYTE(v10) = v13 & 0xF | v10;
                    ++buffer1_1;
                    ++count;
                    step1 = v10;                
                  }
                  while ( count != 8 );
                  // 这个while循环将相应的16进制字符串转化为int类型
                  crc32Init();
                  crcName = Funcrc32(name);
                  //对name数组进行crc32加密,且必须等于Serial的第一部分
                  if ( step1 == crcName )       // 名字必须满足这个条件
                  {
                    v15 = 0;
                    v16 = &code[9];//Serial的第二部分的首地址
                    while ( 1 )
                    {
                      v17 = v16[v15];
                      if ( v17 > '9' && v17 < 'A' )
                        break;
                      if ( v17 < '0' || v17 > 'F' )
                        break;
                      if ( ++v15 == 8 )
                      {
                        cnt_1 = 0;
                        v19 = 0;
                        v20 = &buffer2;
                        do
                        {
                          v19 *= 16;
                          v21 = v16[cnt_1];
                          *v20 = v21;
                          *v16 = v21;
                          if ( v21 < 'A' || v21 > 'F' )
                            v22 = v21 - 48;
                          else
                            v22 = v21 - 55;
                          LOBYTE(v19) = v22 & 0xF | v19;
                          ++v20;
                          ++cnt_1;
                          step2 = v19;
                        }
                        while ( cnt_1 != 8 );
                        // 这个while循环将Serial第二部分的16进制字符串转化为int类型,并保存在step2变量里
                        crc32Init();
                        crcBuffer1 = Funcrc32(&buffer1);
                        if ( step2 == crcBuffer1 )
                        {
                         //Serial第二部分的值必须等于Serial第一部分CRC32加密后的值
                          crc32Init();
                          step2 = Funcrc32(&buffer2);
                          //对第二部分进行crc32加密,并且保存到step2变量里
                          v24 = 0;
                          v25 = &code[18];
                          while ( 1 )
                          {
                            v26 = v25[v24];
                            if ( (unsigned __int8)v26 > 0x39u && (unsigned __int8)v26 < 0x41u )
                              break;
                            if ( (unsigned __int8)v26 < 0x30u || (unsigned __int8)v26 > 0x46u )
                              break;
                            if ( ++v24 == 8 )
                            {
                              cnt_2 = 0;
                              v28 = 0;
                              do
                              {
                                v28 *= 16;
                                v29 = v25[cnt_2];
                                *v25 = v29;
                                if ( (unsigned __int8)v29 < 0x41u || (unsigned __int8)v29 > 0x46u )
                                  v30 = v29 - 48;
                                else
                                  v30 = v29 - 55;
                                LOBYTE(v28) = v30 & 0xF | v28;
                                ++cnt_2;
                                step3 = v28;
                              }
                              while ( cnt_2 != 8 );这个while循环将Serial的第三部分16进制字符串转换为int类型
                              // 
                              if ( (step2 ^ step1) == step3 )//最后一个条件step2和step1进行异或的值必须为step3
                              {
                                SetWindowTextA(hWnd, "GOOD JOB, MAN!");//成功
                                hCheck = GetDlgItem(hWnd, 0x3EE);
                                EnableWindow(hCheck, 0);// 禁用单击按钮
#求codeSize的脚本:
def     crc32(v):
        '''
        Generates the crc32 hash of the v.
        @return: str, the str value for the crc32 of the v
        '''
        return "%08X"%(binascii.crc32(v)&0xffffffff)
 for i in range(60):
            crc = crc32(binascii.a2b_hex('%02X'%i))
            #print crc
            if crc=='2F6016F7':
                print i
                break

#求第9位和第18位的脚本:
for i,j in itertools.product(string.printable,string.printable):
            crc =crc32(binascii.a2b_hex('%02X%02x'%(ord(i),ord(j))))
            if crc=='242C1465':
                print i,j
                break

#上面是确定Serial的长度和格式:12345678-12345678-12345678
#最后注册机为:
        import crypt,binascii,itertools
        name = raw_input('输入你的注册名(大于4):')
        c1 = crc32(name)
        print 'c1',c1,hex(int(c1,16))
        c2 = crypt.crc32(c1)
        print 'c2',c2,hex(int(c2,16))
        t = crypt.crc32(c2)
        c3 = '%08X'%(int(t,16)^int(c1,16))
        print 'Serial:',c1+'-'+c2+'-'+c3

你可能感兴趣的:(二进制)