一个检测二进制文件内容的工具
// incorporate.cpp : Defines the entry point for the console application. // #include "stdafx.h" #include "assert.h" #include "stdio.h" #include<windows.h> #include <fstream> #include <iostream> #include <string> using namespace std; #include "jtzCompress.h" #include "jtcCompress.h" static bool checkContext(const char * fileName, const char * szCheck); static bool checkIfDataHasStr(const char * fileName, const char * szCheck, Byte * pData, UInt32 nFileLen); //单字节、双字节互转 static char * wstrTostr(const wchar_t * lpcwszStr){ DWORD dwNum = WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,NULL,0,NULL,FALSE); char *psText = NULL; psText = new char[dwNum*sizeof(char)]; if(!psText) { delete(psText); psText = NULL; return psText; } WideCharToMultiByte(CP_OEMCP,NULL,lpcwszStr,-1,psText,dwNum,NULL,FALSE); return psText; } static wchar_t * strToWstr(const char * lpcwszStr){ DWORD dwNum = MultiByteToWideChar (CP_ACP, 0, lpcwszStr, -1, NULL, 0); wchar_t *psText = NULL; psText = new wchar_t[dwNum];; if(!psText) { delete(psText); psText = NULL; return psText; } MultiByteToWideChar (CP_ACP, 0, lpcwszStr, -1, psText, dwNum); return psText; } ostream & green(ostream & s) { HANDLE hstdhadle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hstdhadle, FOREGROUND_GREEN|FOREGROUND_INTENSITY); return s; } ostream & white(ostream & s) { HANDLE hstdhadle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hstdhadle, FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY); return s; } class CFile{ private: fstream m_fout; public: CFile(){ m_fout.open("out.txt", ios::out | ios::binary); } //检查要测试文件的路径 void checkFolder(const char* lpPath, const char * szCheck, bool bNeedCheckAllFile){ assert(lpPath); char szFind[1024]; char szFile[1024]; WIN32_FIND_DATA FindFileData; strcpy_s(szFind,lpPath); strcat_s(szFind,"*.*"); wchar_t * wszFind = strToWstr(szFind); HANDLE hFind=FindFirstFile(wszFind,&FindFileData); delete wszFind; if (INVALID_HANDLE_VALUE == hFind) return; bool bHasFileFinded = false;//如果有文件已经找到匹配了,不用全部文件遍历 while(true) { if (FindFileData.dwFileAttributes == FILE_ATTRIBUTE_DIRECTORY) { if (FindFileData.cFileName[0]!='.') { strcpy_s(szFile,lpPath); char * pFileName = wstrTostr(FindFileData.cFileName); strcat_s(szFile,pFileName); strcat_s(szFile,"\\"); delete pFileName; checkFolder(szFile, szCheck, bNeedCheckAllFile); } } else if(bHasFileFinded == false || bNeedCheckAllFile == true) { char * pFileName = wstrTostr(FindFileData.cFileName); char pFilePath[1024] = {0}; strcpy_s(pFilePath,lpPath); strcat_s(pFilePath,pFileName); bHasFileFinded = checkContext(pFilePath, szCheck); delete pFileName; } if (!FindNextFile(hFind,&FindFileData)) break; } FindClose(hFind); } bool checkContext(const char * fileName, const char * szCheck) { fstream fin; bool bRet = false; if(ifFileTypeEqual(fileName, "jtz")) { Byte* fileContext = NULL; UInt32 nFileLen = 0; wchar_t * pFileName = strToWstr(fileName); fin.open(pFileName, ios::in | ios::binary);//防止有中文名 fin.seekg(0, ios::end); nFileLen = fin.tellg(); fileContext = new Byte[nFileLen]; fin.seekg(0, ios::beg); fin.read((char*)fileContext, nFileLen); fin.close(); Byte* unzipMem = NULL; UInt32 unzipSize = 0; Unzip(&unzipMem, &unzipSize, fileContext, nFileLen); delete fileContext; //检测 bRet = checkIfDataHasStr(fileName, szCheck, unzipMem, unzipSize); delete unzipMem; delete pFileName; return bRet; } if(ifFileTypeEqual(fileName, "jtc")) { Byte* unzipMem = NULL; UInt32 unzipSize = 0; CJtcCompress * jtcInstance = new CJtcCompress(fileName); unzipMem = jtcInstance->Decode(unzipSize); delete jtcInstance; wchar_t * pFileName = strToWstr(fileName); //检测 bRet = checkIfDataHasStr(fileName, szCheck, unzipMem, unzipSize); delete unzipMem; delete pFileName; return bRet; } //其他文件格式,直接用strstr即可 if(ifFileTypeEqual(fileName, "ini") || ifFileTypeEqual(fileName, "cfg") || ifFileTypeEqual(fileName, "txt") || ifFileTypeEqual(fileName, "mod")) { Byte* unzipMem = NULL; UInt32 unzipSize = 0; wchar_t * pFileName = strToWstr(fileName); fin.open(pFileName, ios::in | ios::binary);//防止有中文名 assert(fin); fin.seekg(0, ios::end); unzipSize = fin.tellg(); unzipMem = new Byte[unzipSize]; fin.seekg(0, ios::beg); fin.read((char*)unzipMem, unzipSize); fin.close(); //检测 bRet = checkIfDataHasStr(fileName, szCheck, unzipMem, unzipSize); delete unzipMem; delete pFileName; return bRet; } if(ifFileTypeEqual(fileName, "bar")) { char copyLocalCmd[512]; char delLocalCmd[512]; char brewrcCmd[512]; const wchar_t * wszBarName = L"demo.bar"; const wchar_t * wszBrxName = L"demo.brx"; const char * szBarName = "demo.bar"; wchar_t * pFileName = strToWstr(fileName); copyFileToOtherPath(pFileName, wszBarName); sprintf_s(brewrcCmd, 512, "brewrc.exe -d %s > 1.txt", szBarName); system(brewrcCmd);//执行Brew反解析工具 DeleteFile(wszBarName); Byte* unzipMem = NULL; UInt32 unzipSize = 0; fin.open(wszBrxName, ios::in | ios::binary);//防止有中文名 fin.seekg(0, ios::end); unzipSize = fin.tellg(); unzipMem = new Byte[unzipSize]; fin.seekg(0, ios::beg); fin.read((char*)unzipMem, unzipSize); fin.close(); //检测 bRet = checkIfDataHasStr(fileName, szCheck, unzipMem, unzipSize); delete unzipMem; delete pFileName; return bRet; } return bRet; } //判定文件后缀是否匹配 bool ifFileTypeEqual(const char * fullName, const char * szCompare){ assert(fullName && szCompare); bool bRet = false; string * str = new string(fullName); int nLen = str->find_last_of('.'); if (nLen <= 0) bRet = false; else { const char * sz = fullName + nLen + 1; if(strcmp(sz, szCompare) == 0) bRet = true; } delete str; return bRet; } //判定文件后缀是否匹配 const char * getBrxName(const char * fullName){ assert(fullName); char * szRet = NULL; string * str = new string(fullName); int nLen = str->find_last_of('.'); if (nLen > 0) { szRet = strdup(fullName); nLen++; szRet[nLen] = 'b'; nLen++; szRet[nLen] = 'r'; nLen++; szRet[nLen] = 'x'; } delete str; return szRet; } void copyFileToOtherPath(const wchar_t * wszSrc, const wchar_t * wszDes) { assert(wszDes && wszSrc); fstream fin, fout; fin.open(wszSrc, ios::in | ios::binary); if(fin.is_open()) { Byte * buf = NULL; UInt32 nFileLen = 0; fin.seekg(0, ios::end); nFileLen = fin.tellg(); buf = new Byte[nFileLen]; fin.seekg(0, ios::beg); fin.read((char *)buf, nFileLen); fin.close(); fout.open(wszDes, ios::out | ios::binary); if (fout.is_open()) { fout.write((char *)buf, nFileLen); fout.close(); } } } bool checkIfDataHasStr(const char * fileName, const char * szCheck, Byte * pData, UInt32 nFileLen) { assert(pData && fileName && szCheck); bool bRet = false; UInt32 nCheckLen = strlen(szCheck); UInt32 nCheckOffest = 0; UInt32 nOffest = 0; while (nOffest < nFileLen){ while(nOffest < nFileLen && pData[nOffest++] == szCheck[nCheckOffest++]) { if(nCheckOffest == nCheckLen) { const char * c_file = "文件:"; const char * c_have = " 有 "; const char * c_changeline = "\r\n"; m_fout.write(c_file, strlen(c_file)); m_fout.write(fileName, strlen(fileName)); m_fout.write(c_have, strlen(c_have)); m_fout.write(szCheck, strlen(szCheck)); m_fout.write(c_changeline, strlen(c_changeline)); return true; } } nCheckOffest = 0; } cout << white << "检测文件:" << green << fileName << white << endl; return bRet; } ~CFile(){ if(m_fout) m_fout.close(); } }; int main(int argc, char* argv[]/* f */) { //说明 if(argc >= 2 && strcmp(argv[1], "/?") == 0) { cout << "参数1:要检查的目录,以‘/’结束,如“Res/”" << endl; cout << "参数2:要检查的字符串" << endl; cout << "参数3(Y/N):是否检测到一个文件存在要查字符串,就不再查这个目录下的其他文件" << endl; cout << "目前会查的文件有:bar、jtz、jtc、mod、cfg、ini、txt" << endl; return 0; } CFile * pFile = new CFile(); if(argc > 3) { if (toupper(*argv[3]) == 'Y') pFile->checkFolder(argv[1], argv[2], true); else pFile->checkFolder(argv[1], argv[2], false); } else pFile->checkFolder("res\\", "base_url", false); delete pFile; getchar(); return 0; }