Habe leider nichts fertiges hier, aber zum iterieren der Sections schnell aus dem Kopf:
Delphi-Quellcode:
WriteLn('Section Name:');
WriteLn(PAnsiChar(@ImageSectionHeader^.Name[0]));
Das ist strenggenommen falsch, denn TImageSectionHeader.Name ist
nicht notwendigerweise nullterminiert!
Wenn der Name genau 8 Zeichen lang ist, wird ein einfacher PAnsiChar-Cast wie oben möglicherweise zusätzlichen Müll ausgeben.
TImageSectionHeader.Name ist dummerweise als Array of Byte deklariert, nicht als Array of Char.
Für letzteres hat Delphi nämlich ein paar Compiler-Magic-Funktionen, die aus einem Array of (
Ansi)Char einen (
Ansi)String machen und dabei nicht stur nach der Nullterminierung suchen, sondern auch die Maximallänge des Arrays berücksichtigen (_LStrFromArray, _LStrFromWArray, _UStrFromArray, _UStrFromWArray).
Um es besser zu machen, muss man entweder eigenen Code schreiben, der das Name-Bytearray in einen String kovertiert, oder man benutzt einfach einen Cast auf ein passendes Char-Array, damit die Compiler-Magic benutzt wird:
Delphi-Quellcode:
type
TImageSectionHeaderName = array [0..IMAGE_SIZEOF_SHORT_NAME-1] of AnsiChar; // genaugenommen UTF-8 Bytes, argh
// ..
WriteLn('Section Name:');
WriteLn(TImageSectionHeaderName(ImageSectionHeader^.Name));
Um es
ganz korrekt zu machen, sollte man den String als UTF-8 kodiert ansehen und dekodieren lassen...
Hier mal Code von mir:
Delphi-Quellcode:
// GetModuleSectionHeaders: get an array of all TImageSectionHeader structures of a given Module
function GetModuleSectionHeaders(const Module: HMODULE): TArray<TImageSectionHeader>;
var
DosHeader: PImageDosHeader;
NtHeaders: PImageNtHeaders;
SectionHeader: PImageSectionHeader;
i: Integer;
begin
begin
Result := nil;
DosHeader := PImageDosHeader(Module); // a HMODULE is a memory address
// navigate the various headers and check their signatures
if DosHeader.e_magic <> IMAGE_DOS_SIGNATURE then Exit;
NtHeaders := Pointer(PByte(Module) + DosHeader._lfanew);
if (NtHeaders.Signature <> IMAGE_NT_SIGNATURE) or
(NtHeaders.OptionalHeader.Magic <> IMAGE_NT_OPTIONAL_HDR32_MAGIC) then Exit;
// corrected, thanks to Zacherl
SectionHeader := PImageSectionHeader(PByte(NtHeaders) + SizeOf(TImageNtHeaders) -
SizeOf(TImageOptionalHeader) + NtHeaders^.FileHeader.SizeOfOptionalHeader);
SetLength(Result, NtHeaders.FileHeader.NumberOfSections);
for i := Low(Result) to High(Result) do
begin
Result[i] := SectionHeader^;
// add Module's current base address to VirtualAddress
Inc(Result[i].VirtualAddress, UIntPtr(Module));
Inc(SectionHeader);
end;
end;
// GetSectionHeaderName: convert SH.Name from UTF-8 byte array to string
function GetSectionHeaderName(const SH: TImageSectionHeader): string;
type
TSectionHeaderName = array [0..IMAGE_SIZEOF_SHORT_NAME-1] of AnsiChar;
var
Raw: RawByteString;
begin
Raw := TSectionHeaderName(SH.Name); // _LStrFromArray
Result := UTF8ToString(Raw);
end;
var
SH: TImageSectionHeader;
begin
for SH in GetModuleSectionHeaders(HInstance) do
Writeln(Format('%-8s : VirtualAddress=%.8x, VirtualSize=%.8x, Characteristics=%.8x',
[GetSectionHeaderName(SH), SH.VirtualAddress, SH.Misc.VirtualSize, SH.Characteristics]));
end;