偶久网

 找回密码
 注册会员

QQ登录

只需一步,快速开始

首页 改图教学 查看内容

MPQ新的地图加密方法,kill-mpqMaster

2017-5-22 15:36| 发布者: 邪恶叔| 查看: 9262

最近研究MPQ.
...
需要引用的内容是一些前辈通过黑客技术,逆向工程,反汇编技术等等方法所获得的,由于某种非人力不可抗拒因素,这里不能列出他们的名字,抱歉!
...
MPQ文件是一种压缩包(pack)格式,它可以单独存在如*.mpq,也可以寄存在其他文件中如*.w3m,*.w3x
它有一个标准的32byte的header:
  1. struct TMPQHeader
  2. {
  3.     DWORD dwMpqFlag;
  4.     DWORD dwHeaderSize;         
  5.     DWORD dwArchiveSize;
  6.     USHORT wFormatVersion;
  7.     USHORT wBlockSize;
  8.     DWORD dwHashTablePos;
  9.     DWORD dwBlockTablePos;
  10.     DWORD dwHashTableSize;
  11.     DWORD dwBlockTableSize;


    其中dwMqpFlag是一个常量,它的值为'MPQ',用来定位MPQ在寄主文件中的文件头位置。这个地址将作为MPQ包的基地址。
    MPQ使用HashTable-BlockTable来定位一个文件在MPQ包中的位置,当然它们是经过确定密钥加密后放如MPQ包中的,以逃脱明文存放的危险。
    在MPQ中的加密算法分两种:
    1),摘要加密:把不定长度数据转化为定长的数据,hash算法得到一个DWORD
    2),对称加密:把不定长度数据按DWORD转换为同样长度的数据。
    上面两种加密在MPQ中会用到密钥,以确保Hash算法的更不可预料性和对称加密的密钥。
    MPQ使用的密钥有5组,每组密钥(长0x100个DWORD)被全部用于某次加密。密钥是确定的,是可以在加密之前计算出来并且保持不变的常量。计算方法相当有规律:
    1. DWORD cryptTable[0x500]
    2. void prepareCryptTable()
    3. {
    4.     DWORD dwHih, dwLow,seed = 0x00100001,index1 = 0,index2 = 0, i;
    5.     for(index1 = 0; index1 < 0x100; index1++)
    6.     {
    7.         for(index2 = index1, i = 0; i < 5; i++, index2 += 0x100)
    8.         {
    9.             seed = (seed * 125 + 3) % 0x2AAAAB;
    10.             dwHih= (seed & 0xFFFF) << 0x10;
    11.             seed = (seed * 125 + 3) % 0x2AAAAB;
    12.             dwLow= (seed & 0xFFFF);
    13.             cryptTable[index2] = (dwHih| dwLow);
    14.         }
    15.     }


      然后就可以使用MPQ中的加密函数了。
      1. DWORD HashString(char *lpszFileName,DWORD dwCryptIndex)
      2. {
      3.     unsigned char *key = (unsigned char *)lpszFileName;
      4.     DWORD seed1 = 0x7FED7FED, seed2 = 0xEEEEEEEE;
      5.     int ch;
      6.     while(*key != 0)
      7.     {
      8.         ch = toupper(*key++);
      9.         seed1 = cryptTable[(dwCryptIndex<< 8) + ch] ^ (seed1 + seed2);
      10.         seed2 = ch + seed1 + seed2 + (seed2 << 5) + 3;
      11.     }
      12.     return seed1;


        这个Hash函数被用来Hash一个filename根据密钥0,密钥1,密钥2获得三个Hash:Hash,Hash1,Hash2.
        其中Hash被用来在HashTable中定位。Hash%HashTableSize就是索引。
        1. struct TMPQHash
        2. {
        3.     DWORD dwHash1;
        4.     DWORD dwHash2;
        5.     USHORT lcLocale;
        6.     USHORT wPlatform;
        7.     DWORD dwBlockIndex;//0xFFFFFFFEh,0xFFFFFFFFh表示该HashItem无效.

12下一页
返回顶部