delphi で exeファイルのimport sectionを取得したいですが
どうやるのでしょうか?
APIがあるみたいですが自力でやりたいです。
http://bbs.wankuma.com/index.cgi?mode=al2&namber=46936&KLOG=79を
みましたが「VirtualAddress - PointerToRawData を データディクショナリの RVA から引いてやれば、ファイル上での位置がわかります」の部分がよくわかりません。
下記途中までのソース
program peExe;
{$APPTYPE CONSOLE}
uses
SysUtils,Classes,windows;
type
IMAGE_DOS_HEADER = record // DOS .EXE header
e_magic:word; // Magic number
e_cblp:word; // Bytes on last page of file
e_cp:word; // Pages in file
e_crlc:word; // Relocations
e_cparhdr:word; // Size of header in paragraphs
e_minalloc:word; // Minimum extra paragraphs needed
e_maxalloc:word; // Maximum extra paragraphs needed
e_ss:word; // Initial (relative) SS value
e_sp:word; // Initial SP value
e_csum:word; // Checksum
e_ip:word; // Initial IP value
e_cs:word; // Initial (relative) CS value
e_lfarlc:word; // File address of relocation table
e_ovno:word; // Overlay number
e_res:array [0..3] of word; // Reserved words
e_oemid:word; // OEM identifier (for e_oeminfo)
e_oeminfo:word; // OEM information; e_oemid specific
e_res2:array[0..9] of word; // Reserved words
e_lfanew:dword; // File address of new exe header
end;
IMAGE_FILE_HEADER = record
Machine:WORD;
NumberOfSections:WORD;
TimeDateStamp:DWORD;
PointerToSymbolTable:DWORD;
NumberOfSymbols:DWORD;
SizeOfOptionalHeader:WORD;
Characteristics:WORD;
end;
IMAGE_DATA_DIRECTORY = record
RVA:DWORD;
Size:DWORD;
end;
IMAGE_OPTIONAL_HEADER32 = record
//
// Standard fields.
//
Magic:word;
MajorLinkerVersion:BYTE;
MinorLinkerVersion:BYTE;
SizeOfCode:DWORD;
SizeOfInitializedData:DWORD;
SizeOfUninitializedData:DWORD;
AddressOfEntryPoint:DWORD;
BaseOfCode:DWORD;
BaseOfData:DWORD;
//
// NT additional fields.
//
ImageBase:DWORD ;
SectionAlignment:DWORD;
FileAlignment:DWORD;
MajorOperatingSystemVersion:WORD ;
MinorOperatingSystemVersion:WORD ;
MajorImageVersion:WORD ;
MinorImageVersion:WORD ;
MajorSubsystemVersion:WORD ;
MinorSubsystemVersion:WORD ;
Win32VersionValue:DWORD ;
SizeOfImage:DWORD ;
SizeOfHeaders:DWORD ;
CheckSum:DWORD ;
Subsystem:WORD ;
DllCharacteristics:WORD ;
SizeOfStackReserve:DWORD ;
SizeOfStackCommit:DWORD ;
SizeOfHeapReserve:DWORD ;
SizeOfHeapCommit:DWORD ;
LoaderFlags:DWORD ;
NumberOfRvaAndSizes:DWORD ;
DataDirectory:array [0..15] of IMAGE_DATA_DIRECTORY;
end;
IMAGE_NT_HEADERS = record
Signature:DWORD;
FileHeader:IMAGE_FILE_HEADER;
OptionalHeader:IMAGE_OPTIONAL_HEADER32;
end;
IMAGE_SECTION_HEADER = record
Name:array[0..7] of BYTE;
Misc:DWORD;
VirtualAddress:DWORD;
SizeOfRawData:DWORD;
PointerToRawData:DWORD;
PointerToRelocations:DWORD;
PointerToLinenumbers:DWORD;
NumberOfRelocations:WORD;
NumberOfLinenumbers:WORD;
Characteristics:DWORD;
end;
IMAGE_IMPORT_DESCRIPTOR = record
OriginalFirstThunk:DWORD;
// RVA to original unbound IAT (PIMAGE_THUNK_DATA)
TimeDateStamp:DWORD;
ForwarderChain:DWORD;
// -1 if no forwarders
Name:DWORD;
FirstThunk:DWORD;
// RVA to IAT (if bound this IAT has actual addresses)
end;
function toLittleE(val:word):word;overload;
begin
result := val shl 8;
result := result or (val shr 8);
end;
function toLittleE(val:dword):dword;overload;
begin
result := val shl 24;
result := result or ( ($0000FF00 and val) shl 8);
result := result or ( ($00FF0000 and val) shr 8);
result := result or ( ($FF000000 and val) shr 24);
//result := result or (val shr 8);
end;
const
dosfmt = ' Magic number=%s'+#13#10
+' File address of new exe header=%s';
ntfmt = ' Signature=%s';
filefmt =' Machine=%s'+#13#10
+' NumberOfSections=%s';
dirfmt ='no=%2d'
+' rva=%s'+#13#10
+' size=%s';
optfmt = ' AddressOfEntryPoint=%s'+#13#10
+' BaseOfCode=%s'+#13#10
+' BaseOfData=%s'+#13#10
+' ImageBase=%s'+#13#10
+' SectionAlignment=%s'+#13#10
+' SizeOfStackReserve=%s'+#13#10
+' SizeOfStackCommit=%s'+#13#10
+' SizeOfHeapReserve=%s'+#13#10
+' SizeOfHeapCommit=%s'+#13#10
+' NumberOfRvaAndSizes=%s'+#13#10;
scfmt = ' Name:(%s)'+#13#10
+' VirtualSize:%s'+#13#10
+' SizeOfRawData:%s'+#13#10
+' PointerToRawData:%s'+#13#10
+' Characteristics:%s';
var
binFile:TFileStream;
dosHeader:IMAGE_DOS_HEADER;
ntHeader:IMAGE_NT_HEADERS;
scHeader:IMAGE_SECTION_HEADER;
ipHeader:IMAGE_IMPORT_DESCRIPTOR;
Buf: array[0..SizeOf(IMAGE_DOS_HEADER) * 2] of Char;
i,j:Integer;
temp:String;
importAddr:DWORD;
begin
{ TODO -oUser -cConsole Main : この下にコードを記述してください }
Writeln(paramStr(1));
binFile := TFileStream.Create(ParamStr(1),fmOpenRead);
binFile.Read(dosHeader,sizeof(IMAGE_DOS_HEADER));
Writeln('[IMAGE_DOS_HEADER]');
Writeln(format(dosfmt,
[IntToHex(dosHeader.e_magic,4)
,IntToHex(dosHeader.e_lfanew,2)]));
binFile.Seek($100,soFromBeginning);
binFile.Read(ntHeader,sizeof(IMAGE_NT_HEADERS));
Writeln('[IMAGE_NT_HEADERS]');
Writeln(format(ntfmt,[IntToHex(ntHeader.Signature,8)]));
Writeln('[IMAGE_FILE_HEADER]');
Writeln(format(filefmt,[IntToHex(ntHeader.FileHeader.Machine,4),IntToHex(ntHeader.FileHeader.NumberOfSections,4)]));
Writeln('[IMAGE_OPTIONAL_HEADER32]');
Writeln(format(optfmt,[IntToHex(ntHeader.OptionalHeader.AddressOfEntryPoint,8)
,IntToHex(ntHeader.OptionalHeader.BaseOfCode,8)
,IntToHex(ntHeader.OptionalHeader.BaseOfData,8)
,IntToHex(ntHeader.OptionalHeader.ImageBase,8)
,IntToHex(ntHeader.OptionalHeader.SectionAlignment,8)
,IntToHex(ntHeader.OptionalHeader.SizeOfStackReserve,8)
,IntToHex(ntHeader.OptionalHeader.SizeOfStackCommit,8)
,IntToHex(ntHeader.OptionalHeader.SizeOfHeapReserve,8)
,IntToHex(ntHeader.OptionalHeader.SizeOfHeapCommit,8)
,IntToHex(ntHeader.OptionalHeader.NumberOfRvaAndSizes,8)]));
Writeln('[IMAGE_DATA_DIRECTORY]');
for i:=0 to ntHeader.OptionalHeader.NumberOfRvaAndSizes - 1 do begin
writeln(format(dirfmt,[i
,IntToHex(ntHeader.OptionalHeader.DataDirectory[i].RVA,8)
,IntToHex(ntHeader.OptionalHeader.DataDirectory[i].SIZE,8)]));
end;
Writeln('[IMAGE_SECTION_HEADER]');
for i := 0 to ntHeader.FileHeader.NumberOfSections - 1 do begin
binFile.Read(scHeader,sizeof(IMAGE_SECTION_HEADER));
temp := '';
for j := 0 to 7 do temp := temp + char(scHeader.Name[j]);
writeln(format(scfmt,[temp
,IntToHex(scHeader.Misc,8)
,IntToHex(scHeader.SizeOfRawData,8)
,IntToHex(scHeader.PointerToRawData,8)
,IntToHex(scHeader.Characteristics,8)]));
if temp = '.idata'+#0#0 then importAddr := scHeader.PointerToRawData;
end;
Writeln('[インポートセクション]');
binFile.Seek(importAddr,soFromBeginning);
binFile.Read(ipHeader,sizeof(IMAGE_IMPORT_DESCRIPTOR));
binFile.Read(temp,$36);
/// readln;
end.
こんにちは。
リンク先には
> あとは前回書いた通り、
> IMAGE_DATA_DIRECTORY::VirtualAddress - ( IMAGE_SECTION_HEADER::VirtualAddress - IMAGE_SECTION_HEADER::PointerToRawData )
> が、ファイル上でのインポートデスクリプタ(IMAGE_IMPORT_DESCRIPTOR)の位置になります。
とありますから、
IMAGE_DATA_DIRECTORY.RVA - (IMAGE_SECTION_HEADER.VirtualAddress - IMAGE_SECTION_HEADER.PointerToRawData)
となるのではないでしょうか。
なお PE ヘッダ等の構造体は、あらかた Windows.pas にて定義されています。
RTL の定義で書きなおすと、
IMAGE_DATA_DIRECTORY.VirtualAddress - (IMAGE_SECTION_HEADER.VirtualAddress - IMAGE_SECTION_HEADER.PointerToRawData)
となると思います。
ご返信ありがとうございました。
お陰様でインポートデスクリプタの取得方法は、分かりましたので
少しテストしてみます。
なので解決といたします。
ありがとうございました。
ぽちっとな
ツイート | ![]() |