PE的导入表与导出表,自己看吧<br><br>unit UPEEntry;<br><br>interface<br><br>uses<br> Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,<br> StdCtrls, Buttons, Menus;<br><br>type<br> {PE导出表声明}<br> PImageExportDirectory = ^TImageExportDirectory;<br> TImageExportDirectory = packed record<br> Characteristics: DWORD;<br> TimeDateStamp: DWORD;<br> MajorVersion: WORD;<br> MinorVersion: WORD;<br> Name: DWORD;<br> Base: DWORD;<br> NumberOfFunctions: DWORD;<br> NumberOfNames: DWORD;<br> AddressOfFunctions: DWORD;<br> AddressOfNames: DWORD;<br> AddressOfNameOrdinals: DWORD;<br> end;<br><br> PImportByName=^TImportByName;<br> TImportByName =Packed record<br> ProcedureHint: word;<br> ProcedureName: array[0..1]of char;<br> end;<br><br> PImageImportDescriptor = ^TImageImportDescriptor;<br> TImageImportDescriptor = packed record<br> OriginalFirstThunk: DWord;<br> TimeDateStamp : DWord;<br> ForwarderChain : DWord;<br> DLLName : DWord;<br> FirstThunk : DWord;<br> end;<br><br> PImageThunkData=^TImageThunkData;<br> TImageThunkData = record<br> case integer of<br> 1
ForwarderString : DWord; );<br> 2
Function_ : DWord; );<br> 3
Ordinal : DWord; );<br> 4
AddressOfData : DWord; );<br> end;<br> PImageBaseRelocation=^TImageBaseRelocation;<br> TImageBaseRelocation=Packed Record<br> VirtualAddress: Dword;<br> SizeOfBlock: Dword;<br> TypeOffset: array[0..1] of Word; //不定长<br> end;<br><br> TPESection = record //自定义<br> ObjectName: string;<br> Address: PChar;<br> PhysicalSize: Integer;<br>// VirtualSize: Integer;<br>// Characteristics: Cardinal;<br> PointerToRawData: Integer;<br> end;<br><br> TNameOrID = (niName, niID); <br> TPEImport = record<br> NameOrID: TNameOrID;<br> Name: string;<br> ID: Integer;<br>// PAddress: PChar; {指向导入表函数用于执行此函数}<br> end;<br> TPEImports = record {记录一个Dll文件所调用的函数个数}<br> DLLName: string;<br> Entries: array of TPEImport; {函数数据}<br> end;<br><br> TPEExport = record<br> Name: string;<br> RelativeID: Integer;<br> ID: Integer;<br> Address: DWORD;{相对地址}<br> end;<br><br> TfrmPEEntry = class(TForm)<br> GroupBox1: TGroupBox;<br> ListBox1: TListBox;<br> GroupBox2: TGroupBox;<br> ListBox2: TListBox;<br> GroupBox3: TGroupBox;<br> BitBtn2: TBitBtn;<br> procedure BitBtn2Click(Sender: TObject);<br> private<br> { Private declarations }<br> public<br> { Public declarations }<br> PEImports: array of TPEImports;<br> PEExport: array of TPEExport;<br> Section: array of TPESection;<br> procedure Load(FileName:string);<br> end;<br><br>var<br> frmPEEntry: TfrmPEEntry;<br><br>implementation<br><br>uses UMain;<br><br>{$R *.DFM}<br><br>procedure TfrmPEEntry.Load(FileName:string);<br>type<br> TImageSectionHeaderArray=array[0..1]of TImageSectionHeader;<br> PImageSectionHeaderArray=^TImageSectionHeaderArray;<br>var<br> FileStream: TFileStream;<br> ImageDosHeader:TImageDosHeader;<br> ImageNtHeaders:TImageNtHeaders;<br> ImageBase: PChar;<br> FileBase: PChar;<br> ImageSize: Integer;<br> HeaderSize: Integer;<br> NTHeader: PImageNtHeaders;<br> I,J: integer;<br> ImportEntry: PImageImportDescriptor;<br> LookupEntry: PDWord;<br> ImportByName: PImportByName;<br> SectionTable
ImageSectionHeaderArray;<br><br> ExportEntry: PImageExportDirectory;<br> AddressOfFunctions: PChar;<br> AddressOfNames: PChar;<br> AddressOfNameOrdinals: PChar;<br> Found:boolean;<br>begin<br> ListBox1.Clear;<br> ListBox2.clear;<br> for I := 0 to High(PEImports) do<br> SetLength(PEImports
.Entries, 0);<br> SetLength(PEImports,0);<br> FileStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);<br> with FileStream do<br> begin<br> ReadBuffer(ImageDosHeader,sizeof(TImageDosHeader));<br> {以下检验是否是合法的PE文件}<br> if ImageDosHeader.e_magic<>IMAGE_DOS_SIGNATURE then<br> begin<br> showmessage('未知的文件格式.');<br> FileStream.free;<br> exit;<br> end;<br> if ImageDosHeader._lfanew >= Size then<br> begin<br> showmessage('未知的文件格式.');<br> FileStream.free;<br> exit;<br> end;<br> Position := ImageDosHeader._lfanew;<br> ReadBuffer(ImageNtHeaders,sizeof(TImageNtHeaders));<br> {检验 NT Header.}<br> if ImageNtHeaders.Signature<>IMAGE_NT_SIGNATURE then<br> begin<br> showmessage('此文件不是WIN32 PE可执行文件.');<br> FileStream.free;<br> exit;<br> end;<br> ImageBase:=pointer(ImageNtHeaders.OptionalHeader.ImageBase);<br> ImageSize:=ImageNtHeaders.OptionalHeader.SizeOfImage;<br> HeaderSize:=ImageNtHeaders.OptionalHeader.SizeOfHeaders;<br> {在ImageBaseAdress中分配内存}<br> FileBase := VirtualAlloc(ImageBase, ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);<br> {返回映射后的基地址}<br> if FileBase = nil then<br> begin<br> {由系统自动分配内存页}<br> FileBase := VirtualAlloc(nil, ImageSize, MEM_RESERVE or MEM_COMMIT, PAGE_READWRITE);<br> if FileBase = nil then<br> begin<br> showmessage('不能分配内存');<br> FileStream.free;<br> exit;<br> end;<br> end;<br> Position := 0;<br> ReadBuffer(PPointer(FileBase)^, HeaderSize); {读取数据到文件头中}<br> {把文件指针定位到NtHeader}<br> NTHeader := PImageNtHeaders(FileBase + PImageDosHeader(FileBase)^._lfanew);<br> {保存栈}<br>// StackCommitSize := NTHeader^.OptionalHeader.SizeOfStackCommit;<br> {保存保留栈}<br>// StackReserveSize := NTHeader^.OptionalHeader.SizeOfStackReserve;<br> {保存切入点}<br>// EntryPoint := FileBase + NTHeader^.OptionalHeader.AddressOfEntryPoint;<br> {保存代码大小}<br>// CodeSize := NTHeader^.OptionalHeader.SizeOfCode;<br> {保存代码地址}<br>// Code := FileBase + NTHeader^.OptionalHeader.BaseOfCode;<br> {保存数据大小}<br>// DataSize := NTHeader^.OptionalHeader.SizeOfInitializedData;<br> {保存数据地址}<br>// Data := FileBase + NTHeader^.OptionalHeader.BaseOfData;<br> {从文件中读取信息并保存在变量中}<br> SetLength(Section, NTHeader^.FileHeader.NumberOfSections);<br> SectionTable:= PImageSectionHeaderArray(longword(NtHeader)+sizeof(TImageNtHeaders));<br> for I := 0 to High(Section) do<br> begin<br> SetLength(Section.ObjectName, 8);<br> Move(SectionTable^.Name, Section.ObjectName[1], 8);<br> SetLength(Section.ObjectName, StrLen(PChar(Section.ObjectName)));<br> Section.PhysicalSize := SectionTable^.SizeOfRawData;<br>// Section.VirtualSize := SectionTable^.Misc.VirtualSize;<br> Section.Address := FileBase + SectionTable^.VirtualAddress;<br> Section.PointerToRawData := SectionTable^.PointerToRawData;<br> Position := SectionTable^.PointerToRawData;<br> ReadBuffer(PPointer(Section.Address)^, Section.PhysicalSize);<br>// Section.Characteristics := SectionTable^.Characteristics;<br> end;<br> if NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress<>0 then<br> begin<br> ImportEntry := PImageImportDescriptor(FileBase +<br> NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);<br> {读取导入表入口,直到空为止}<br> while ImportEntry^.DLLName <> 0 do<br> begin<br> {新导入表入口}<br> SetLength(PEImports, Length(PEImports) + 1);<br> PEImports[High(PEImports)].DLLName := FileBase + ImportEntry^.DLLName;<br> if ImportEntry^.OriginalFirstThunk<>0 then<br> LookupEntry := PDWord(FileBase + ImportEntry^.OriginalFirstThunk)<br> else LookupEntry := PDWord(FileBase + ImportEntry^.FirstThunk);<br> {继续读取此Dll直到为空}<br> while LookupEntry^ <> 0 do<br> begin<br> {函数入口}<br> SetLength(PEImports[High(PEImports)].Entries, Length(PEImports[High(PEImports)].Entries) + 1);<br> with PEImports[High(PEImports)].Entries[High(PEImports[High(PEImports)].Entries)] do<br> begin<br> if (LookupEntry^ and $80000000) <> 0 then<br> begin<br> NameOrID := niID;<br> ID := LookupEntry^ and $7FFFFFFF; {为ID,屏蔽最高位}<br> frmPEEntry.listbox1.items.add(format('函数编号:%-34d 来自的DLL:%-28s 地址:%.8X',[id,PEImports[High(PEImports)].DllName, LookupEntry^]));<br> end<br> else<br> begin<br> NameOrID := niName;<br> ImportByName:=PImportByName(FileBase + LookupEntry^);<br> Name := ImportByName^.ProcedureName; {头两个字节存储ID,其后紧跟为名字}<br> frmPEEntry.listbox1.items.add(format('函数名:%-36s 来自的DLL:%-18s Hint:%.4X 地址:%.8X',[ImportByName^.ProcedureName, PEImports[High(PEImports)].DllName, ImportByName^.ProcedureHint, LookupEntry^]));<br> end;<br>// PAddress := PChar(LookupEntry);<br> end;<br> Inc(LookupEntry);<br> end; //end with<br> Inc(ImportEntry);<br> end; //end while<br> end;<br><br> if NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress <> 0 then<br> begin<br> ExportEntry := PImageExportDirectory(FileBase +<br> NTHeader^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);<br> {ExportEntry指向导出表的位置}<br> AddressOfNames := FileBase + ExportEntry^.AddressOfNames;<br> AddressOfNameOrdinals := FileBase + ExportEntry^.AddressOfNameOrdinals;<br> AddressOfFunctions := FileBase + ExportEntry^.AddressOfFunctions;<br><br> {导出的函数的个数}<br> setlength(PEExport,ExportEntry^.NumberOfFunctions);<br>// FillChar(FList^, FCount * SizeOf(TpeExport), 0);<br> for I := 0 to ExportEntry^.NumberOfNames - 1 do {以名字导出的函数的个数}<br> begin<br> {保存导出地址}<br> PEExport.Name := FileBase + PDWord(AddressOfNames + I * 4)^;<br> {以ID来查找的导出函数}<br> PEExport.RelativeID := PWord(AddressOfNameOrdinals + I * 2)^ ;<br> PEExport.ID := PEExport.RelativeID + integer(ExportEntry^.Base-1);<br> {函数所处一地址}<br> PEExport.Address := PDword(AddressOfFunctions + PEExport.RelativeID * 4)^; //相对地址,+FileBase=绝对地址<br> listbox2.items.add(format('函数名:%-36s 编号:%.5d 地址:%.8X',[PEExport.name,PEExport.ID ,Dword(PEExport.address)]));<br> end;<br><br> for I := 0 to ExportEntry^.NumberOfFunctions - 1 do {搜索以编号导出的函数}<br> begin<br> Found:=false;<br> for J := 0 to ExportEntry^.NumberOfNames - 1 do<br> begin<br> if I=PEExport[J].RelativeID then //if I+(Base-1)=PEExport[J].ID then<br> begin<br> Found:=true;<br> break;<br> end;<br> end;<br> if not Found then<br> begin<br> PEExport.Name := '';<br> PEExport.RelativeID := I;<br> PEExport.ID := PEExport.RelativeID + integer(ExportEntry^.Base-1);<br> PEExport.Address := PDword(AddressOfFunctions + PEExport.ID * 4)^; //相对地址,+FileBase=绝对地址<br> listbox2.items.add(format('函数名:%-36s 编号:%.5d 地址:%.8X',['',PEExport.ID-integer(ExportEntry^.Base-1) ,Dword(PEExport.address)]));<br> end;<br> end;<br> end;<br> end;<br> VirtualFree(FileBase, 0, MEM_RELEASE);<br> FileStream.free;<br>end;<br><br>procedure TfrmPEEntry.BitBtn2Click(Sender: TObject);<br>begin<br> close;<br>end;<br><br>end.