|  | 
 
| 出于我并不是th135pak的作者,我没法直接发所有源文件 以下提及的函数需要在Riatre大神的th135pak中对应修改才能使用。
 
 本来以为黄昏在正式版当中封入了文件名,,,,结果并没有。。。
 我跑了个彩虹表,,,能有3、4千文件名,,,,实在跑不动了。。。。。
 
 以下代码请在有限范围内任意使用。。。
 话说我要不要挂一份去github。。。
 复制代码
const unsigned char PUBLIC_KEY_N[KEY_BYTESIZE] = {
        0xC6, 0x43, 0xE0, 0x9D, 0x35, 0x5E, 0x98, 0x1D, 0xBE, 0x63, 0x6D, 0x3A, 0x5F, 0x84, 0x0F, 0x49,
        0xB8, 0xE8, 0x53, 0xF5, 0x42, 0x06, 0x37, 0x3B, 0x36, 0x25, 0xCB, 0x65, 0xCE, 0xDD, 0x68, 0x8C,
        0xF7, 0x5D, 0x72, 0x0A, 0xC0, 0x47, 0xBD, 0xFA, 0x3B, 0x10, 0x4C, 0xD2, 0x2C, 0xFE, 0x72, 0x03,
        0x10, 0x4D, 0xD8, 0x85, 0x15, 0x35, 0x55, 0xA3, 0x5A, 0xAF, 0xC3, 0x4A, 0x3B, 0xF3, 0xE2, 0x37
};
int Decrypt6432(const unsigned char* src,unsigned char* dst,size_t dstLen)
{
        if(keyInitialized == -1) InitRSAKeyPair(0);
        if(dstLen > 0x20) return -1;
        unsigned char tmp[64] = {0};
        DecryptBlock(src,tmp);
        unsigned char*lp = tmp + 2;
        while (*lp++ == 0xff);
        memcpy(dst, lp, dstLen);
        return 0;
}
int DecodeFile(unsigned char* src, unsigned char* dst, size_t Len, byte* __key)
{
        memcpy(dst, src, Len);
        unsigned char* currentlp = dst;
        DWORD uk1 = *(DWORD*)__key, uk2 = *(DWORD*)__key;
        byte key[20] = { 0 };
        memcpy(key, __key, 16);
        memcpy(key+16, __key, 4);
        
        if (!strncmp((char*)(currentlp), "TFWA", 4) || !strncmp((char*)(currentlp), "TFBM", 4) || !strncmp((char*)(currentlp), "OggS", 4) || !strncmp((char*)(currentlp+2), "RI", 2))
        {
                uk2 = *(DWORD*)currentlp;
                currentlp += 4;
                uk2 >>= 8;
                uk2 += (*currentlp)*0x1000000;
                *currentlp^= *(key + 4);
                *currentlp ^= *(currentlp-4);
                currentlp++;
        }
        if (Len & 1)
        {
                DWORD tmpKey = uk2 >> 8;
                tmpKey += (*currentlp) * 0x1000000;
                unsigned long current = (currentlp - dst) & 0xf;
                (*(byte*)currentlp) ^= *(byte*)(key + current);
                (*(byte*)currentlp) ^= LOBYTE( uk2);
                uk2 = tmpKey;
                currentlp ++;
        }else
        if (Len & 2)
        {
                DWORD tmpKey = HIWORD(uk2) + LOWORD((*(DWORD*)currentlp)) * 0x10000;
                unsigned long current = (currentlp - dst) & 0xf;
                (*(WORD*)currentlp) ^= *(WORD*)(key + current);
                (*(WORD*)currentlp) ^= LOWORD(uk2);
                currentlp += 2;
                uk2 = tmpKey;
        }
        if (currentlp < dst + Len)
        {
                do
                {
                        DWORD tmp = *(DWORD*)currentlp;
                        unsigned long current = (currentlp - dst) & 0xf;
                        (*(DWORD*)currentlp) ^= *(DWORD*)(key + current);
                        (*(DWORD*)currentlp) ^= uk2;
                        uk2 = tmp;
                        currentlp += 4;
                } while (currentlp < dst + Len);
        }
        return 0;
}
DWORD SpecialFNVHash(char *begin, char *end, DWORD initHash = 0x811C9DC5u)
{
        DWORD hash; 
        byte ch; 
        
        int inMBCS = 0;
        for (hash = initHash; begin != end; hash = (hash^ch) * 0x1000193  )
        {
                ch = *begin++;
                if (ch == '/') ch = '\\';
                if (!inMBCS && ch>=128)
                        inMBCS = 2;
                if(!inMBCS)
                {
                        ch = tolower(ch);  // bad ass style but WORKS PERFECTLY!
                }
                else inMBCS--;
        }
        return hash;
}
int ExtractAll(const wchar_t* ArchiveFileName,const wchar_t* OutputFolder)
{
        HANDLE hFile = CreateFile(ArchiveFileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_RANDOM_ACCESS,NULL);
        HANDLE hInMapping = CreateFileMapping(hFile,NULL,PAGE_READONLY,0,GetFileSize(hFile,NULL),NULL);
        BYTE* pPackage = (BYTE*)MapViewOfFile(hInMapping,FILE_MAP_READ,0,0,0);
        if(hFile == INVALID_HANDLE_VALUE || hInMapping == INVALID_HANDLE_VALUE || !pPackage)
                return 0;
        DWORD Magic = *(DWORD*)pPackage;
        if(Magic != 'KPFT')
                return 0;
        DWORD cur = 0x5;
        DWORD DirCount = 0;
        Decrypt6432(pPackage + cur, (BYTE*)&DirCount, sizeof(DWORD));
        cur += KEY_BYTESIZE;
        std::unordered_map<DWORD, std::pair<char*, char*> > hashToName;
        if (DirCount)
        {
        DIRLIST* DirList = new DIRLIST[DirCount];
        ZeroMemory(DirList, DirCount*sizeof(DIRLIST));
        for (int i = 0; i < DirCount; i++)
        {
                Decrypt6432(pPackage + cur, (BYTE*)&DirList[i], sizeof(DWORD) * 2);
                cur += KEY_BYTESIZE;
        }
        FNHEADER fnh;
        ZeroMemory(&fnh, sizeof(FNHEADER));
        Decrypt6432(pPackage + cur, (BYTE*)&fnh, sizeof(FNHEADER));
        cur += KEY_BYTESIZE;
        BYTE* CompFN = new BYTE[fnh.CompSize + KEY_BYTESIZE];
        for (int i = 0; i < fnh.BlockCnt; i++)
        {
                Decrypt6432(pPackage + cur, CompFN + i*KEY_BYTESIZE / 2);
                cur += KEY_BYTESIZE;
        }
        char* FNList = new char[fnh.OrigSize];
        DWORD realOrigSize = fnh.OrigSize;
        ZeroMemory(FNList, fnh.OrigSize);
        uncompress((BYTE*)FNList, &realOrigSize, CompFN, fnh.CompSize);
        delete[] CompFN;
        HANDLE hTemp = CreateFile(L"fnlist.txt",GENERIC_READ|GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_FLAG_RANDOM_ACCESS,NULL);
        WriteFile(hTemp,FNList,fnh.OrigSize,&realOrigSize,NULL);
        CloseHandle(hTemp);
        assert(fnh.OrigSize == realOrigSize);
        DWORD fnPos = 0;
        for (int i = 0; i < DirCount; i++)
        {
                for (int j = 0; j < DirList[i].FileCount; j++)
                {
                        int tlen = strlen(FNList + fnPos);
                        DWORD NameHash = -SpecialFNVHash(FNList + fnPos, FNList + fnPos + tlen, DirList[i].PathHash);
                        hashToName[NameHash] = std::make_pair(DirList[i].Path, FNList + fnPos);
                        fnPos += tlen + 1;
                }
        }
        }
        DWORD FileCount = 0;
        Decrypt6432(pPackage + cur, (BYTE*)&FileCount, sizeof(DWORD));
        cur += KEY_BYTESIZE;
        
        unordered_map<DWORD, FileLST> fileList;
        vector<DWORD> hashList;
        for (int i = 0; i < FileCount; i++)
        {
                QWORD fileDes = {0};
                Decrypt6432(pPackage + cur, (BYTE*)&fileDes, sizeof(QWORD));
                cur += KEY_BYTESIZE;
                QWORD hashDes = { 0 };
                Decrypt6432(pPackage + cur, (BYTE*)&hashDes, sizeof(QWORD));
                cur += KEY_BYTESIZE;
                DQWORD XorKeys = { 0 };
                Decrypt6432(pPackage + cur, (BYTE*)&XorKeys, sizeof(DQWORD));
                cur += KEY_BYTESIZE;
                fileDes.HIDWORD ^= XorKeys.HIQWORD.HIDWORD;//FileSize
                fileDes.LODWORD ^= XorKeys.HIQWORD.LODWORD;//FileOffset;
                //fileDes.LODWORD += FileBegin;
                hashDes.HIDWORD ^= XorKeys.LOQWORD.HIDWORD;
                hashDes.LODWORD ^= XorKeys.LOQWORD.LODWORD;
                DWORD hash = hashDes.HIDWORD;
                hashList.push_back(hash);
                fileList[hash].size = fileDes.HIDWORD;
                fileList[hash].offset = fileDes.LODWORD;
                fileList[hash].unKey = hashDes.LODWORD;
                memcpy(fileList[hash].xorKey, &XorKeys, 16);
                for (unsigned int i = 0; i<4; i++)
                {
                        ((DWORD*)fileList[hash].xorKey)[i] = -((DWORD*)fileList[hash].xorKey)[i];
                }
        }
        
        DWORD FileBegin = cur;
        for (unsigned int i = 0; i < hashList.size(); i++)
        {
                DWORD cHash = hashList[i];
                byte* loadDst = (byte*)calloc(1, fileList[cHash].size + 4);
                DecodeFile(pPackage + fileList[cHash].offset + FileBegin, loadDst, fileList[cHash].size, fileList[cHash].xorKey);
                WCHAR path[MAX_PATH] = { 0 };
                if (dirHashToName.find(cHash)==dirHashToName.end())
                {
                        char* extend = NULL;
                        if (!strncmp((char*)loadDst, "TFCS", 4))//人家说函数返回值不要是布尔,果然很难理解= =
                        {
                                extend = ".csv";
                        }
                        else if (!strncmp((char*)loadDst, "OggS", 4))
                        {
                                extend = ".ogg";
                        }
                        else if (!strncmp((char*)(loadDst + 2), "RIQS", 4))
                        {
                                extend = ".nut";
                        }
                        else if (!strncmp((char*)(loadDst + 2), "xml", 3))
                        {
                                extend = ".xml";
                        }
                        else if (!strncmp((char*)(loadDst), "ACT", 3))
                        {
                                extend = ".act";
                        }
                        else if (!strncmp((char*)(loadDst), "#===", 4))
                        {
                                extend = ".pl";
                        }
                        else if (!strncmp((char*)(loadDst), "DDS", 3))
                        {
                                extend = ".dds";
                        }
                        else if (!strncmp((char*)(loadDst), "OTTO", 4))
                        {
                                extend = ".otf";
                        }
                        else if (!strncmp((char*)(loadDst), "TFBM", 4))
                        {
                                extend = ".bmp";
                        }
                        else if (!strncmp((char*)(loadDst), "TFWA", 4))
                        {
                                extend = ".wav";
                        }
                        else if (!strncmp((char*)(loadDst), "IBMB", 4))
                        {
                                extend = ".bmb";
                        }
                        else if (!strncmp((char*)(loadDst), "TFPA", 4))
                        {
                                extend = ".bmp";
                        }
                        else
                        {
                                extend = ".null";
                        }
                        
                        swprintf(path, L"%s%x%s", OutputFolder, cHash, extend);
                }
                else
                {
                        swprintf(path, L"%s%s", OutputFolder, dirHashToName[cHash].data());
                        
                }
                CreateDirectoryForPath(path);
                DWORD rb = 0;
                HANDLE Hload = CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, 0, OPEN_ALWAYS, 0, 0);
                WriteFile(Hload, loadDst, fileList[cHash].size, &rb, NULL);
                CloseHandle(Hload);
                free(loadDst);
                cout << ".";
        }
        UnmapViewOfFile(pPackage);
        CloseHandle(hInMapping);
        CloseHandle(hFile);
        return 1;
}
 | 
评分
查看全部评分
 |