void BlowFishDecode(byte* key, int nBufLen, byte* pBuff) { CBlowFish blow; blow.Initialize((byte*)key,16); int nlength = nBufLen; int nDifference = nlength % 8; int nNewLength = nlength; if( nDifference != 0 ) nNewLength = (nlength - nDifference) + 8; blow.Decode(pBuff,pBuff,nNewLength); }
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); }
void BlowFishCWrapper_Decode(BYTE_BLOWFISH * pInput, BYTE_BLOWFISH * pOutput, DWORD_BLOWFISH lSize) { CBlowFish blow; /*blow.Initialize((byte*)&key,sizeof(key));*/ 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.Decode(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; }
//=========================================================================== //スレッド実行 //=========================================================================== void __fastcall TAttacheCaseFileDecrypt1::Execute() { int i, c, len; float ProgressPercentNumF; //進捗パーセンテージ(浮動小数点) // バッファ char buffer[BUF_SIZE]; char source_buffer[BUF_SIZE]; char temp_buffer[BUF_SIZE]; char output_buffer[LARGE_BUF_SIZE]; char *headerbuffer; //パスワード bool fPasswordOk; String FilePath, FileName; // ファイルストリーム TFileStream *fsIn; TFileStream *fsOut; bool fInputFileOpen = false; bool fOutputFileOpen = false; float free_space_required; __int64 CurrentPos, TotalSize; __int64 CurrentDriveFreeSpaceSize; //処理する合計サイズ AllTotalSize = 0; int ret; //バッファ出力の返値 int FileIndex = 0; //Blowfish CBlowFish *bf; char token[17] = {0, }; const String PrefixString = "Fn_"; const char charTokenString[17] = "_AttacheCaseData"; //復号の正否に使う String AtcFileTokenString; //暗号化ファイルのトークン(文字列) String AtcFileCreateDateString; //暗号化ファイルの生成日時(文字列) //同名ファイル/フォルダーはすべて上書きして復号する //(ユーザーがダイアログで「すべてはい」を選択したとき = true ) fOverwirteYesToAll = false; //「復号したファイルを関連付けされたソフトで開く」一時的な設定 fTempOpenFile = fOpenFile; //フォルダーを一度開いたか(深いフォルダーすべてを開かないように) fOpenFolderOnce = false; // 出力するディレクトリ OutDirPath = IncludeTrailingPathDelimiter(OutDirPath); String TempRelativePath; // 暗号化部分のヘッダサイズ int EncryptHeaderSize = 0; int DataVersion; // ver.2.00~は "5", ver.2.70~は "6" int flush, status; // zlib z_stream z; // zlibライブラリとやりとりするための構造体 bool fInputEnd = false; // 入力ストリームの終了 //ヘッダデータから必要情報を取り出すための TMemoryStream *pms; // メモリストリーム int idx; TStringList *DataList; TStringList *tsv; TStringList *FileList = new TStringList(); // 0: ファイル名 __int64 *FileSizeList = 0; // 1: ファイルサイズ(フォルダは-1) int *FileAttrList = 0; // 2: 属性 int *FileAgeList = 0; // 3: タイムスタンプ int rest; int buf_size; //---------------------------------------------------------------------- // 平文のヘッダ内容チェック try { fsIn = new TFileStream(AtcFilePath, fmOpenRead | fmShareDenyNone); } catch(...) { //'復号するファイルを開けません。他のアプリケーションが使用中の可能性があります。' MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_OPEN); MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); goto LabelError; } fInputFileOpen = true; // 暗号部ヘッダサイズを取得 fsIn->Read(&EncryptHeaderSize, sizeof(int)); // トークンを取得 fsIn->Read(token, 16); if (StrComp(token, charTokenString) != 0 ) { //-------------------------------------------------------- //実は自己実行形式ファイル?(拡張子偽装されている場合も) //-------------------------------------------------------- // サイズを再取得 fsIn->Seek(-(__int64)sizeof(__int64), TSeekOrigin::soEnd); fsIn->Read(&AllTotalSize, sizeof(__int64)); // 位置を戻す fsIn->Seek(-(AllTotalSize + sizeof(__int64)), TSeekOrigin::soEnd); // もう一度、暗号部ヘッダサイズを取得 fsIn->Read(&EncryptHeaderSize, sizeof(int)); // もう一度、トークンを取得 fsIn->Read(token, 16); // トークンを再チェック if (StrComp(token, charTokenString) != 0 ) { // '暗号化ファイルではありません。アタッシェケースによって暗号化されたファイルでないか、'+#13+ // 'ファイルが壊れている可能性があります。' MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_FILE_NOT_ATC); MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); goto LabelError; } } else{ AllTotalSize = fsIn->Size; } //----------------------------------- // データバージョンチェック //----------------------------------- DataVersion = -1; fsIn->Read(&DataVersion, sizeof(int)); if (DataVersion <= 103) { // Blowfishで暗号化されたファイル } else{ //'バージョンがちがいます。復号できません。'+#13+ //'ファイルはver.1のアタッシェケースで暗号化されていません。'; MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_NOT_BLOWFISH_ENCRYPTION); MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); goto LabelError; } //----------------------------------- // 復号の準備 //----------------------------------- bf = new CBlowFish; bf->Initialize( KeyString.c_str(), KeyString.Length() ); //初期化 //----------------------------------- // 暗号部ヘッダの復号(ECBモード) //----------------------------------- pms = new TMemoryStream; len = 0; while (len < EncryptHeaderSize) { // 読み出しバッファ for (c = 0; c < BUF_SIZE; c++) { source_buffer[c] = 0; } // 暗号化されたデータブロックの読み出し len += fsIn->Read(source_buffer, BUF_SIZE); // 復号処理 bf->Decode( source_buffer, buffer, BUF_SIZE); pms->Write(buffer, BUF_SIZE); } pms->Seek((__int64)0, TSeekOrigin::soBeginning); //ポインタを先頭へ戻す DataList = new TStringList; DataList->LoadFromStream(pms, TEncoding::GetEncoding(932)); // shift-jis //----------------------------------- // 復号正否(復号できたか) //----------------------------------- if (DataList->Count == 0 || DataList->Strings[0].Pos("AttacheCase") == 0) { fPasswordOk = false; } else{ fPasswordOk = true; //パスワード合致 } if ( fPasswordOk == false ) { //'パスワードがちがいます。復号できません。'+#13+ //'場合によってはファイルが壊れている可能性もあります。'; MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_PASSWORD_WRONG); MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); delete DataList; goto LabelTypeMiss; } //----------------------------------- // 復号時のエンコーディング判定 //----------------------------------- pms->Position = 0; DataList->LoadFromStream(pms, TEncoding::GetEncoding(932)); // shift-jis //=================================== // デバッグ //ShowMessage(DataList->Text); //=================================== delete pms; //----------------------------------- // 暗号化ファイルの生成日時 //----------------------------------- //※特に今は使用していないが、将来的に // 期限付きでファイルを復号できなくなる // などの機能を追加しても良いかも。 //----------------------------------- AtcFileCreateDateString = DataList->Strings[1]; //----------------------------------- // ヘッダデータからファイルリストや // ファイル情報などを各変数を動的確保 //----------------------------------- FileSizeList = new __int64[DataList->Count]; // 1: ファイルサイズ(フォルダは-1) FileAttrList = new int[DataList->Count]; // 2: 属性 FileAgeList = new int[DataList->Count]; // 3: タイムスタンプ DataList->NameValueSeparator = ':'; tsv = new TStringList; tsv->Delimiter = '\t'; tsv->StrictDelimiter = true; char lpPath[MAX_PATH]; for (i = 0; i < DataList->Count; i++) { idx = DataList->IndexOfName(PrefixString+IntToStr(i)); if (idx > 0) { tsv->DelimitedText = DataList->ValueFromIndex[idx]; // ディレクトリ・トラバーサル対策(ver.2.8.5.0~) bool fDirectoryTraversal = false; AnsiString CanonicalizePath = AnsiString(OutDirPath + tsv->Strings[0]); if (CanonicalizePath.Length() < MAX_PATH) { // ファイルパスを正規化 if (PathCanonicalize(lpPath, CanonicalizePath.c_str()) == true) { // 正規化したパスが保存先と一致するか if (AnsiString(lpPath).Pos(OutDirPath) != 1 ){ fDirectoryTraversal = true; } } else{ fDirectoryTraversal = true; } } else{ fDirectoryTraversal = true; } if (fDirectoryTraversal == true) { //'不正なファイルパスが含まれています。復号できません。'; MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_INVALID_FILE_PATH) + "\n" + CanonicalizePath; MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); delete DataList; goto LabelTypeMiss; } FileList->Add(tsv->Strings[0]); // 0: ファイルパス FileSizeList[i] = StrToIntDef(tsv->Strings[1], -1); // 1: ファイルサイズ(フォルダは-1) FileAttrList[i] = StrToIntDef(tsv->Strings[2], -1); // 2: 属性 FileAgeList[i] = StrToIntDef(tsv->Strings[3], -1); // 3: タイムスタンプ } } delete tsv; delete DataList; //----------------------------------- //ディスクの空き容量チェック //----------------------------------- CurrentDriveFreeSpaceSize = GetDiskFreeSpaceNum(OutDirPath); if (CurrentDriveFreeSpaceSize > -1) { if ( AllTotalSize > CurrentDriveFreeSpaceSize ) { //'復号する先のドライブの空き容量が足りません。'+#13+ //'復号するには、約%dMBの空き容量が必要です。復号処理を中止します。'; MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_DRIVE_NO_FREE_SPACE); free_space_required = (float)AllTotalSize/1024/1024; // MB MsgText = String().sprintf(MsgText.c_str(), free_space_required); MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); goto LabelError; } } else{ // OK! // } //----------------------------------- //複数フォルダ/ファイルを開こうとしているので確認 //----------------------------------- //復号したファイルを関連付けされたソフトで開くか if ( fTempOpenFile == true && FileList->Count > 4) { //'5つ以上のファイルを復号後に開こうとしていますが、処理を続けますか?'+#13+ //'「いいえ」を選択すると、開かず復号します。'; MsgText = LoadResourceString(&Msgdecrypt::_MSG_CONFIRM_OPEN_DECRYPTED_FILES); MsgType = mtConfirmation; MsgButtons = TMsgDlgButtons() << mbYes << mbNo << mbCancel; MsgDefaultButton = mbCancel; Synchronize(&PostConfirmMessageForm); if ( MsgReturnVal == mrCancel ) { goto LabelStop; } else if ( MsgReturnVal == mrNo ) { fTempOpenFile = true; } } //----------------------------------- // 復号開始 //----------------------------------- //'復号しています...' ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_DECRYPTING); ProgressMsgText = ExtractFileName(AtcFilePath); // ファイル(データ本体)サイズを取得する AllTotalSize = fsIn->Size - fsIn->Position + 1; // zlib 前準備 // 圧縮においてすべてのメモリ管理をライブラリに任せる z.zalloc = Z_NULL; z.zfree = Z_NULL; z.opaque = Z_NULL; if (inflateInit(&z) != Z_OK) { // エラー // zlibエラーは最後でまとめてメッセージ処理 goto LabelError; } // 通常は deflate() の第2引数は Z_NO_FLUSH にして呼び出す flush = Z_NO_FLUSH; // 入出力バッファ for (i = 0; i < LARGE_BUF_SIZE; i++) { output_buffer[i] = 0; } z.avail_in = 0; // 入力バッファ中のデータのバイト数 z.next_in = Z_NULL; // 入力バッファ中のデータのバイト数 z.next_out = output_buffer; // 出力バッファ残量 z.avail_out = LARGE_BUF_SIZE; // 出力ポインタ(展開するので大きめに) status = Z_OK; while (Terminated == false) { //----------------------------------- // 入力 //----------------------------------- if (z.avail_in == 0) { TotalSize = InputBuffer(bf, len, source_buffer, fsIn, fInputFileOpen, TotalSize); z.avail_in = len; z.next_in = source_buffer; if ( len == 0 ) { //入力ストリーム終了 fInputEnd = true; } } //----------------------------------- // 展開 //----------------------------------- status = inflate(&z, flush); //----------------------------------- // 処理ステータス //----------------------------------- if ( status == Z_OK ){ if ( z.avail_out == 0 ) { ret = OutputBuffer(output_buffer, LARGE_BUF_SIZE, fsOut, fOutputFileOpen, FileList, FileIndex, FileSizeList, FileAttrList, FileAgeList); if ( ret == 0) { z.next_out = output_buffer; z.avail_out = LARGE_BUF_SIZE; } else if (ret == -1) { goto LabelError; } else{ goto LabelStop; } }//end if (z.avail_out == 0); } //----------------------------------- // バッファエラー //----------------------------------- else if ( status == Z_BUF_ERROR ) { //出力バッファがいっぱいの可能性 //出力バッファをクリアにして継続させる len = LARGE_BUF_SIZE - z.avail_out; ret = OutputBuffer(output_buffer, len, fsOut, fOutputFileOpen, FileList, FileIndex, FileSizeList, FileAttrList, FileAgeList); if (ret == 0) { z.next_out = output_buffer; z.avail_out = LARGE_BUF_SIZE; } else if ( ret == -1) { goto LabelError; } else{ goto LabelStop; } } //----------------------------------- // 終了 //----------------------------------- else if (status == Z_STREAM_END) { break; } //----------------------------------- // エラー //----------------------------------- else{ // #define Z_OK 0 // #define Z_STREAM_END 1 // #define Z_NEED_DICT 2 // #define Z_ERRNO (-1) // #define Z_STREAM_ERROR (-2) // #define Z_DATA_ERROR (-3) // #define Z_MEM_ERROR (-4) // #define Z_BUF_ERROR (-5) // #define Z_VERSION_ERROR (-6) goto LabelError; } //----------------------------------- //進捗状況表示 ProgressPercentNumF = (float)TotalSize/AllTotalSize; ProgressPercentNum = (int)(ProgressPercentNumF*100); if (AllTotalSize < 104857600) { // 100MB未満 ProgressPercentNumText = IntToStr(ProgressPercentNum)+"%"; } else{ ProgressPercentNumText = FloatToStrF(ProgressPercentNumF*100, ffNumber, 4, 1)+"%"; } if ( fInputEnd == true) { break; } }//while (!Terminated); if (Terminated == true) { //ユーザーキャンセルで抜けてきた goto LabelStop; } //---------------------------------------------------------------------- // 万が一、出力バッファに余りがある場合 //---------------------------------------------------------------------- len = LARGE_BUF_SIZE - z.avail_out; ret = OutputBuffer(output_buffer, len, fsOut, fOutputFileOpen, FileList, FileIndex, FileSizeList, FileAttrList, FileAgeList); if ( ret == 0 ) { } else if ( ret == -1 ){ goto LabelError; } else{ goto LabelStop; } if (inflateEnd(&z) != Z_OK) { goto LabelError; } ProgressPercentNum = 100; //'完了' ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_COMPLETE); ProgressMsgText = ExtractFileName(AtcFilePath); if ( fInputFileOpen == true ) { delete fsIn; fInputFileOpen = false; } if ( fOutputFileOpen == true ) { delete fsOut; fOutputFileOpen = false; } delete FileList; delete [] FileSizeList; // 1: ファイルサイズ(フォルダは-1) delete [] FileAttrList; // 2: 属性 delete [] FileAgeList; // 3: 更新日 //復号成功 StatusNum = 1; return; //----------------------------------- //パスワード入力ミスの後始末 //----------------------------------- LabelTypeMiss: ProgressPercentNum = 0; //'エラー' ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR); //'復号に失敗しました。' ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED); if ( fInputFileOpen == true ) { delete fsIn; fInputFileOpen = false; } if ( fOutputFileOpen == true ) { delete fsOut; fOutputFileOpen = false; } delete FileList; delete [] FileSizeList; delete [] FileAttrList; delete [] FileAgeList; StatusNum = -1; return; //----------------------------------- //エラーの後始末 //----------------------------------- LabelError: ProgressPercentNum = 0; if ( status < 0 ){ //'zlibライブラリからエラーを返されました。' //'エラー番号:' MsgText = LoadResourceString(&Msgdecrypt::_MSG_ERROR_ZLIB) + IntToStr(status) + "\n" + z.msg; MsgType = mtError; MsgButtons = TMsgDlgButtons() << mbOK; MsgDefaultButton = mbOK; Synchronize(&PostConfirmMessageForm); } //'エラー' ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_ERROR); //'復号に失敗しました。' ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_FAILED); if ( fInputFileOpen == true ) { delete fsIn; fInputFileOpen = false; } if ( fOutputFileOpen == true ) { delete fsOut; fOutputFileOpen = false; } delete FileList; delete [] FileSizeList; delete [] FileAttrList; delete [] FileAgeList; StatusNum = -2; return; //----------------------------------- //ユーザーキャンセルの後始末 //----------------------------------- LabelStop: ProgressPercentNum = 0; //'キャンセル' ProgressStatusText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_TITLE_USER_CANCEL); //'復号が中止されました。' ProgressMsgText = LoadResourceString(&Msgdecrypt::_LABEL_STATUS_DETAIL_STOPPED); if ( fInputFileOpen == true ) { delete fsIn; fInputFileOpen = false; } if ( fOutputFileOpen == true ) { delete fsOut; fOutputFileOpen = false; } delete FileList; delete [] FileSizeList; delete [] FileAttrList; delete [] FileAgeList; StatusNum = 0; return; }
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; }
int Extract(TCHAR* szFileName) { int temp; HANDLE hFile=CreateFile(szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if(hFile==INVALID_HANDLE_VALUE) return -1; LARGE_INTEGER liFileSize; GetFileSizeEx(hFile,&liFileSize); HANDLE hMap=CreateFileMapping(hFile,0,PAGE_READONLY,liFileSize.HighPart,liFileSize.LowPart,NULL); if(!hMap) { CloseHandle(hFile); return -1; } char* lpOri=(char*)MapViewOfFile(hMap,FILE_MAP_READ,0,0,0); if(!lpOri) { CloseHandle(hFile); CloseHandle(hMap); return -1; } char* p2=new char[20]; char* p3=p2; { char*pend=szFileName+strlen(szFileName); char *p=pend; while(*p--!='\\'); p+=2; while(*p++!='.'&&p<pend) *p3++=*(p-1); *p3='\0'; } string prefix(p2); delete[] p2; 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"; char* pcuroff=lpOri; PAZHDR hdr; //read(fd, &hdr, sizeof(hdr)); memcpy(&hdr,pcuroff,sizeof(hdr)); char simple_key = hdr.toc_len >> 24; read_unobfuscate(pcuroff, simple_key, &hdr, sizeof(hdr)); pcuroff+=sizeof(hdr); unsigned char* toc_buff = new unsigned char[hdr.toc_len]; // unsigned char* toc_buff2 = new unsigned char[hdr.toc_len]; read_unobfuscate(pcuroff, simple_key, toc_buff, hdr.toc_len); pcuroff+=hdr.toc_len; CBlowFish bf; bf.Initialize (keys.toc_key, sizeof(keys.toc_key)); bf.Decode(toc_buff,toc_buff,hdr.toc_len); PAZHDR2* hdr2 = (PAZHDR2*) toc_buff; unsigned char* p = (unsigned char*) (hdr2 + 1); //DWORD tmpp; //HANDLE tmp=CreateFile("a.dat",GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); //WriteFile(tmp,toc_buff,hdr.toc_len,&tmpp,0); //CloseHandle(tmp); unsigned char* mov_seed = NULL; if (is_mov) { mov_seed = p; p += 256; } for (unsigned long i = 0; i < hdr2->entry_count; i++) { string filename = (char*) p; p += filename.length() + 1; PAZENTRY* entry = (PAZENTRY*) p; p += sizeof(*entry); unsigned long len = 0; unsigned char* buff = NULL; len = entry->padded_length; buff = new unsigned char[len]; //lseek(fd, entry->offset, SEEK_SET); pcuroff=lpOri+entry->offset; read_unobfuscate(pcuroff, simple_key, buff, len); 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 ",entry->length); transform(filename.begin (),filename.end (),filename.begin (),tolower); string seed=filename+(string)entrylen+crud; if (is_mov) { decrypt_mov(mov_seed, seed, buff, len); } else { //bfD.SetKey (keys.dat_key ,sizeof(keys.dat_key )); //bfD.ProcessData (buff,buff, len); bf.Initialize(keys.dat_key ,sizeof(keys.dat_key )); bf.Decode(buff,buff,len); if (!crud.empty()) unobfuscate3(seed, buff, len); } char* path=new char[strlen(szFileName)+1]; char* ppath=path+strlen(szFileName); strcpy(path,szFileName); while(*--ppath!='.'); *ppath='\0'; if(!::SetCurrentDirectory(path)) { CreateDirectory(path,0); SetCurrentDirectory(path); } delete[] path; wchar_t *fn=new wchar_t[filename.length()+1]; MultiByteToWideChar(932,0,filename.c_str(),-1,fn,filename.length()+1); HANDLE hNewFile=_MakeFile(fn); //HANDLE hNewFile=CreateFile(filename.c_str(),GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0); if(hNewFile==INVALID_HANDLE_VALUE) continue; WriteFile(hNewFile,buff,entry->length ,(LPDWORD)&temp,0); CloseHandle(hNewFile); delete[] buff; } 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; }