这个KeygenMe的验证过程主要就是:利用username计算出一个20字节的数据,然后利用lic的32字节的数据同样计算出一个20字节的数据,如果相同,那么就成功。
利用username计算出20字节的过程是一个正向的过程,直接剥代码就搞定,这道题目的关键就是怎样利用username计算出的20字节的数据推出lic,因为lic有32字节的数据。表明上看来这是一个不可能的事情,因为20字节到32字节是一个扩充的过程,可是只要仔细分析lic把32字节压缩成20字节的过程,这个逆向过程其实是很简单的。
由于username的组成限定了只能在“ABCDEFGHJKMNPQRSTVWXYZ1234567890”这32个中选择,然后根据查表得出值,这个值才是验证计算过程需要使用的数据。
这里需要特别注意一点,这个值最大不超过32,也就是最大值是5位。这就是这个压缩过程的关键所在。一个字节有8位,用8位来存储5位的值,有3位是空闲的,这个压缩过程就是将这空闲的3位全部利用起来。20/32正好等于5/8,这就是最好的证明。实际上这个压缩过程是没有任何数据损失的!!!
仔细分析lic压缩的过程,实际上就是一个精心构造的过程,把所有的空闲3字节都填上数据。下表就是利用5个字节存储8个字节的构造(注意,这8字节的数据每个值都不超过32),整个20字节就是将这个过程重复4次。表中每个单元格表示压缩后数组的一位。
 1      2       3      4      5       6      7       8
(1-1  1-2  1-3  1-4  1-5)  (2-1  2-2  2-3     第1字节
2-4  2-5)  (3-1  3-2  3-3  3-4  3-5)  (4-1    第2字节
4-2  4-3  4-4  4-5)  (5-1  5-2  5-3  5-4    第3字节
5-5)  (6-1  6-2  6-3  6-4  6-5)  (7-1  7-2    第4字节
7-3  7-4  7-5)  (8-1  8-2  8-3  8-4  8-5)   第5字节

注:1-1表示原始数据的第一个值的第一位。
只要了解了这个压缩过程,逆向过程就很好写出来了。只要逐字节额的拼凑,就可以利用20字节拼出所需要的32字节了,也就是需要计算出来的lic。!!!

上传的附件 QQ截图未命名.jpg

  • 标 题:答复
  • 作 者:SJQIANG
  • 时 间:2010-10-24 12:35:27

好像好多人都死在这个BASE32编码算法上了

char *Base32(char *sha1,char *code,int len)
{
  char base[]={"ABCDEFGHJKMNPQRSTVWXYZ1234567890"};

  int length =(len*8+4)/5;
    char* sb = code;
    int cur_i = 0;
    byte cur_b = 0;
    int index;
    int k;
    for (int i = 0; i < length; i++)
    {
        index = 0;
        for (int j = 0; j < 5; j++)
        {
            k = i * 5 + j;
            if (k == len * 8)
                break;
            if (k % 8 == 0)
      {
                cur_b = *(BYTE*)(sha1+cur_i);
        cur_i++;
      }
            index <<= 1;
            index |= (cur_b & 128) == 0 ? 0 : 1;
            cur_b <<= 1;
        }
    *(BYTE*)(code+i)=base[index];
    }


  return code;
}