学习PE文件格式后编写的简单代码(C代码)

/* 
 * 近日学习pe文件格式,写了一个简单的分析程序
 * 个人网站:http://ggg82.126.com
 * 电子邮件:ggg82@163.com
 * QQ:358416653
 *
 * 本程序在win2000+vc6平台编译通过
 * 学习参考:看学论坛
 */
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
void help()
{
  printf("Usage:Pedir <exefile>/n");
  printf("Press any key to exit this program./n");
  getch();
}
//IMAGE_DOS_SIGNATURE 
int main(int argc,char *argv[])
{
  IMAGE_DOS_HEADER *pDosHead;
  IMAGE_NT_HEADERS *pPeHead;
  IMAGE_SECTION_HEADER *pSectionHead;
  HANDLE hFile,hMapping;
  char *pBasePoint;
//  char buffer[MAX_PATH];
  int i;
  if(argc<2)
  {
    help();
    exit(1);
  }
  hFile=CreateFile(argv[1],GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING, 
    FILE_ATTRIBUTE_NORMAL,0);    //Create the File handle
  if (hFile==INVALID_HANDLE_VALUE)
  {  //test File Handle
    GetLastError(); 
    return 0; 
  } 
  if (!(hMapping=CreateFileMapping(hFile,0,PAGE_READONLY|SEC_COMMIT,0,0,0)))
  {                  //Create the File Map and test
    CloseHandle(hFile);
    return 0;
  }
  if (!(pBasePoint=MapViewOfFile(hMapping,FILE_MAP_READ,0,0,0)))
  {                  
    CloseHandle(hFile);
    CloseHandle(hMapping);
    return 0;
  } // GetShortPathName(argv[1],buffer,sizeof buffer);
  //判断是否是pe文件
  pDosHead=(IMAGE_DOS_HEADER *)pBasePoint;
  if(IMAGE_DOS_SIGNATURE!=pDosHead->e_magic)
  {
    printf("DOS文件头出错!/n");
    exit(1);
  }
  //通过Dos头找到pe头
  pPeHead=(IMAGE_NT_HEADERS *)(pBasePoint+pDosHead->e_lfanew);
  //判断pe头
  if(IMAGE_NT_SIGNATURE!=pPeHead->Signature)
  {
    printf("PE文件头错误!/n");
    exit(1);
  }
  //列出pe filehead的信息
  printf("运行平台:/t");
  if(IMAGE_FILE_MACHINE_I386==pPeHead->FileHeader.Machine)
    printf("%s/n","X86CPU");
  else
    printf("未知(%X)/n",pPeHead->FileHeader.Machine);
  printf("节数目:/t%d/n",pPeHead->FileHeader.NumberOfSections);
  printf("创建时间:/t%X/n",pPeHead->FileHeader.TimeDateStamp);
  printf("PointerToSymbolTable:/t%X/n",pPeHead->FileHeader.PointerToSymbolTable);
  printf("NumberOfSymbols:/t%X/n",pPeHead->FileHeader.NumberOfSymbols);
  printf("SizeOfOptionalHeader:/t%X/n",pPeHead->FileHeader.SizeOfOptionalHeader);
  printf("Characteristics:/t%X/n",pPeHead->FileHeader.Characteristics);
  //列出Optional Header信息
  printf("进入点:/t%x/n",pPeHead->OptionalHeader.AddressOfEntryPoint);
  printf("载入地址:/t%x/n",pPeHead->OptionalHeader.ImageBase);
  printf("内存对齐:/t%x/n",pPeHead->OptionalHeader.SectionAlignment);
  printf("文件对齐:/t%x/n",pPeHead->OptionalHeader.FileAlignment);
  printf("MajorSubsystemVersion:/t%x/n",pPeHead->OptionalHeader.MajorSubsystemVersion);
  printf("MinorSubsystemVersion:/t%x/n",pPeHead->OptionalHeader.MinorSubsystemVersion);
  printf("映像大小:/t%x/n",pPeHead->OptionalHeader.SizeOfImage);
  printf("头大小:/t%x/n",pPeHead->OptionalHeader.SizeOfHeaders);
  printf("界面:/t%x/n",pPeHead->OptionalHeader.Subsystem);
  //DataDirectory
  //Section Table
  //fseet应该不用定位了吧
  for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++)
  {
    int j;
    pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead);
    printf("/n节名称:/t");
    for(j=0;j<sizeof pSectionHead->Name;j++)
    {
      if(0==pSectionHead->Name[j])
        break;
      putchar(pSectionHead->Name[j]);
    }
    printf("/n本节的RVA:/t%X/n",pSectionHead->VirtualAddress);
    printf("映射尺寸:/t%X/n",pSectionHead->SizeOfRawData);
    printf("文件数据偏移:/t%X/n",pSectionHead->PointerToRawData);
    printf("节属性:/t%X/n",pSectionHead->Characteristics);
  }
#define addr(rva) (void *)((char *)((char *)pBasePoint+pSectionHead->PointerToRawData)+((DWORD)(rva)-pSectionHead->VirtualAddress))
  //导入表//遍历节表查找导入表的位置
  for(i=0;i<pPeHead->FileHeader.NumberOfSections;i++)
  {
    IMAGE_DATA_DIRECTORY *pData=&pPeHead->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    pSectionHead=(IMAGE_SECTION_HEADER *)((char *)pPeHead+sizeof *pPeHead+i*sizeof *pSectionHead);
   //查看导入表是否在该节内
    if(pData->VirtualAddress>=pSectionHead->VirtualAddress
      &&pData->VirtualAddress+pData->Size<=pSectionHead->VirtualAddress+pSectionHead->SizeOfRawData)
    {
      //定位地址
      IMAGE_IMPORT_DESCRIPTOR *pImport=addr(pData->VirtualAddress);
      while(pImport->Name)
      {
        IMAGE_THUNK_DATA *imThunk_data=addr(pImport->Characteristics);
        //输出模块名称
        printf("/n导入模块:%s/n/n",(char *)addr(pImport->Name));
        //输出引入函数表
        while(imThunk_data->u1 .Ordinal)
        {
          if(IMAGE_SNAP_BY_ORDINAL(imThunk_data->u1.Ordinal))
          {
            printf("/t导入ID:/t%d/n",IMAGE_ORDINAL(imThunk_data->u1 .Ordinal ));
          }
          else
          {
            IMAGE_IMPORT_BY_NAME *imImport_Name=(IMAGE_IMPORT_BY_NAME *) addr(imThunk_data->u1.AddressOfData);
            printf("/t导入函数:/t%s/n",(char *)imImport_Name->Name);
          }
          imThunk_data++;
        }//*/
        pImport++;
      }
      break;
    }
  }
  //导出表//和导入标实现方法类似
  CloseHandle(hFile);
  CloseHandle(hMapping);

  return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值