文件类型真实性判断
用来检测文件的后缀是否是真实的后缀,这里我调用的是一个名为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;
}