PE import function

本文介绍了一个C++程序如何解析PE文件格式的导入表,通过使用Windows API和直接操作内存映射文件来读取并解析PE文件中的导入表信息。文章详细展示了如何定位到导入表的位置,并遍历每个导入的DLL及其对应的API名称。

// cccc.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include"memory.h"
#include "windows.h"
#include <stdio.h>
#include <conio.h>
#include "Dbghelp.h"

PIMAGE_SECTION_HEADER ImageRVA2Section(PIMAGE_NT_HEADERS pimage_nt_headers,DWORD dwRVA)
{
 int i;
 PIMAGE_SECTION_HEADER pimage_section_header=(PIMAGE_SECTION_HEADER)((PCHAR(pimage_nt_headers)) + sizeof(IMAGE_NT_HEADERS));
 for(i=0;i<pimage_nt_headers->FileHeader.NumberOfSections;i++)
 {
  if((pimage_section_header->VirtualAddress) && (dwRVA<=(pimage_section_header->VirtualAddress+pimage_section_header->SizeOfRawData)))
  {
   return ((PIMAGE_SECTION_HEADER)pimage_section_header);
  }
  pimage_section_header++;
 }
 return(NULL);
}
DWORD RVA2Offset(PCHAR pImageBase,DWORD dwRVA)
{
 DWORD _offset;
 PIMAGE_SECTION_HEADER section;
 PIMAGE_DOS_HEADER pimage_dos_header;
 PIMAGE_NT_HEADERS pimage_nt_headers;
 pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase);
 pimage_nt_headers = (PIMAGE_NT_HEADERS)(pImageBase+pimage_dos_header->e_lfanew);
 section=ImageRVA2Section(pimage_nt_headers,dwRVA);
 if(section==NULL)
 {
  return(0);
 }
 _offset=dwRVA+section->PointerToRawData-section->VirtualAddress;
 return(_offset);
}

 


int func(int x)
{
    int countx = 0;
    while(x)
    {
          countx ++;
          x = x&(x-1);
    }
    return countx;
}
int _tmain(int argc, _TCHAR* argv[])
{
// LoadLibrary(_T("Dbghelp.dll"));
 DWORD dwFsize   = 0;
 PIMAGE_NT_HEADERS  nt_header;//=new IMAGE_NT_HEADERS;
 HANDLE hFile;
 HANDLE hMapFile;
 PCHAR pImageBase;
 hFile=CreateFile(_T("1.exe"),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);
 if (hFile == INVALID_HANDLE_VALUE)
 {
  printf("Could not open file (error %d)/n", GetLastError());
  return 0;
 }
 hMapFile = CreateFileMapping(
                 hFile,    // use paging file
                 NULL,                    // default security
                 PAGE_READWRITE,          // read/write access
                 0,                       // max. object size
                 dwFsize,                // buffer size 
                 _T("Test"));                 // name of mapping object
 if (hMapFile == NULL || hMapFile == INVALID_HANDLE_VALUE)
   {
      printf("Could not create file mapping object (%d)./n",
             GetLastError());
      return 0;
   }
 dwFsize=GetFileSize(hFile,0);
 pImageBase=(PCHAR)MapViewOfFile(hMapFile,   // handle to map object
                        FILE_MAP_ALL_ACCESS, // read/write permission
                        0,                  
                        0,                  
                        dwFsize); 
 if (pImageBase == NULL)
    {
      printf("Could not map view of file (%d)./n",
             GetLastError());
      return 0;
    }
 nt_header=ImageNtHeader(pImageBase);

 DWORD it_voffset = nt_header->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
 PIMAGE_DOS_HEADER pimage_dos_header = PIMAGE_DOS_HEADER(pImageBase);
 PIMAGE_NT_HEADERS pimage_nt_headers = PIMAGE_NT_HEADERS(pImageBase + pimage_dos_header->e_lfanew);
  it_voffset = pimage_nt_headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
 

  DWORD dwImportDirectory=RVA2Offset(pImageBase, pimage_nt_headers->OptionalHeader.
          DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

  PIMAGE_IMPORT_DESCRIPTOR pimage_import_descriptor= (PIMAGE_IMPORT_DESCRIPTOR)(pImageBase+dwImportDirectory);

 PCHAR pThunk;
 PCHAR pHintName;
 DWORD dwAPIaddress;
 PCHAR pDllName;
 PCHAR pAPIName;
 while(pimage_import_descriptor->Name!=0)
 {
  pThunk= pImageBase+pimage_import_descriptor->FirstThunk;
  pHintName= pImageBase;
  if(pimage_import_descriptor->OriginalFirstThunk!=0)
  {
   pHintName+= RVA2Offset(pImageBase, pimage_import_descriptor->OriginalFirstThunk);
  }
  else
  {
   pHintName+= RVA2Offset(pImageBase, pimage_import_descriptor->FirstThunk);
  }
  pDllName= pImageBase + RVA2Offset(pImageBase, pimage_import_descriptor->Name);
  printf(" DLL Name: %s/r/n First Thunk: 0x%x/r/n", pDllName,
  pimage_import_descriptor->FirstThunk);
  PIMAGE_THUNK_DATA pimage_thunk_data= (PIMAGE_THUNK_DATA) pHintName;
  while(pimage_thunk_data->u1.AddressOfData!=0)
  {
   dwAPIaddress= pimage_thunk_data->u1.AddressOfData;
   if((dwAPIaddress&0x80000000)==0x80000000)
   {
    dwAPIaddress&= 0x7FFFFFFF;
    printf("  Proccess: 0x%x/r/n", dwAPIaddress);

   }
   else
   {
    pAPIName= pImageBase+RVA2Offset(pImageBase, dwAPIaddress)+2;
    printf("  Proccess: %s/r/n", pAPIName);
    if (strcmp(pAPIName,"MessageBoxW")==0)
    {
     MessageBox(NULL,_T("get name"),0,0);
    }
   }
   pThunk+= 4;
   pHintName+= 4;
   pimage_thunk_data++;
  }
  pimage_import_descriptor++;
 }

 UnmapViewOfFile(pImageBase);

 

 getchar();
 func(0xfffff);
 return 0;
}
 

在计算机领域,PE 通常指的是 **Portable Executable(可移植可执行文件)** 格式。这是由微软为 Windows 操作系统开发的一种文件格式,用于可执行文件(如 `.exe`)、动态链接库(如 `.dll`)、驱动程序(如 `.sys`)等二进制文件的存储和加载。 ### PE 文件结构的作用 PE 文件格式为 Windows 系统下的程序提供了标准的加载和执行机制。它包含多个关键结构,例如: - **DOS 头部**:用于兼容 MS-DOS 的小型引导程序。 - **PE 文件签名**:标识该文件为 PE 格式。 - **文件头(File Header)**:描述文件的基本属性,如目标平台、节的数量等。 - **可选头(Optional Header)**:包含程序加载时所需的信息,如入口地址、代码段地址、数据段地址等。 - **节表(Section Table)**:描述每个节(如 `.text`、`.data`、`.rsrc`)的属性和偏移。 - **导入表(Import Table)**:列出程序运行时依赖的外部函数和 DLL。 - **导出表(Export Table)**:列出该文件提供给其他模块调用的函数。 - **资源(Resources)**:如图标、字符串、对话框模板等。 这些结构为逆向工程、恶意软件分析、程序调试和安全检测提供了关键信息[^1]。 ### PE 文件在安全分析中的应用 PE 文件格式为恶意软件的检测和分析提供了结构化依据: - **静态分析**:通过解析 PE 文件的头部信息、导入表、节表等,可以识别潜在的恶意行为特征。例如,某些恶意软件会使用特定的节名(如 `.malcode`)或隐藏导入函数以逃避检测。 - **动态分析**:加载 PE 文件并监控其行为,如 API 调用序列、内存分配模式、网络连接等。 - **行为检测**:结合控制流图(CFG)、抽象语法树(AST)以及特征向量,可以识别未知恶意软件家族。 - **YARA 规则匹配**:通过匹配 PE 文件中的节名、导入函数、魔数等特征,识别已知的恶意软件样本[^1]。 ### 示例:PE 文件结构解析 以下是一个简单的 Python 示例,使用 `pefile` 库解析 PE 文件的导入表信息: ```python import pefile # 加载 PE 文件 pe = pefile.PE("example.exe") # 遍历导入表 for entry in pe.DIRECTORY_ENTRY_IMPORT: print(f"Imported DLL: {entry.dll.decode('utf-8')}") for func in entry.imports: print(f" Function: {func.name.decode('utf-8')} (RVA: 0x{func.address:08X})") ``` 该代码输出 PE 文件中导入的 DLL 及其函数名称和地址,适用于静态分析流程。 ### PE 在其他上下文中的含义 虽然 PE 在计算机领域最常指 **Portable Executable**,但在其他语境中也可能有不同的含义,例如: - 在教育领域,PE 可能指 **Physical Education(体育)**,如“PE teacher”表示“体育老师”[^2]。 - 在自然语言处理领域,PE 可能是 **Pre-trained Embedding** 或 **Positional Encoding** 的缩写,用于表示词的位置信息,如 Transformer 模型中的位置编码。 不过,在计算机安全和逆向工程领域,PE 几乎无一例外地指 **Portable Executable** 格式。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值