void BlowFish::Encode(byte* key,ByteBuf & buf) { CBlowFish blow; blow.Initialize((byte*)key,16); int iLength = buf.first; int iDifference = iLength % 8; int iNewLength = iLength; if( iDifference != 0 ) iNewLength = (iLength - iDifference) + 8; buf.first=blow.Encode(buf.second,buf.second,iNewLength); }
DWORD WINAPI Encrypt(PBYTE pbBuffer, TMyPAZEntry *pEntry) { CHAR szName[MAX_PATH]; BYTE bySeed[400]; DWORD dwSeed, dwSize; LPCSTR lpCrud; LPSTR lpExt, lpFileName; lpFileName = pEntry->szName; lstrcpy(szName, lpFileName); lpExt = findext(szName); if (lpExt && bIsVoice) { *lpExt = 0; } dwSize = pEntry->dwCompSize; lpCrud = GetCrud(findext(lpFileName), &GameInfo[dwInfoIndex]); if (lpCrud) dwSeed = sprintf((char *)bySeed, "%s %08X %s", strlwr(lpFileName), pEntry->dwCompSize, lpCrud ? lpCrud : ""); if (g_bIsMovie == False) { CBlowFish bf; bf.Initialize(GameInfo[dwInfoIndex].key[dwKeyIndex].DataKey, sizeof(GameInfo[dwInfoIndex].key[dwKeyIndex].DataKey)); if (lpCrud) { Decrypt(bySeed, dwSeed, pbBuffer, dwSize); } dwSize = bf.Encode(pbBuffer, pbBuffer, pEntry->dwDecryptSize); } else { if (dwInfoIndex != EF_FIRST) { memset(&bySeed[dwSeed + 10], 0, 0x100); DecryptMovie(&bySeed[dwSeed + 10], bySeed, dwSeed, pbBuffer, pEntry->dwCompSize); } else { } } if (bNeedXor) Xor(pbBuffer, dwSize); return dwSize; }
int Compact(TCHAR* szFolder,TCHAR* szFileName) { DWORD temp; if(!::SetCurrentDirectory(szFolder)) return -1; char* p=szFolder; p+=strlen(szFolder); if(*(p-1)=='\\') p--; while(*--p!='\\'); string prefix=++p; p=szFolder+strlen(szFolder); if(*(p-1)=='\\') --p; strcpy(p,".dat"); key_info_t keys; for (unsigned long i = 0; !GAME_INFO.keys[i].prefix.empty(); i++) { if (prefix == GAME_INFO.keys[i].prefix) { keys = GAME_INFO.keys[i]; } } if (keys.prefix.empty()) return -1; bool is_audio = prefix == "bgm" || prefix == "se" || prefix == "voice" || prefix == "PMvoice"; bool is_mov = prefix == "mov"; if(is_mov) return -1; PAZHDR hdr; // strcpy((char*)&hdr,"mashiroiro"); HANDLE hOldFile=CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hOldFile==INVALID_HANDLE_VALUE) return -1; ReadFile(hOldFile,&hdr,sizeof(hdr),&temp,0); char simple_key = hdr.toc_len >> 24; if(simple_key) return -1; char* toc_buff2=new char[hdr.toc_len]; ReadFile(hOldFile,toc_buff2,hdr.toc_len,&temp,0); CloseHandle(hOldFile); CBlowFish bf; bf.Initialize(keys.toc_key,sizeof(keys.toc_key)); bf.Decode((unsigned char*)toc_buff2,(unsigned char*)toc_buff2,hdr.toc_len); list<PAZENTRY2> entries; list<PAZENTRY2>::iterator ent_itr,ent_itr_end; char*p2=toc_buff2; int nEntryCount=*(long*)p2; p2+=4; for(int i=0;i<nEntryCount;i++) { PAZENTRY2 entry; entry.fn=p2; p2+=entry.fn.length()+1; memcpy(&entry.ent,p2,sizeof(entry.ent)); p2+=sizeof(entry.ent); entries.push_back(entry); } delete[] toc_buff2; //int nSizeEntries=sizeof(PAZHDR2); //WIN32_FIND_DATA stFindData; //HANDLE hFind=FindFirstFile(TEXT("*"),&stFindData); //if(hFind!=INVALID_HANDLE_VALUE) // do // { // PAZENTRY2 entry; // HANDLE hNowFile=CreateFile(stFindData.cFileName,GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); // if(hNowFile==INVALID_HANDLE_VALUE) // continue; // entry.fn=stFindData.cFileName; // entry.ent.length =GetFileSize(hNowFile,NULL); // entry.ent.original_length=entry.ent.length ; // entry.ent.padded_length = (entry.ent.length + 7) & ~7; // entries.push_back(entry); // nSizeEntries+=entry.fn.length ()+1+sizeof(PAZENTRY); // CloseHandle(hNowFile); // }while(FindNextFile(hFind,&stFindData)); //else // return -1; //FindClose(hFind); // nSizeEntries=(nSizeEntries + 7) & ~7; int nNowOffset=sizeof(PAZHDR)+hdr.toc_len; ent_itr=entries.begin(); ent_itr_end=entries.end(); char* toc_buff=new char[hdr.toc_len]; memset(toc_buff,0,hdr.toc_len); *(long*)toc_buff=entries.size(); for(char* p=toc_buff+sizeof(PAZHDR2);ent_itr!=ent_itr_end;ent_itr++) { ent_itr->ent.offset=nNowOffset; nNowOffset+=ent_itr->ent.padded_length; strcpy(p,ent_itr->fn.c_str()); p+=ent_itr->fn.length()+1; memcpy(p,&ent_itr->ent,sizeof(ent_itr->ent)); p+=sizeof(ent_itr->ent); } HANDLE hNewFile=CreateFile(szFolder,GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if(hNewFile==INVALID_HANDLE_VALUE) return -1; // hdr.toc_len=nSizeEntries; WriteFile(hNewFile,&hdr,sizeof(hdr),&temp,0); bf.Initialize(keys.toc_key,sizeof(keys.toc_key)); bf.Encode((unsigned char*)toc_buff,(unsigned char*)toc_buff,hdr.toc_len); WriteFile(hNewFile,toc_buff,hdr.toc_len,&temp,0); delete[] toc_buff; ent_itr=entries.begin(); ent_itr_end=entries.end(); for(;ent_itr!=ent_itr_end;ent_itr++) { string filename=ent_itr->fn; HANDLE hNowFile=CreateFile(filename.c_str(),GENERIC_READ,0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hNowFile==INVALID_HANDLE_VALUE) return -1; char* buff=new char[ent_itr->ent.padded_length]; memset(buff,0,ent_itr->ent.padded_length); ReadFile(hNowFile,buff,ent_itr->ent.length,&temp,0); CloseHandle(hNowFile); string crud; if (filename.find(".png") != string::npos) { crud = GAME_INFO.crud.png; } else if (filename.find(".ogg") != string::npos || is_audio) { crud = GAME_INFO.crud.ogg; } else if (filename.find(".sc") != string::npos) { crud = GAME_INFO.crud.sc; } else if (filename.find(".avi") != string::npos || filename.find(".mpg") != string::npos) { crud = GAME_INFO.crud.avi; } char entrylen[12]; wsprintf(entrylen," %08X ",ent_itr->ent.length); transform(filename.begin (),filename.end (),filename.begin (),tolower); string seed=filename+(string)entrylen+crud; if(is_mov) return -1; else { bf.Initialize(keys.dat_key,sizeof(keys.dat_key)); if(!crud.empty()) unobfuscate3(seed,(unsigned char*)buff,ent_itr->ent.padded_length); bf.Encode((unsigned char*)buff,(unsigned char*)buff,ent_itr->ent.padded_length); } WriteFile(hNewFile,buff,ent_itr->ent.padded_length,&temp,0); delete[] buff; } SetEndOfFile(hNewFile); CloseHandle(hNewFile); return 0; }
Void WINAPI WriteEntry(HANDLE hFile, TMyPAZEntry *pEntry, DWORD dwCount, Bool bEncrypt) { DWORD dwLength, dwEntryPos, dwRemainder; PBYTE pbEntry; BYTE byMovieSeed[256], byMod8[8]; *(LPDWORD)&byMod8[0] = 0; *(LPDWORD)&byMod8[3] = 0; dwEntryPos = 0x24 + (g_bIsMovie ? 0x100 : 0); SetFilePointer(hFile, 0x20, 0, FILE_BEGIN); WriteFile(hFile, &dwCount, 4, &dwLength, NULL); // entry size WriteFile(hFile, &dwCount, 4, &dwLength, NULL); // entry count if (g_bIsMovie) { if (bEncrypt == False) { if (dwInfoIndex != EF_FIRST) { memset(byMovieSeed, 0, sizeof(byMovieSeed)); WriteFile(hFile, byMovieSeed, sizeof(byMovieSeed), &dwLength, NULL); } else { for (int i = 0; i != 256; ++i) { byMovieSeed[i] = i; } for (int i = 0; i != 256; ++i) WriteFile(hFile, byMovieSeed, sizeof(byMovieSeed), &dwLength, NULL); } } else { SetFilePointer(hFile, dwInfoIndex != EF_FIRST ? 0x100 : 0x10000, 0, FILE_CURRENT); } } for (DWORD i = dwCount; i; ) { LPSTR lpExt; --i; lpExt = findext(pEntry[i].szName); if (lpExt) { if (lstrcmpiA(lpExt, ".uca") && bIsVoice) *lpExt = 0; else if (lstrcmpiA(lpExt, ".ogg") && lstrcmpiA(lpExt, ".m4a")) lpExt = NULL; } dwLength = lstrlenA(pEntry[i].szName) + 1; WriteFile(hFile, pEntry[i].szName, dwLength, &dwLength, NULL); if (lpExt && *lpExt == 0) { *lpExt = '.'; } WriteFile(hFile, &pEntry[i].l64Offset, sizeof(*pEntry) - sizeof(pEntry->szName), &dwLength, NULL); } dwCount = SetFilePointer(hFile, 0, 0, FILE_CURRENT) - sizeof(TPAZHeader); dwRemainder = dwCount % 8; if (dwRemainder) { dwRemainder = 8 - dwRemainder; WriteFile(hFile, byMod8, dwRemainder, &dwLength, NULL); dwCount += dwRemainder; } if (bEncrypt) { HANDLE hHeap; CBlowFish bf; hHeap = ghHeap; pbEntry = (PBYTE)HeapAlloc(hHeap, 0, dwCount); SetFilePointer(hFile, 0x24, 0, FILE_BEGIN); ReadFile(hFile, pbEntry, dwCount, &dwLength, NULL); bf.Initialize(GameInfo[dwInfoIndex].key[dwKeyIndex].IndexKey, sizeof(GameInfo[dwInfoIndex].key[dwKeyIndex].IndexKey)); dwLength = bf.Encode(pbEntry, pbEntry, dwLength); if (bNeedXor) { Xor(pbEntry, dwLength); } SetFilePointer(hFile, 0x24, 0, FILE_BEGIN); WriteFile(hFile, pbEntry, dwLength, &dwLength, NULL); dwCount = SetFilePointer(hFile, 0, 0, FILE_CURRENT) - sizeof(TPAZHeader) + 4; } dwCount += 4; SetFilePointer(hFile, 0x20, NULL, FILE_BEGIN); WriteFile(hFile, &dwCount, 4, &dwLength, NULL); // entry size if (bEncrypt && bNeedXor) { CHAR h[0x24]; SetFilePointer(hFile, 0, NULL, FILE_BEGIN); ReadFile(hFile, h, sizeof(h), &dwLength, NULL); Xor((PBYTE)h, sizeof(h)); SetFilePointer(hFile, 0, NULL, FILE_BEGIN); WriteFile(hFile, h, sizeof(h), &dwLength, NULL); } SetFilePointer(hFile, 0, 0, FILE_END); }
int Compact(TCHAR* szFolder,TCHAR* szFileName) { DWORD temp; int len=lstrlen(szFolder); if(szFolder[len-1]=='\\') szFolder[len-1]='\0'; if(!(GetFileAttributes(szFolder)&FILE_ATTRIBUTE_DIRECTORY)) { Mbe(TEXT("目录错误")); return -1; } vector<LPTSTR> vFiles; GetDirectoryFiles(szFolder,&vFiles,lstrlen(szFolder)+1); string* prefix=GetPrefix((char*)szFolder); key_info_t keys; for (unsigned long i = 0; !GAME_INFO.keys[i].prefix.empty(); i++) { if (*prefix == GAME_INFO.keys[i].prefix) { keys = GAME_INFO.keys[i]; } } if (keys.prefix.empty()) { Mbe(TEXT("请使用scr,mov等游戏目录中已存在的目录名")); delete prefix; FreeDirectoryFiles(&vFiles); return -1; } bool is_audio = *prefix == "bgm" || *prefix == "se" || *prefix == "voice" || *prefix == "PMvoice"; bool is_mov = *prefix == "mov"; delete prefix; int idxlen=4; for(int i=0;i<vFiles.size();i++) { idxlen+=lstrlen(vFiles[i])+1+0x18; } if(is_mov) idxlen+=256; HANDLE hNewFile=CreateFile(szFileName,GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if(hNewFile==INVALID_HANDLE_VALUE) { Mbe(TEXT("无法访问封包文件!")); FreeDirectoryFiles(&vFiles); return -1; } BYTE mov_block[256]; memset(mov_block,0,256); MyPazEnt* ents=new MyPazEnt[vFiles.size()]; MyPazEnt* pe=ents; DWORD offset=((idxlen+7)&~7)+sizeof(PAZHDR); CBlowFish bf; string rootpath=szFolder; rootpath+="\\"; for(int i=0;i<vFiles.size();i++) { pe->fn=vFiles[i]; HANDLE hf=CreateFile((rootpath+vFiles[i]).c_str(),GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hf==INVALID_HANDLE_VALUE) { delete[] ents; FreeDirectoryFiles(&vFiles); sprintf(errmes,"无法访问%s!",vFiles[i]); Mbe(errmes); return -1; } DWORD fsize=GetFileSize(hf,0); pe->comprlen=fsize; pe->uncomprlen=fsize; pe->decryptlen=(fsize+7)&~7; pe->unk=0; pe->iscompr=0; pe->offset=offset; offset+=pe->decryptlen; BYTE* buf=new BYTE[pe->decryptlen]; memset(buf+pe->decryptlen-8,0,8); ReadFile(hf,buf,fsize,&temp,0); string* seed=MakeSeed(pe); if(is_mov) { if(seed==NULL) { delete[] buf; delete[] ents; FreeDirectoryFiles(&vFiles); Mbe(TEXT("视频格式错误!")); return -1; } decrypt_mov(mov_block,*seed,buf,pe->decryptlen); delete seed; } else { if(seed!=NULL) { unobfuscate3(*seed,buf,pe->decryptlen); delete seed; } bf.Initialize(keys.dat_key,sizeof(keys.dat_key)); bf.Encode(buf,buf,pe->decryptlen); } SetFilePointer(hNewFile,pe->offset,0,FILE_BEGIN); WriteFile(hNewFile,buf,pe->decryptlen,&temp,0); delete[] buf; CloseHandle(hf); pe++; } PAZHDR hdr; strcpy((char*)&hdr,"mashiroiro"); hdr.toc_len=(idxlen+7)&~7; SetFilePointer(hNewFile,0,0,FILE_BEGIN); WriteFile(hNewFile,&hdr,sizeof(hdr),&temp,0); BYTE* idxbuff=new BYTE[idxlen]; BYTE* p=idxbuff; *(DWORD*)p=vFiles.size(); p+=4; if(is_mov) { memset(p,0,256); p+=256; } pe=ents; for(int i=0;i<vFiles.size();i++) { strcpy((char*)p,pe->fn); p+=strlen(pe->fn)+1; memcpy(p,&(pe->offset),0x18); p+=0x18; pe++; } //bf.Initialize(keys.toc_key,sizeof(keys.toc_key)); //bf.Encode(idxbuff,idxbuff,hdr.toc_len); WriteFile(hNewFile,idxbuff,idxlen,&temp,0); CloseHandle(hNewFile); delete[] idxbuff; delete[] ents; FreeDirectoryFiles(&vFiles); return 0; }