文件类型真实性判断

c++

Posted by YiMiTuMi on January 11, 2021

文件类型真实性判断

用来检测文件的后缀是否是真实的后缀,这里我调用的是一个名为TrID的开源软件,同时他给我们提供了对外的接口。

通过对比文件的二进制数据来查找特征值,收集足够的特征值来判断文件所占类型的比例。但是纯文本文件是没办法进行判断的。

注意:Exe、Dll等文件都是PE文件所以判断出来的都为Exe后缀文件。

文件官网: https://mark0.net/soft-trid-deflist.html

DLL文件下载地址还附送例子: https://mark0.net/code-tridlib-e.html

TrIDDefs.TRD是很重要的文件,里面保存着对比文件类型的效验值,作者会定时更新。

例:

#include "stdafx.h"
#include "tridlib.h"
#include <windows.h>
#include <string>
#include <atlstr.h>
#include <iostream>

using namespace std;

string strFilePath;

void FileSuffixVerification(char* szFilePath)
{
	int ret;
	
	string strText = strFilePath + '\\';
	char* szInstall = (char *)strText.c_str();
	
	strText = strFilePath + '\\' + "TrIDLib.dll";
	char* szInstallDll = (char *)strText.c_str();

	trid trd(szInstall, szInstallDll); //TrIDDefs.TRD文件路径,Dll文件路径
	trd.SubmitFileA(szFilePath);
	ret = trd.Analyze();
	if(ret)
	{
		char buf[260];
		*buf = 0;
		ret = trd.GetInfo(TRID_GET_RES_NUM,0,buf);
		printf("%d matches\n",ret);

		for(int i = ret+1; --i;)
		{
			trd.GetInfo(TRID_GET_RES_FILETYPE,i,buf);
			printf("File type: %s\n",buf);
			trd.GetInfo(TRID_GET_RES_FILEEXT,i,buf);;
			printf("File ext: .%s\n",buf);
			ret = trd.GetInfo(TRID_GET_RES_POINTS,i,buf);
			printf("Matching points: %d\n\n",ret);
		}
	}
	else
		puts("analyze:(");

	return ;
}

int _tmain(int argc, _TCHAR* argv[])
{
	//获取当前安装路径
	CHAR szModuleFileName[MAX_PATH]; 
	GetModuleFileNameA(NULL, szModuleFileName, MAX_PATH);

	strFilePath = szModuleFileName;

	int iVal = strFilePath.find_last_of('\\');
	if (iVal == -1)
	{
		return 0;
	}
	
	strFilePath = strFilePath.substr(0, iVal);


	string strPath;
	cin >> strPath;

	FileSuffixVerification((char *)strPath.c_str());

	cin >> strPath;
	return 0;
}

应用

我写了一个函数,返回类型是否为真实的文件类型,同时如果不是真实类型返回一个有可能的类型列表,但是DLL提供的函数是不支持中文目录的,所以需要将文件移动到临时目录进行判断。

移动文件函数:

//接受一个源文件路径,目的路径,文件后缀
BOOL MoveFileToTempPath(CString strFilePath, CString &strFileTempPath, CString &strFileSuffix)
{
	wchar_t szTempPath[MAX_PATH];
	GetTempPathW(MAX_PATH, szTempPath);
	//CString strTempPath = szTempPath;

	CString strPath;

	//获取文件后缀
	int iVal = strFilePath.ReverseFind('.');
	if (iVal != -1)
	{
		strFileSuffix = strFilePath.Mid(iVal + 1);
	}

	//拼接路径
	strFileTempPath.Format(L"%sTempFileJudgeSuffix.%s", szTempPath, strFileSuffix.GetString());

	CopyFile(strFilePath, strFileTempPath, FALSE);
	if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFileTempPath))
	{
		return FALSE;
	}

	return TRUE;
}

删除文件:

void DeleteMoveTempFile(CString &strFileTempPath)
{
	if (strFileTempPath.IsEmpty())
	{
		return;
	}

	if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strFileTempPath))
	{
		return;
	}

	DeleteFileW(strFileTempPath.GetString());
}

文件类型判断函数:

//判断文件类型真实性, strRetDetectionInfo  后缀不符合时可能的文件类型, strRetDetectionInfo为空则为真实后缀
BOOL FileTypeAuthenticity(CString &strRetDetectionInfo) 
{

	CString strClientInstallPath = L"E:\\xxxxx\\xxxxx\\xxxx\\bin\\";  //DLL所在路径
	CString strFilePath;  //判断后缀的文件路径	


	if (strClientInstallPath.IsEmpty() || strFilePath.IsEmpty())
	{
		return FALSE;
	}

	//文件不存在,不能使用该功能
	if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strClientInstallPath + _T("TrIDLib.dll")))
	{
		return FALSE;
	}

	if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(strClientInstallPath + _T("triddefs.trd")))
	{
		return FALSE;
	}
	
	CString strFileSuffix;
	CString strDllPath = strClientInstallPath;
	strDllPath += L"TrIDLib.dll";

	CString strTempFilePath;
	CString strResult;
	CString strTemp;
	CString strText;
	map<CString, int> mapExtType;
	int iSuffix = 0;
	int ret = 0;
	strFileSuffix.MakeLower();

	//将文件copy到临时目录后,判断文件,防止存在中文目录
	if (!MoveFileToTempPath(strFilePath, strTempFilePath, strFileSuffix))
	{
		return FALSE;
	}

	//初始化
	trid trd(CW2A(strClientInstallPath.GetString()), CW2A(strDllPath.GetString()));
	ret = trd.SubmitFileA(CW2A(strTempFilePath.GetString())); //‪C:\\Users\\WGH\\Desktop\\CW.exe     CW2A(strTempFilePath.GetString())
	ret = trd.Analyze();

	if (ret)
	{
		char buf[260];
		*buf = 0;
		ret = trd.GetInfo(TRID_GET_RES_NUM, 0, buf);
		//printf("%d matches\n",ret);
		strTemp.Format(_T("%d matches\n"), ret);
		strResult += strTemp;

		if (ret != 0)
		{ 
			//匹配到了扩展名,需要判断最大可能性的扩展名
			int iTotal = 0;
			for (int i = ret + 1; --i;)
			{
				trd.GetInfo(TRID_GET_RES_FILETYPE, i, buf);
				//printf("File type: %s\n",buf);

				strText = CA2W(buf);
				strTemp.Format(_T("File type: %s\r\n"), strText.GetString());

				strResult += strTemp;
				trd.GetInfo(TRID_GET_RES_FILEEXT, i, buf);;
				//printf("File ext: .%s\n",buf);
				CString strExtTpe;


				strText = CA2W(buf);
				strExtTpe.Format(_T("%s"), strText.GetString());
				strTemp.Format(_T("File ext: .%s\r\n"), strText.GetString());


				strResult += strTemp;
				ret = trd.GetInfo(TRID_GET_RES_POINTS, i, buf);
				//printf("Matching points: %d\n\n",ret);

				strTemp.Format(_T("Matching points: %d\r\n"), ret);
				strResult += strTemp;
				iTotal += ret;

				int iExtPoint = ret;
				strExtTpe.MakeLower();

				if (strExtTpe == strFileSuffix)
				{
					if (iSuffix < iExtPoint)
					{
						iSuffix = iExtPoint;
					}
				}

				map<CString, int>::iterator iter = mapExtType.find(strExtTpe.GetString());
				if (iter != mapExtType.end())
				{
					iter->second = iExtPoint;
				}
				else
				{
					mapExtType.insert(std::make_pair(strExtTpe, iExtPoint));
				}
			}
		}
	}
	else
	{
		//puts("analyze:(");
		strTemp.Format(_T("analyze:("));
		strResult += strTemp;

		DeleteMoveTempFile(strTempFilePath);
		return TRUE;
	}

	//判断后缀是否符合
	if (mapExtType.empty())
	{
		DeleteMoveTempFile(strTempFilePath);
		return TRUE;
	}


	BOOL bjue = FALSE;
	map<CString, int>::iterator itermap = mapExtType.begin();
	for (; itermap != mapExtType.end(); itermap++)
	{
		if (itermap->second == iSuffix)
		{
			bjue = TRUE;
		}

		//保存文件后缀
		CString strFileType = itermap->first;
		if (!strFileType.IsEmpty())
		{
			strRetDetectionInfo += strFileType;
			strRetDetectionInfo += ",";
		}
	}
	
	if (bjue == TRUE)
	{
		strRetDetectionInfo = L"";
	}
	
	DeleteMoveTempFile(strTempFilePath);
	return bjue;
}

蓝色妖姬 – 相守