设为首页收藏本站喵玉殿官方微博

 找回密码
 少女注册中
搜索
查看: 9451|回复: 6

[编程算法] 东方深秘录解包工具源代码【需对应修改】

[复制链接]
发表于 2015-5-16 23:49:52 | 显示全部楼层 |阅读模式
出于我并不是th135pak的作者,我没法直接发所有源文件
以下提及的函数需要在Riatre大神的th135pak中对应修改才能使用。

本来以为黄昏在正式版当中封入了文件名,,,,结果并没有。。。
我跑了个彩虹表,,,能有3、4千文件名,,,,实在跑不动了。。。。。

以下代码请在有限范围内任意使用。。。
话说我要不要挂一份去github。。。

  1. const unsigned char PUBLIC_KEY_N[KEY_BYTESIZE] = {
  2.         0xC6, 0x43, 0xE0, 0x9D, 0x35, 0x5E, 0x98, 0x1D, 0xBE, 0x63, 0x6D, 0x3A, 0x5F, 0x84, 0x0F, 0x49,
  3.         0xB8, 0xE8, 0x53, 0xF5, 0x42, 0x06, 0x37, 0x3B, 0x36, 0x25, 0xCB, 0x65, 0xCE, 0xDD, 0x68, 0x8C,
  4.         0xF7, 0x5D, 0x72, 0x0A, 0xC0, 0x47, 0xBD, 0xFA, 0x3B, 0x10, 0x4C, 0xD2, 0x2C, 0xFE, 0x72, 0x03,
  5.         0x10, 0x4D, 0xD8, 0x85, 0x15, 0x35, 0x55, 0xA3, 0x5A, 0xAF, 0xC3, 0x4A, 0x3B, 0xF3, 0xE2, 0x37
  6. };


  7. int Decrypt6432(const unsigned char* src,unsigned char* dst,size_t dstLen)
  8. {
  9.         if(keyInitialized == -1) InitRSAKeyPair(0);
  10.         if(dstLen > 0x20) return -1;
  11.         unsigned char tmp[64] = {0};
  12.         DecryptBlock(src,tmp);
  13.         unsigned char*lp = tmp + 2;
  14.         while (*lp++ == 0xff);
  15.         memcpy(dst, lp, dstLen);
  16.         return 0;
  17. }


  18. int DecodeFile(unsigned char* src, unsigned char* dst, size_t Len, byte* __key)
  19. {

  20.         memcpy(dst, src, Len);
  21.         unsigned char* currentlp = dst;
  22.         DWORD uk1 = *(DWORD*)__key, uk2 = *(DWORD*)__key;

  23.         byte key[20] = { 0 };
  24.         memcpy(key, __key, 16);
  25.         memcpy(key+16, __key, 4);

  26.        

  27.         if (!strncmp((char*)(currentlp), "TFWA", 4) || !strncmp((char*)(currentlp), "TFBM", 4) || !strncmp((char*)(currentlp), "OggS", 4) || !strncmp((char*)(currentlp+2), "RI", 2))
  28.         {
  29.                 uk2 = *(DWORD*)currentlp;
  30.                 currentlp += 4;
  31.                 uk2 >>= 8;
  32.                 uk2 += (*currentlp)*0x1000000;
  33.                 *currentlp^= *(key + 4);
  34.                 *currentlp ^= *(currentlp-4);
  35.                 currentlp++;
  36.         }

  37.         if (Len & 1)
  38.         {
  39.                 DWORD tmpKey = uk2 >> 8;
  40.                 tmpKey += (*currentlp) * 0x1000000;

  41.                 unsigned long current = (currentlp - dst) & 0xf;

  42.                 (*(byte*)currentlp) ^= *(byte*)(key + current);
  43.                 (*(byte*)currentlp) ^= LOBYTE( uk2);

  44.                 uk2 = tmpKey;
  45.                 currentlp ++;
  46.         }else
  47.         if (Len & 2)
  48.         {
  49.                 DWORD tmpKey = HIWORD(uk2) + LOWORD((*(DWORD*)currentlp)) * 0x10000;
  50.                 unsigned long current = (currentlp - dst) & 0xf;

  51.                 (*(WORD*)currentlp) ^= *(WORD*)(key + current);
  52.                 (*(WORD*)currentlp) ^= LOWORD(uk2);

  53.                 currentlp += 2;
  54.                 uk2 = tmpKey;
  55.         }

  56.         if (currentlp < dst + Len)
  57.         {
  58.                 do
  59.                 {
  60.                         DWORD tmp = *(DWORD*)currentlp;
  61.                         unsigned long current = (currentlp - dst) & 0xf;
  62.                         (*(DWORD*)currentlp) ^= *(DWORD*)(key + current);
  63.                         (*(DWORD*)currentlp) ^= uk2;
  64.                         uk2 = tmp;
  65.                         currentlp += 4;
  66.                 } while (currentlp < dst + Len);
  67.         }


  68.         return 0;
  69. }


  70. DWORD SpecialFNVHash(char *begin, char *end, DWORD initHash = 0x811C9DC5u)
  71. {
  72.         DWORD hash;
  73.         byte ch;
  74.        
  75.         int inMBCS = 0;

  76.         for (hash = initHash; begin != end; hash = (hash^ch) * 0x1000193  )
  77.         {
  78.                 ch = *begin++;
  79.                 if (ch == '/') ch = '\\';
  80.                 if (!inMBCS && ch>=128)
  81.                         inMBCS = 2;
  82.                 if(!inMBCS)
  83.                 {
  84.                         ch = tolower(ch);  // bad ass style but WORKS PERFECTLY!
  85.                 }
  86.                 else inMBCS--;
  87.         }
  88.         return hash;
  89. }

  90. int ExtractAll(const wchar_t* ArchiveFileName,const wchar_t* OutputFolder)
  91. {
  92.         HANDLE hFile = CreateFile(ArchiveFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
  93.         HANDLE hInMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,GetFileSize(hFile,NULL),NULL);
  94.         BYTE* pPackage = (BYTE*)MapViewOfFile(hInMapping,FILE_MAP_READ,0,0,0);
  95.         if(hFile == INVALID_HANDLE_VALUE || hInMapping == INVALID_HANDLE_VALUE || !pPackage)
  96.                 return 0;

  97.         DWORD Magic = *(DWORD*)pPackage;
  98.         if(Magic != 'KPFT')
  99.                 return 0;

  100.         DWORD cur = 0x5;
  101.         DWORD DirCount = 0;

  102.         Decrypt6432(pPackage + cur, (BYTE*)&DirCount, sizeof(DWORD));
  103.         cur += KEY_BYTESIZE;

  104.         std::unordered_map<DWORD, std::pair<char*, char*> > hashToName;

  105.         if (DirCount)
  106.         {
  107.         DIRLIST* DirList = new DIRLIST[DirCount];
  108.         ZeroMemory(DirList, DirCount*sizeof(DIRLIST));
  109.         for (int i = 0; i < DirCount; i++)
  110.         {
  111.                 Decrypt6432(pPackage + cur, (BYTE*)&DirList[i], sizeof(DWORD) * 2);
  112.                 cur += KEY_BYTESIZE;
  113.         }

  114.         FNHEADER fnh;
  115.         ZeroMemory(&fnh, sizeof(FNHEADER));
  116.         Decrypt6432(pPackage + cur, (BYTE*)&fnh, sizeof(FNHEADER));
  117.         cur += KEY_BYTESIZE;
  118.         BYTE* CompFN = new BYTE[fnh.CompSize + KEY_BYTESIZE];
  119.         for (int i = 0; i < fnh.BlockCnt; i++)
  120.         {
  121.                 Decrypt6432(pPackage + cur, CompFN + i*KEY_BYTESIZE / 2);
  122.                 cur += KEY_BYTESIZE;
  123.         }
  124.         char* FNList = new char[fnh.OrigSize];
  125.         DWORD realOrigSize = fnh.OrigSize;
  126.         ZeroMemory(FNList, fnh.OrigSize);
  127.         uncompress((BYTE*)FNList, &realOrigSize, CompFN, fnh.CompSize);
  128.         delete[] CompFN;
  129.         HANDLE hTemp = CreateFile(L"fnlist.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS,NULL);
  130.         WriteFile(hTemp,FNList,fnh.OrigSize,&realOrigSize,NULL);
  131.         CloseHandle(hTemp);
  132.         assert(fnh.OrigSize == realOrigSize);


  133.         DWORD fnPos = 0;
  134.         for (int i = 0; i < DirCount; i++)
  135.         {
  136.                 for (int j = 0; j < DirList[i].FileCount; j++)
  137.                 {
  138.                         int tlen = strlen(FNList + fnPos);
  139.                         DWORD NameHash = -SpecialFNVHash(FNList + fnPos, FNList + fnPos + tlen, DirList[i].PathHash);
  140.                         hashToName[NameHash] = std::make_pair(DirList[i].Path, FNList + fnPos);
  141.                         fnPos += tlen + 1;
  142.                 }
  143.         }



  144.         }
  145.         DWORD FileCount = 0;
  146.         Decrypt6432(pPackage + cur, (BYTE*)&FileCount, sizeof(DWORD));
  147.         cur += KEY_BYTESIZE;
  148.        


  149.         unordered_map<DWORD, FileLST> fileList;
  150.         vector<DWORD> hashList;
  151.         for (int i = 0; i < FileCount; i++)
  152.         {
  153.                 QWORD fileDes = {0};
  154.                 Decrypt6432(pPackage + cur, (BYTE*)&fileDes, sizeof(QWORD));
  155.                 cur += KEY_BYTESIZE;

  156.                 QWORD hashDes = { 0 };
  157.                 Decrypt6432(pPackage + cur, (BYTE*)&hashDes, sizeof(QWORD));
  158.                 cur += KEY_BYTESIZE;

  159.                 DQWORD XorKeys = { 0 };
  160.                 Decrypt6432(pPackage + cur, (BYTE*)&XorKeys, sizeof(DQWORD));
  161.                 cur += KEY_BYTESIZE;

  162.                 fileDes.HIDWORD ^= XorKeys.HIQWORD.HIDWORD;//FileSize
  163.                 fileDes.LODWORD ^= XorKeys.HIQWORD.LODWORD;//FileOffset;
  164.                 //fileDes.LODWORD += FileBegin;

  165.                 hashDes.HIDWORD ^= XorKeys.LOQWORD.HIDWORD;
  166.                 hashDes.LODWORD ^= XorKeys.LOQWORD.LODWORD;

  167.                 DWORD hash = hashDes.HIDWORD;
  168.                 hashList.push_back(hash);
  169.                 fileList[hash].size = fileDes.HIDWORD;
  170.                 fileList[hash].offset = fileDes.LODWORD;
  171.                 fileList[hash].unKey = hashDes.LODWORD;
  172.                 memcpy(fileList[hash].xorKey, &XorKeys, 16);
  173.                 for (unsigned int i = 0; i<4; i++)
  174.                 {
  175.                         ((DWORD*)fileList[hash].xorKey)[i] = -((DWORD*)fileList[hash].xorKey)[i];
  176.                 }
  177.         }
  178.        
  179.         DWORD FileBegin = cur;


  180.         for (unsigned int i = 0; i < hashList.size(); i++)
  181.         {
  182.                 DWORD cHash = hashList[i];
  183.                 byte* loadDst = (byte*)calloc(1, fileList[cHash].size + 4);
  184.                 DecodeFile(pPackage + fileList[cHash].offset + FileBegin, loadDst, fileList[cHash].size, fileList[cHash].xorKey);

  185.                 WCHAR path[MAX_PATH] = { 0 };

  186.                 if (dirHashToName.find(cHash)==dirHashToName.end())
  187.                 {
  188.                         char* extend = NULL;
  189.                         if (!strncmp((char*)loadDst, "TFCS", 4))//人家说函数返回值不要是布尔,果然很难理解= =
  190.                         {
  191.                                 extend = ".csv";
  192.                         }
  193.                         else if (!strncmp((char*)loadDst, "OggS", 4))
  194.                         {
  195.                                 extend = ".ogg";
  196.                         }
  197.                         else if (!strncmp((char*)(loadDst + 2), "RIQS", 4))
  198.                         {
  199.                                 extend = ".nut";
  200.                         }
  201.                         else if (!strncmp((char*)(loadDst + 2), "xml", 3))
  202.                         {
  203.                                 extend = ".xml";
  204.                         }
  205.                         else if (!strncmp((char*)(loadDst), "ACT", 3))
  206.                         {
  207.                                 extend = ".act";
  208.                         }
  209.                         else if (!strncmp((char*)(loadDst), "#===", 4))
  210.                         {
  211.                                 extend = ".pl";
  212.                         }
  213.                         else if (!strncmp((char*)(loadDst), "DDS", 3))
  214.                         {
  215.                                 extend = ".dds";
  216.                         }
  217.                         else if (!strncmp((char*)(loadDst), "OTTO", 4))
  218.                         {
  219.                                 extend = ".otf";
  220.                         }
  221.                         else if (!strncmp((char*)(loadDst), "TFBM", 4))
  222.                         {
  223.                                 extend = ".bmp";
  224.                         }
  225.                         else if (!strncmp((char*)(loadDst), "TFWA", 4))
  226.                         {
  227.                                 extend = ".wav";
  228.                         }
  229.                         else if (!strncmp((char*)(loadDst), "IBMB", 4))
  230.                         {
  231.                                 extend = ".bmb";
  232.                         }
  233.                         else if (!strncmp((char*)(loadDst), "TFPA", 4))
  234.                         {
  235.                                 extend = ".bmp";
  236.                         }
  237.                         else
  238.                         {
  239.                                 extend = ".null";
  240.                         }
  241.                        
  242.                         swprintf(path, L"%s%x%s", OutputFolder, cHash, extend);
  243.                 }
  244.                 else
  245.                 {
  246.                         swprintf(path, L"%s%s", OutputFolder, dirHashToName[cHash].data());
  247.                        
  248.                 }

  249.                 CreateDirectoryForPath(path);


  250.                 DWORD rb = 0;
  251.                 HANDLE Hload = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
  252.                 WriteFile(Hload, loadDst, fileList[cHash].size, &rb, NULL);
  253.                 CloseHandle(Hload);
  254.                 free(loadDst);
  255.                 cout << ".";
  256.         }

  257.         UnmapViewOfFile(pPackage);
  258.         CloseHandle(hInMapping);
  259.         CloseHandle(hFile);

  260.         return 1;
  261. }
复制代码

评分

参与人数 1积分 +10 喵玉币 +60 萌度 +120 收起 理由
drzzm32 + 10 + 60 + 120 Oh……

查看全部评分

 楼主| 发表于 2015-5-16 23:54:55 | 显示全部楼层
本来是自己写了一段代码的,结果一看正式版的封包比起web版又改了,又回到了古老的模式,,,我干脆就又用th135pak的代码做基础改了。。。

丧病的黄昏体验版里对RSApublicKey的加密在正式版里居然没了。。
回复

使用道具 举报

发表于 2015-5-17 12:20:47 | 显示全部楼层
要找文件名的话,还不如过一遍脚本里面的字符串来得快

点评

大部分文件名在mat和mesh文件里,文件名和文件夹名是分开的  发表于 2015-5-17 12:35
回复

使用道具 举报

发表于 2015-5-17 18:22:28 | 显示全部楼层
文件名我直接扒内存找了
回复

使用道具 举报

发表于 2015-5-17 18:22:35 | 显示全部楼层
文件名我直接扒内存找了
回复

使用道具 举报

发表于 2015-5-28 22:46:01 | 显示全部楼层
哇,大触!技术群里新来的那位特地在群里问起您了……

点评

我大概是才能比得上别人的四分之一了。。  发表于 2015-6-4 16:19
回复

使用道具 举报

发表于 2015-5-28 23:32:35 | 显示全部楼层
为何不直接丢到GitHub呢

点评

毕竟有别人的代码,,,他也没说怎么开的源  发表于 2015-6-4 16:19
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 少女注册中

本版积分规则

合作与事务联系|无图版|手机版|小黑屋|喵玉殿

GMT+8, 2025-10-31 03:39

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表