Exemple #1
0
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 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);
}
//===========================================================================
//スレッド実行
//===========================================================================
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;

}
Exemple #4
0
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;
}
Exemple #5
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;
}