• 取PE文件的引入表和导出表


    直接上代码(这里列出C++和Delphi的代码),Delphi代码中包含导入及导出文件和函数列表,PE结构可参阅资料,很多很详细,需要注意的是,本例中是映射到内存,不是通过PE装载器装入的,所以对于节的RVA地址需要转换成为文件偏移地址。

    Delphi代码

    [delphi] view plaincopy
     
    1. unit Unit1;  
    2.   
    3. interface  
    4.   
    5. uses  
    6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
    7.   Dialogs, StdCtrls, ComCtrls;  
    8.   
    9. type  
    10.   //导入表元素结构  
    11.   TImageImportDiscriptor = packed record  
    12.     OriginalFirstThunk: DWORD;  
    13.     DataTimpStamp: DWORD;  
    14.     ForwardChain: DWORD;  
    15.     DLLName: DWORD;  
    16.     FirstThunk: DWORD;  
    17.   end;  
    18.   PImageImportDiscriptor = ^TImageImportDiscriptor;  
    19.   //导出表元素结构  
    20.   PImageExportDirectory = ^TImageExportDirectory;  
    21.   TImageExportDirectory = packed record  
    22.     Characteristics: DWORD;  
    23.     TimeDateStamp: DWORD;  
    24.     MajorVersion: WORD;  
    25.     MinorVersion: WORD;  
    26.     Name: DWORD;  
    27.     Base: DWORD;  
    28.     NumberOfFunctions: DWORD;  
    29.     NumberOfNames: DWORD;  
    30.     AddressOfFunctions: DWORD;  
    31.     AddressOfNames: DWORD;  
    32.     AddressOfNameOrdinals: DWORD;  
    33.   end;  
    34.   //函数名结构  
    35.   TImportByName = packed record  
    36.     proHint: Word;  
    37.     proName: array [0..1] of char;  
    38.   end;  
    39.   PImportByName = ^TImportByName;  
    40.     
    41.   TForm1 = class(TForm)  
    42.     OpenDialog1: TOpenDialog;  
    43.     Button1: TButton;  
    44.     TreeView1: TTreeView;  
    45.     Label1: TLabel;  
    46.     procedure Button1Click(Sender: TObject);  
    47.   private  
    48.     { Private declarations }  
    49.     procedure GetList(filename:string);  
    50.     {导入列表}  
    51.     procedure GetImportList(pBaseAddress:Pointer;ntHeader:PImageNtHeaders);  
    52.     {导出列表}  
    53.     procedure GetExportList(pBaseAddress:Pointer;ntHeader:PImageNtHeaders);  
    54.   public  
    55.     { Public declarations }  
    56.   end;  
    57.   
    58. var  
    59.   Form1: TForm1;  
    60.   
    61. implementation  
    62.   
    63. {$R *.dfm}  
    64.   
    65. { TForm1 }  
    66.   
    67. procedure TForm1.GetList(filename: string);  
    68. var  
    69.   fileHandle:THandle;  
    70.   fileMap:THandle;  
    71.   pBaseAddress:Pointer;  
    72.   dosHeader: PImageDosHeader;  
    73.   ntHeader: PImageNtHeaders;  
    74. begin  
    75.   TreeView1.Items.Clear;  
    76.   try  
    77.     //打开文件  
    78.     fileHandle := CreateFile(PChar(filename),GENERIC_READ,FILE_SHARE_READ,nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);  
    79.     if fileHandle = INVALID_HANDLE_VALUE then  
    80.     begin  
    81.       ShowMessage('文件打开失败!');  
    82.       Exit;  
    83.     end;  
    84.     //创建内存映射  
    85.     fileMap := CreateFileMapping(fileHandle,nil,PAGE_READONLY,0,0,nil);  
    86.     if fileMap = then  
    87.     begin  
    88.       ShowMessage('创建内存映射失败!');  
    89.       Exit;  
    90.     end;  
    91.     //映射到当前进程,pBaseAddress是基址  
    92.     pBaseAddress := MapViewOfFile(fileMap,FILE_MAP_READ,0,0,0);  
    93.     if pBaseAddress = nil then  
    94.     begin  
    95.       ShowMessage('获取地址失败!');  
    96.       Exit;  
    97.     end;  
    98.     //获取Dos信息头部结构数据  
    99.     dosHeader := pImageDosHeader(LongInt(pBaseAddress));  
    100.     //判断Dos标识  
    101.     if dosHeader.e_magic <> IMAGE_DOS_SIGNATURE then  
    102.     begin  
    103.       ShowMessage('不可识别的文件格式!');  
    104.       Exit;  
    105.     end;  
    106.     //获取NT信息头部结构数据,IsBadReadPtr判断指针是否可读,ntHeader.Signature是NT标识  
    107.     ntHeader := pImageNtHeaders(LongInt(pBaseAddress)+dosHeader._lfanew);  
    108.     if (IsBadReadPtr(ntHeader,SizeOf(TImageNtHeaders))) or  
    109.        (ntHeader.Signature <> IMAGE_NT_SIGNATURE) then  
    110.     begin  
    111.        ShowMessage('不是有效地Win32程序!');  
    112.        Exit;  
    113.     end;  
    114.     GetImportList(pBaseAddress,ntHeader);  
    115.     GetExportList(pBaseAddress,ntHeader);  
    116.   finally  
    117.     UnmapViewOfFile(pBaseAddress);  
    118.     CloseHandle(fileMap);  
    119.     CloseHandle(fileHandle);  
    120.   end;  
    121. end;  
    122.   
    123. procedure TForm1.Button1Click(Sender: TObject);  
    124. begin  
    125.   if OpenDialog1.Execute then  
    126.   begin  
    127.     Label1.Caption := '以下是'+OpenDialog1.FileName+'的导入及导出表';  
    128.     GetList(OpenDialog1.FileName);  
    129.   end;  
    130. end;  
    131.   
    132.   
    133. procedure TForm1.GetExportList(pBaseAddress: Pointer; ntHeader: PImageNtHeaders);  
    134. var  
    135.   imageEntry: PImageExportDirectory;  
    136.   sectionHeader: PImageSectionHeader;  
    137.   importbyname: PImportByName;  
    138.   proEntry:PDWORD;  
    139.   proTemp:PWORD;  
    140.   rva,frva: DWORD;  
    141.   dllname: string;  
    142.   i,j:integer;  
    143.   node:TTreeNode;  
    144.   s:string;  
    145.   pname:PChar;  
    146. begin  
    147.   rva := ntHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;  
    148.   if rva = then Exit;  
    149.   //定位到第一个节的地址  
    150.   sectionHeader := PImageSectionHeader(LongInt(ntHeader)+SizeOf(TImageNtHeaders));  
    151.   //ntHeader^.FileHeader.NumberOfSections为节的数量,此处循环,找到引入表的节  
    152.   for i := to ntHeader^.FileHeader.NumberOfSections - do  
    153.   begin  
    154.     //IMAGE_DIRECTORY_ENTRY_IMPORT,引入表,检查rva是否落在节内  
    155.     if ( rva >= LongInt(sectionHeader.VirtualAddress)) and (rva<LongInt(sectionHeader.VirtualAddress+sectionHeader.Misc.VirtualSize)) then  
    156.     begin  
    157.       Break;  
    158.     end;  
    159.     //没找到,那么增加SizeOf(TImageSectionHeader)字节数,指向下一个节  
    160.     Inc(sectionHeader);  
    161.   end;  
    162.   node := TreeView1.Items.Add(nil,'导出函数表');  
    163.   frva := sectionHeader.VirtualAddress - sectionHeader.PointerToRawData;  
    164.   //导出表入口  
    165.   imageEntry := PImageExportDirectory(LongInt(pBaseAddress)+rva-frva);  
    166.   proEntry := PDWord(LongInt(pBaseAddress)+imageEntry.AddressOfFunctions-frva);  
    167.   pname := PChar(LongInt(pBaseAddress)+imageEntry.Name-frva);  
    168.   for i := to imageEntry.NumberOfFunctions - do  
    169.   begin  
    170.     if proEntry^ = then Continue;  
    171.     proTemp := PWORD(LongInt(pBaseAddress)+LongInt(imageEntry.AddressOfNameOrdinals)-frva);  
    172.     for j := to imageEntry.NumberOfNames -  do  
    173.     begin  
    174.       if proTemp^ = i then  
    175.       begin  
    176.         s := '';  
    177.         while True do  
    178.         begin  
    179.           if pname^=#then Break;  
    180.           Inc(pname);  
    181.         end;  
    182.         while True do  
    183.         begin  
    184.           if (pname-1)^=#then  
    185.           begin  
    186.             s:=Format('%s', [pname]);  
    187.             Break;  
    188.           end;  
    189.           Inc(pname);  
    190.         end;  
    191.       end;  
    192.       Inc(proTemp);  
    193.     end;  
    194.     TreeView1.Items.AddChild(node,s);  
    195.     Inc(proEntry);  
    196.   end;  
    197. end;  
    198.   
    199. procedure TForm1.GetImportList(pBaseAddress: Pointer; ntHeader: PImageNtHeaders);  
    200. var  
    201.   imageEntry: PImageImportDiscriptor;  
    202.   sectionHeader: PImageSectionHeader;  
    203.   importbyname: PImportByName;  
    204.   proEntry:PDWORD;  
    205.   rva,frva: DWORD;  
    206.   dllname: string;  
    207.   i:integer;  
    208.   node:TTreeNode;  
    209. begin  
    210.   rva := ntHeader.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;  
    211.   if rva = then Exit;  
    212.   //定位到第一个节的地址  
    213.   sectionHeader := PImageSectionHeader(LongInt(ntHeader)+SizeOf(TImageNtHeaders));  
    214.   //ntHeader^.FileHeader.NumberOfSections为节的数量,此处循环,找到引入表的节  
    215.   for i := to ntHeader^.FileHeader.NumberOfSections - do  
    216.   begin  
    217.     //IMAGE_DIRECTORY_ENTRY_IMPORT,引入表,检查rva是否落在节内  
    218.     if ( rva >= LongInt(sectionHeader.VirtualAddress)) and (rva<LongInt(sectionHeader.VirtualAddress+sectionHeader.Misc.VirtualSize)) then  
    219.     begin  
    220.       Break;  
    221.     end;  
    222.     //没找到,那么增加SizeOf(TImageSectionHeader)字节数,指向下一个节  
    223.     Inc(sectionHeader);  
    224.   end;  
    225.   frva := sectionHeader.VirtualAddress - sectionHeader.PointerToRawData;  
    226.   TreeView1.Items.Add(nil,'导入函数表');  
    227.   //引入表入口  
    228.   imageEntry := PImageImportDiscriptor(LongInt(pBaseAddress)+rva-frva);  
    229.   //加载的DLL的名称,这里是RVA地址,需要转换成文件偏移地址,因为我们不是通过PE加载器加载,而是映射到内存  
    230.   while imageEntry.DLLName <> do  
    231.   begin  
    232.     dllname := PChar(LongInt(pBaseAddress)+imageEntry.DLLName-frva);  
    233.     node := TreeView1.Items.AddChild(TreeView1.Items[0],dllname);  
    234.     if imageEntry.OriginalFirstThunk <> then  
    235.       proEntry := PDWord(LongInt(pBaseAddress)+imageEntry.OriginalFirstThunk-frva)  
    236.     else  
    237.       proEntry := PDWord(LongInt(pBaseAddress)+imageEntry.FirstThunk-frva);  
    238.     while proEntry^ <> do  
    239.     begin  
    240.       if (proEntry^ and $80000000) <> then  
    241.         TreeView1.Items.AddChild(node,Format('函数编号:%-15d',[proEntry^ and $7FFFFFFF]))  
    242.       else  
    243.       begin  
    244.         importbyname := PImportByName(LongInt(pBaseAddress)+proEntry^-frva);  
    245.         TreeView1.Items.AddChild(node,Format('函数名称:%-15s',[importbyname.proName]));  
    246.       end;  
    247.       Inc(proEntry);  
    248.     end;  
    249.     //继续读取  
    250.     Inc(imageEntry);  
    251.   end;  
    252. end;  
    253.   
    254. end.  

    C++代码

    [cpp] view plaincopy
     
    1. #include<string>  
    2. #include<windows.h>  
    3.   
    4.   
    5. void GetImportDllList(void)  
    6. {  
    7.     IMAGE_IMPORT_DESCRIPTOR* importEntry = 0;  
    8.     IMAGE_SECTION_HEADER* sectionHeader = 0;  
    9.     char* filename = "c://test.exe";  
    10.     //打开文件  
    11.     HANDLE hfile = CreateFileA(filename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);  
    12.     if (hfile == INVALID_HANDLE_VALUE)  
    13.     {  
    14.         printf("%s","文件打开失败!");  
    15.         return;  
    16.     }  
    17.     //创建内存映射  
    18.     HANDLE hmap = CreateFileMapping(hfile,NULL,PAGE_READONLY,0,0,NULL);  
    19.     if (hmap == 0)  
    20.     {  
    21.         printf("%s","创建内存映射失败!");  
    22.         return;  
    23.     }  
    24.     //映射到当前进程,pBaseAddress是基址  
    25.     HANDLE pBaseAddress = MapViewOfFile(hmap,FILE_MAP_READ,0,0,0);  
    26.     if (!pBaseAddress)  
    27.     {  
    28.         printf("%s","获取地址失败!");  
    29.         return;  
    30.     }  
    31.     //获取Dos信息头部结构数据  
    32.     IMAGE_DOS_HEADER* dosHeader = (IMAGE_DOS_HEADER*)pBaseAddress;  
    33.     //判断Dos标识  
    34.     if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)  
    35.     {  
    36.         printf("%s","不可识别的文件格式!");  
    37.         return;  
    38.     }  
    39.     //获取NT信息头部结构数据,IsBadReadPtr判断指针是否可读,ntHeader->Signature是NT标识  
    40.     IMAGE_NT_HEADERS* ntHeader = (IMAGE_NT_HEADERS*)((DWORD)pBaseAddress+dosHeader->e_lfanew);  
    41.     if (ntHeader->Signature != IMAGE_NT_SIGNATURE)  
    42.     {  
    43.         printf("%s","不是有效地Win32程序!");  
    44.         return;  
    45.     }  
    46.     //定位到第一个节的地址  
    47.     sectionHeader = (IMAGE_SECTION_HEADER*)((DWORD)ntHeader+sizeof(IMAGE_NT_HEADERS));  
    48.     //ntHeader->FileHeader.NumberOfSections为节的数量,此处循环,找到引入表的节  
    49.     for (int i=0;i<ntHeader->FileHeader.NumberOfSections;i++)  
    50.     {  
    51.         //IMAGE_DIRECTORY_ENTRY_IMPORT,引入表  
    52.         if (sectionHeader->VirtualAddress == ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)  
    53.         {  
    54.             break;  
    55.         }  
    56.         //没找到,那么增加SizeOf(IMAGE_SECTION_HEADER)字节数,指向下一个节  
    57.         sectionHeader++;  
    58.     }  
    59.     //引入表入口  
    60.     importEntry = (IMAGE_IMPORT_DESCRIPTOR*)((DWORD)pBaseAddress+sectionHeader->PointerToRawData);  
    61.     printf("下面是%s的引入文件/n",filename);  
    62.     //加载的DLL的名称,这里是RVA地址,需要转换成文件偏移地址,因为我们不是通过PE加载器加载,而是映射到内存  
    63.     while (importEntry->Name != 0)  
    64.     {  
    65.         DWORD offset = (DWORD)pBaseAddress+importEntry->Name-(sectionHeader->VirtualAddress - sectionHeader->PointerToRawData);  
    66.         char* s = (char*)offset;  
    67.         printf("%s/n",s);  
    68.         //继续读取  
    69.         importEntry++;  
    70.     }  
    71.     UnmapViewOfFile(pBaseAddress);  
    72.     CloseHandle(hmap);  
    73.     CloseHandle(hfile);  
    74. }  
    75.   
    76. int main()  
    77. {   
    78.     GetImportDllList();  
    79.     return 0;  
    80. }  

    http://blog.csdn.net/bdmh/article/details/6100745

  • 相关阅读:
    HDU Number Sequence
    HDU Wolf and Rabbit
    HDU Fire Net
    C# QQ weather
    Jquery 随窗口改变大小不会影响浏览位置,DIV可以在绝对的位置不变.菜单相对位置不变
    C# 验证中国电话号码,电子邮件,网址,身份证号码等等
    C# Image Download
    Csharp 两个DataTable或DataView互换,可以用来加密解密
    C# Windows Forms TreeView SelectedNode(VS2008)
    C# 获取源代码
  • 原文地址:https://www.cnblogs.com/findumars/p/5001973.html
Copyright © 2020-2023  润新知