百度空间 | 百度首页 
 
查看文章
 
文件类型检测 FI 之七
2007-01-09 18:13

class CFI
{
public:
 int  FI(char *strFileName, char *strInfo);

public:
 CFI();
 ~CFI();

private:
 BYTE Buff_H[0x400]; // 头缓冲
 BYTE Buff_E[0x400]; // 入口缓冲
 FILE *fp;
 int  File_Length; // 文件长度
 int  File_Type;  // 文件类型 1-com 2-exe 8-pe
 DWORD EP;    // 入口

private:
 int  GetFileSize(FILE *pFile);
 int  SRead(int FilePos, PBYTE pPage, int nReadLen);
 int  SWrite(int FilePos, PBYTE pPage, int nReadLen);

 DWORD Rva2Phys(IMAGE_NT_HEADERS *pPE_Header, DWORD dwAddr);
 int  InitBuff();
 bool HexstrToHex(char *str, BYTE &Val);
 int  LoadLib_GT();
 int  LoadLib_PE();
 int  LoadLib();
 FILETYPEDATA_GT *FI_GT();
 FILETYPEDATA_PE *FI_PE();
 char *FIRec(char *str);
 cli_file_t cli_filetype(const char *buf, size_t buflen, char *strInfo);
};

CFI::CFI()
{
 fp = NULL;
 File_Type = -1;
 File_Length = 0;
 EP = 0;
}

CFI::~CFI()
{

}

//------------------------------------------------------------------------------- 公用函数
// 函数功能:获取文件的大小
int CFI::GetFileSize(FILE *pFile)
{
 int Pos = ftell(pFile);
 fseek(pFile, 0, SEEK_END);
 int FileSize = ftell(pFile);
 fseek(pFile, Pos, SEEK_SET);

 return FileSize;
}

// 函数功能:读文件到制定缓冲区
int CFI::SRead(int FilePos, PBYTE pPage, int nReadLen)
{
 if (FilePos < 0 || pPage == NULL || nReadLen <= 0)
  return 0;

 fseek(fp, FilePos, SEEK_SET);
 return fread(pPage, 1, nReadLen, fp);
}

// ------------------------------------------------------------------------------- 功能函数
// 函数功能:将PE文件的Image中的线性地址转换成实际偏移
DWORD CFI::Rva2Phys(IMAGE_NT_HEADERS *pPE_Header, DWORD dwAddr)
{
 int  i;
 DWORD dwSectionOffset; // 节表偏移
 IMAGE_SECTION_HEADER *pSection_Header;

 if (pPE_Header == NULL)
  return dwAddr;

 // 范围判断
 if (dwAddr < pPE_Header->OptionalHeader.SizeOfHeaders && (int)dwAddr < File_Length)
  return dwAddr;

 // 遍历节表
 dwSectionOffset = pPE_Header->FileHeader.SizeOfOptionalHeader + 0x18; 
 for (i = 0; i < pPE_Header->FileHeader.NumberOfSections; i ++, dwSectionOffset += 0x28)
 {
  pSection_Header = (IMAGE_SECTION_HEADER*)((BYTE*)pPE_Header + dwSectionOffset);
  if ((dwAddr >= pSection_Header->VirtualAddress)  && (dwAddr < pSection_Header->VirtualAddress+pSection_Header->Misc.VirtualSize))
   return pSection_Header->PointerToRawData + dwAddr - pSection_Header->VirtualAddress ;
 }

 return dwAddr;
}

// 函数功能:初始化缓冲区
// 函数返回:0-失败;1-成功
int CFI::InitBuff()
{
 int     nPeOff;
 IMAGE_DOS_HEADER *pDos_Head;
 IMAGE_NT_HEADERS *pPE_Header;

 if (File_Type == -1)
 {
  memset(Buff_H, 0, sizeof(Buff_H)); // 头缓冲
  memset(Buff_E, 0, sizeof(Buff_E)); // 入口缓冲
 }

 File_Type = 1;
 EP = 0;
 SRead(0, Buff_H, 0x400); // 读头

 // 判断类型
 switch(*(WORD*)Buff_H)
 {
 case 'MZ':
 case 'ZM':
  File_Type = 2;
  break;
 default:
  break;
 }

 // 继续判断
 switch(File_Type)
 {
 case 1:
  {
   // 做为COM文件处理
   EP = 0;
   SRead(EP, Buff_E, 0x400);
  }
  break;
 case 2:
  {
   pDos_Head = (IMAGE_DOS_HEADER*)Buff_H;
   EP = (pDos_Head->e_cs + pDos_Head->e_cparhdr * 0x10 + pDos_Head->e_ip) & 0xfffff;
   SRead(EP, Buff_E, 0x400);

   // 是否存在PE
   nPeOff = *(DWORD*)(Buff_H+0x3c);
   if (nPeOff != 0 && File_Length > nPeOff) 
   {
    SRead(nPeOff, Buff_E, 8);
    if (*(WORD*)Buff_E == 'EP')
    {
     SRead(nPeOff, Buff_H, 0x400);
     File_Type = 8;

     // 读PE入口代码到Buff_E
     pPE_Header = (IMAGE_NT_HEADERS*)Buff_H;
     EP = Rva2Phys(pPE_Header, pPE_Header->OptionalHeader.AddressOfEntryPoint);
     SRead(EP, Buff_E, 0x400);
    }
   }
  }
  break;
 default:
  SRead(0, Buff_E, 0x400);
  break;
 }

 return 1;
}

// 函数功能:16进制字符串转化为数字
// 函数返回:0不是16进制数,1是十六进制数
bool CFI::HexstrToHex(char *str, BYTE &Val)
{
 int  nLen;
 int  i;
 int  pow;
 BYTE s;
 char ch;   
 char *p;

 nLen = 2;
 p = str + nLen;
 s = 0;
 pow = 1;
 for(i = nLen; i > 0; i --)
 {
  ch = *(--p);

  if ((ch >= 'a') && (ch <= 'f'))
   ch = ch - 'a' + 10;
  else if ((ch >= 'A') && (ch <= 'F'))
   ch = ch -  'A' + 10;
  else if ((ch >= '0') && (ch <= '9'))
   ch = ch - '0';
  else
   return false;

  s += ch * pow;
  pow *= 16;
 }

 Val = s;
 return 1;
}

// 函数功能:加载文件类型数据
// 函数返回:0-失败;1-成功
int CFI::LoadLib_GT()
{
 int  i, j;
 int  nRecCount;
 int  nStrLen;
 char *p;
 FILETYPEDATA_GT *pRecGT;

 // 加载GT库
 pRecGT = FileTypeRec_GT;
 nRecCount = sizeof(FileTypeRec_GT)/sizeof(FILETYPEDATA_GT);
 for (i = 0; i < nRecCount; i ++, pRecGT ++)
 {
  memset(pRecGT->RecData, 0, sizeof(pRecGT->RecData));
  nStrLen = strlen(pRecGT->strData);
  pRecGT->nRecLen = nStrLen/2;
  p = pRecGT->strData;
  for (j = 0; j < pRecGT->nRecLen; j ++)
  {
   if (!HexstrToHex(p, pRecGT->RecData[j]))
    break;
   p += 2;
  }
 }
 return 1;
}

// 函数功能:加载文件类型数据
// 函数返回:0-失败;1-成功
int CFI::LoadLib_PE()
{
 int  i, j;
 int  nRecCount;
 int  nStrLen;
 char *p;
 FILETYPEDATA_PE *pRecPE;

 // 加载PE库
 pRecPE = FileTypeRec_PE;
 nRecCount = sizeof(FileTypeRec_PE)/sizeof(FILETYPEDATA_PE);
 for (i = 0; i < nRecCount; i ++, pRecPE ++)
 {
  // Pos
  memset(pRecPE->PosData, 0, sizeof(pRecPE->PosData));
  nStrLen = strlen(pRecPE->Pos);
  pRecPE->nPosLen = nStrLen/2;
  p = pRecPE->Pos;
  for (j = 0; j < pRecPE->nPosLen; j ++)
  {
   if (!HexstrToHex(p, pRecPE->PosData[j]))
    break;
   p += 2;
  }

  // Fea
  memset(pRecPE->FeaData, 0, sizeof(pRecPE->FeaData));
  nStrLen = strlen(pRecPE->Fea);
  pRecPE->nFeaLen = nStrLen/2;
  p = pRecPE->Fea;
  for (j = 0; j < pRecPE->nFeaLen; j ++)
  {
   if (!HexstrToHex(p, pRecPE->FeaData[j]))
    break;
   p += 2;
  }
 }
 return 1;
}

// 函数功能:加载文件类型数据
// 函数返回:0-失败;1-成功
int CFI::LoadLib()
{
 LoadLib_GT();
 LoadLib_PE();
 return 1;
}

// 分析文件类型GT
FILETYPEDATA_GT *CFI::FI_GT()
{
 int  i, j, s;
 int  nRecCount;
 BYTE *p;
 FILETYPEDATA_GT *pRecGT;

 // GT库
 pRecGT = FileTypeRec_GT;
 nRecCount = sizeof(FileTypeRec_GT)/sizeof(FILETYPEDATA_GT);
 for (i = 0; i < nRecCount; i ++, pRecGT ++)
 {
  s = 0;
  p = pRecGT->RecData;
  for (j = 0; j < pRecGT->nRecLen; j ++, p ++)
  {
   if (*p == 0)
    continue;
   s = s + (*p ^ Buff_E[j]);
   if (s != 0)
    break;
  }
  if (s == 0)
   return pRecGT;
 }

 return NULL;
}

// 分析文件类型PE
FILETYPEDATA_PE *CFI::FI_PE()
{
 int  i, j;
 int  nRecCount;
 BYTE *p;
 FILETYPEDATA_PE *pRecPE;

 // PE库
 pRecPE = FileTypeRec_PE;
 nRecCount = sizeof(FileTypeRec_PE)/sizeof(FILETYPEDATA_PE);
 for (i = 0; i < nRecCount; i ++, pRecPE ++)
 {
  p = pRecPE->FeaData;
  if (pRecPE->IsOrdered)
  {
   for (j = 0; j < pRecPE->nFeaLen; j ++, p ++)
   {
    if (*p != Buff_E[j])
     break;
   }
   if (j == pRecPE->nFeaLen)
    return pRecPE;
  }
  else
  {
   for (j = 0; j < pRecPE->nFeaLen; j ++, p ++)
   {
    if (*p != Buff_E[pRecPE->PosData[j]-1])
     break;
   }
   if (j == pRecPE->nFeaLen)
    return pRecPE;
  }
 }

 return NULL;
}

// 分析文件类型
char *CFI::FIRec(char *str)
{
 FILETYPEDATA_GT *pRecGT;
 FILETYPEDATA_PE *pRecPE;

 // PE
 if ((pRecPE=FI_PE()) != NULL)
 {
  strcpy(str, pRecPE->Info);
  return str;
 }

 // GT
 if ((pRecGT=FI_GT()) != NULL)
 {
  strcpy(str, pRecGT->strName);
  strcat(str, "   ");
  strcat(str, pRecGT->strType);
  return str;
 }

 return NULL;
}

// 函数功能:分析文件类型
cli_file_t CFI::cli_filetype(const char *buf, size_t buflen, char *strInfo)
{
 int i, ascii = 1, len;

 for(i = 0; cli_magic[i].magic; i++) 
 {
  if(buflen >= cli_magic[i].offset+cli_magic[i].length) 
  {
   if(memcmp(buf+cli_magic[i].offset, cli_magic[i].magic, cli_magic[i].length) == 0) 
   {
    strcpy(strInfo, cli_magic[i].descr);
    return cli_magic[i].type;
   }
  }
 }

 buflen < 25 ? (len = buflen) : (len = 25);
 for(i = 0; i < len; i++)
 {
  if(!internat[buf[i] & 0xff]) 
  {
   ascii = 0;
   break;
  }
 }

 if (ascii)
  strcpy(strInfo, "Text file.");
 else
  strcpy(strInfo, "COM file or Others.");
 return ascii ? CL_TYPE_UNKNOWN_TEXT : CL_TYPE_UNKNOWN_DATA;
}

// 分析文件加壳等类型
int CFI::FI(char *strFileName, char *strInfo)
{
 // 打开文件
 if ((fp = fopen(strFileName, "rb")) == NULL)
 {
  strcpy(strInfo, "Open file failed.");
  return false;
 }

 // 读文件大小
 if ((File_Length = GetFileSize(fp)) == 0)
 {
  strcpy(strInfo, "Size of file is 0.\n");
  return false;
 }

 // 初始化缓冲区
 if (!InitBuff())
 {
  strcpy(strInfo, "Isn't exe file.\n");
  return false;
 }

 // 加载类型库
 if (!LoadLib())
 {
  strcpy(strInfo, "Load filetype lib failed.\n");
  return false;
 }

 // 判断类型
 if (!FIRec(strInfo))
 {
  if (File_Type == 2)
   strcpy(strInfo, "DOS execute file!\n");
  else if (File_Type == 8)
   strcpy(strInfo, "PE file!\n");
  else 
  {
   SRead(0, Buff_H, sizeof(Buff_H));
   cli_filetype((char*)Buff_H, sizeof(Buff_H), strInfo);
  }
 }
 return true;
}

void main(int avgc, char **argv)
{
 char strFileInfo[0x200];
 CFI  aFi;

 // 初始化
 printf("FileInfo v1.0 (c) 2006.10.23 by wangwei.\n");
 printf("My bolg: http://hi.baidu.com/avengine\n\n");
 memset(strFileInfo, 0, sizeof(strFileInfo));
 if (avgc != 2)
 {
  printf("Fi [FILE]\n");
  return;
 }

 // 判断类型
 aFi.FI(argv[1], strFileInfo);
 printf("%s\n", strFileInfo);
}

 


类别:应用源码 | 添加到搜藏 | 浏览() | 评论 (1)
 
最近读者:
 
网友评论:
1
2008-03-27 13:07 | 回复
好东西居然没人顶?呵呵!
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu