首页
社区
课程
招聘
[旧帖] [原创]判断PE文件的入口是否正常 0.00雪花
发表于: 2012-2-4 19:55 1538

[旧帖] [原创]判断PE文件的入口是否正常 0.00雪花

2012-2-4 19:55
1538
GetRVA.rar
在学习PE文件的格式的时候写的,通过获取IMAGE_OPTIONAL_HEADER 的AddressOfEntryPoint得到程序的执行入口地址c,然后获取区块.text的地址范围[a,b],如果c不再[a,b]的范围里面,则入口是异常的,可能被加壳
#pragma warning(disable:4786)
#include<windows.h>
#include<stdio.h>
#include<iostream>
#include<winnt.h>
#include<stdlib.h>
#include<imagehlp.h>
#include<cstring>
#include<string>
#include<vector>
#include<string.h>
using namespace std;
/////////////////////
#pragma comment(lib,"imagehlp.lib")
///////////////////////////////////////////////////////
//
//
typedef struct _MAP_FILE_STRUCT
{
  HANDLE hFile;
  HANDLE hMapping;
  LPVOID ImageBase;
}MAP_FILE_STRUCT,*PMAP_FILE_STRUCT;
/////////////////////
#define GETTHUNK(pImportDesc) ((DWORD)                                             \
  (                                                          \
  (PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->OriginalFirstThunk ?                           \
        (PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->OriginalFirstThunk:(PIMAGE_IMPORT_DESCRIPTOR)pImportDesc->FirstThunk ) \
)
///////////////////////////////////////////////
//函数功能:载入文件句柄,文件映像,文件基地址
//参    数:lpFilename文件名
//          PMAP_FILE_STRUCT文件结构体
//返    回:打开成功返回TRUE
///////////////////////////////////////////////
bool load(LPTSTR lpFilename,PMAP_FILE_STRUCT &p)
{
  HANDLE hFile=CreateFile(lpFilename,GENERIC_READ,FILE_SHARE_READ,NULL,
    OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,0);
  if(!hFile)
  {
    cout<<"file open error"<<endl;
    return false;
  }
  HANDLE hMapping=CreateFileMapping(hFile,NULL,PAGE_READONLY,0,0,NULL);
  if(!hMapping)
  {
    cout<<"file map error"<<endl;
    return false;
  }
  LPVOID ImageBase=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0);
  if(!ImageBase)
  {
    cout<<"file load error"<<endl;
    return false;
  }
  p->hFile=hFile;
  p->hMapping=hMapping;
  p->ImageBase=ImageBase;
  return true;
}
///////////////////////////////////////////////
//函数功能:判断文件是否为PE文件
//参    数:ImageBase文件的基地址
//返    回:是PE文件返回TRUE
///////////////////////////////////////////////
bool IsPE(LPVOID ImageBase)
{
  PIMAGE_DOS_HEADER pdos=NULL;
  PIMAGE_NT_HEADERS pnt=NULL;
  pdos=(PIMAGE_DOS_HEADER)ImageBase;
  if(pdos->e_magic!=IMAGE_DOS_SIGNATURE)
  {
    return false;
  }
  pnt=(PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
  if(pnt->Signature!=IMAGE_NT_SIGNATURE)
  {
    return false;
  }
  return true;
}
///////////////////////////////////////////////
//函数功能:获取文件的PIMAGE_NT_HEADERS地址
//参    数:ImageBase文件的基地址
//返    回:返回PIMAGE_NT_HEADERS
///////////////////////////////////////////////
PIMAGE_NT_HEADERS  GetNtHead(LPVOID ImageBase)
{
  if(!IsPE(ImageBase))
  {
    return NULL;
  }
  PIMAGE_NT_HEADERS  pnt;
  PIMAGE_DOS_HEADER  pdos;
  pdos=(PIMAGE_DOS_HEADER)ImageBase;
  pnt=(PIMAGE_NT_HEADERS)((DWORD)pdos+pdos->e_lfanew);
  return pnt;
}
///////////////////////////////////////////////
//函数功能:获取文件的PIMAGE_OPTIONAL_HEADER地址
//参    数:ImageBase文件的基地址
//返    回:返回PIMAGE_OPTIONAL_HEADER
///////////////////////////////////////////////
PIMAGE_OPTIONAL_HEADER GetOptionalHead(LPVOID ImageBase)
{
  PIMAGE_DOS_HEADER pdos=NULL;
  PIMAGE_NT_HEADERS pnt=NULL;
  PIMAGE_OPTIONAL_HEADER poptional=NULL;
  pnt=GetNtHead(ImageBase);
  poptional=&(pnt->OptionalHeader);
  return poptional;
}

///////////////////////////////////////////////////////////////////////
//函数功能:获取程序执行入口
//参    数:ImageBase文件的基地址
//返    回:程序执行入口地址
//////////////////////////////////////////////////////////////////////
DWORD GetAddressOfEntryPoint(LPVOID ImageBase)
{
    PIMAGE_OPTIONAL_HEADER poptional=GetOptionalHead(ImageBase);
    return poptional->AddressOfEntryPoint;
}
///////////////////////////////////////////////////////////////////////
//函数功能:函数入口是否正常
//参    数:ImageBase文件的基地址
//返    回:正常返回TRUE
//////////////////////////////////////////////////////////////////////
bool EntryPointIsRright(LPVOID ImageBase)
{
  DWORD c=GetAddressOfEntryPoint(ImageBase);
  PIMAGE_NT_HEADERS pnh=NULL;
  PIMAGE_FILE_HEADER pfh=NULL;
  PIMAGE_SECTION_HEADER psh=NULL;
  pnh=GetNtHead(ImageBase);
  pfh=(PIMAGE_FILE_HEADER)&pnh->FileHeader;
  int num=pfh->NumberOfSections;
  psh=IMAGE_FIRST_SECTION(pnh);
  int i,j;
  for( i=0;i<num&&psh;i++,psh++)
  {
    string tmp;
    for( j=0;j<8;j++)
    {
      char ch=psh->Name[j];
      if(ch=='.'||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))
      {
        tmp+=psh->Name[j];
      }
    }
    int a=psh->VirtualAddress;
    int b=psh->VirtualAddress+psh->SizeOfRawData;
    //printf("%s %d %d\n",tmp.c_str(),psh->VirtualAddress,psh->SizeOfRawData+psh->VirtualAddress);
    if(tmp==".text"&&a<=c&&c<=b)
    {
      return true;
    }
  }
  return false;
}
////////////////////////////////////////////////////////////////////
int main()
{
  //freopen("a.txt","w",stdout);
  string s;
  printf("输入文件目录:");
  while(cin>>s)
  {
    LPTSTR filename=(LPTSTR )s.c_str();
    PMAP_FILE_STRUCT map;
    map=(PMAP_FILE_STRUCT)malloc(sizeof(MAP_FILE_STRUCT));
    if(!load(filename,map))
    {
      cout<<"load() error"<<endl;
      return 0;
    }
    if(!IsPE(map->ImageBase))
    {
      cout<<"ispe() error"<<endl;
      return 0;
    }
    bool t=EntryPointIsRright(map->ImageBase);
    printf("%d\n",t);
  }
  return 0;
}

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 1149
活跃值: (888)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
2
这个不一定很准确,如果自定义了text 标记呢....所以 不能从名字上着手.....
ps:对于壳的判断需要很强大的理论,但这个也是仅仅理论上的 正确,也是可能出现误判的

http://www.unpack.cn/archiver/tid-51639.html
可以看看这个
2012-2-4 20:38
0
雪    币: 145
活跃值: (105)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
这种方法确实被.text自定义干掉啦,我看了你发的那个,是用了样本统计出来的方法,不知道效果怎么样,有没有完整源码发一下来测试
2012-2-4 20:54
0
雪    币: 603
活跃值: (40)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
4
。。。。判断的相对性。。。
2012-2-4 20:58
0
雪    币: 1149
活跃值: (888)
能力值: ( LV13,RANK:260 )
在线值:
发帖
回帖
粉丝
5
kanxue.com
2012-2-4 21:04
0
雪    币: 145
活跃值: (105)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
6
        for(i = 0; i < pFH->NumberOfSections; i++)
        {
                PBYTE        pData = (PBYTE)ImageBase+pSH->PointerToRawData;
                DWORD        dwLength =pSH->SizeOfRawData<pSH->Misc.VirtualSize? pSH->SizeOfRawData : pSH->Misc.VirtualSize;

                while(dwLength && pData[dwLength - 1] == 0)
                {
                        dwLength--;
                }
                pSH++;
        }
大牛推荐的代码里面有这个,pData[dwLength-1]总是会越界,求问其中错误的原因
2012-2-16 16:07
0
游客
登录 | 注册 方可回帖
返回
//