![]() |
.text section dumpen
Hallo,
Ich würde gerne (so schön wie möglich) die .text oder CODE section aus meinem eigenen Prozess dumpen. Mein momentaner Plan ist mittels ReadProcessMemory() ab der Imagebase den gesamten (eigenen) Prozess zu kopieren (aus dem Speicher) und dann mittels PE-Offsets die Stelle der .text-Section zu ermitteln. Da ich wirklich faul bin und überhaupt keine Lust mehr habe ein PE-Tutorial auszupacken und mich durch die ganzen Offsets, Alignments und was weiß ich durchzuwühlen, hoffe ich hier um ehrlich zusein auf eine Codelösung. a Vieleicht hat ja jemand ein früheres Projekt in dem er eine Section des eigenen (oder fremden) Prozesses kopiert/gedumpt hat und wäre so freundlich das Snippet hier zu posten. Ansonsten hoffe ich auf alternative Lösungen. Alternative Lösungen sollten aber nur das von mir genannte Problem lösen, also keine Workarounds. Ich möchte aus dem Speicher heraus, eine Section kopieren - nicht anders. Danke :) |
AW: .text section dumpen
Mit der PE Dokumentation hast du das in einer Stunde locker geschafft. Dauert deutlich weniger lange, als hier auf eine fertige Lösung zu warten (die aller Wahrscheinlichkeit nach bei dieser spezifischen Fragestellung nicht kommen wird).
ReadProcessMemory im eigenen Prozess zu verwenden ist btw. relativ unsinnig. Du kannst den Speicher auch einfach direkt ansprechen. |
AW: .text section dumpen
Zitat:
Vermutlich hast du recht. Ich muss auch gestehen, dass ich die letzte Zeile in diesem Thread gelöscht habe. In der stand: "Ich warte dann mal auf die Antwort von Zacherl, mit viel Glück hat er noch was übrig". Wenn - dann hätte ich ein Snippet von dir erwartet hier als native Windows Experte :P Naja dann pack ich mal die alten ARTeam Tut's aus ^^ Danke trotzdem ;) |
AW: .text section dumpen
Zitat:
Habe leider nichts fertiges hier, aber zum iterieren der Sections schnell aus dem Kopf:
Delphi-Quellcode:
Statt hInstance kannst du auch die ImageBase einer beliebigen Dll nehmen, falls du das brauchst. Die Section dumpst du dir dann einfach mit CreateFile/WriteFile über die Virtual Address.
var
ImageBase: Pointer; ImageDosHeader: PImageDosHeader; ImageNtHeaders: PImageNtHeaders; ImageSectionHeader: PImageSectionHeader; I: Integer; begin ImageBase := Pointer(hInstance); ImageDosHeader := PImageDosHeader(ImageBase); if (ImageDosHeader^.e_magic <> IMAGE_DOS_SIGNATURE) then begin Exit; end; ImageNtHeaders := PImageNtHeaders(PByte(ImageDosHeader) + ImageDosHeader^._lfanew); if (ImageNtHeaders^.Signature <> IMAGE_NT_SIGNATURE) then begin Exit; end; ImageSectionHeader := PImageSectionHeader(PByte(ImageNtHeaders) + SizeOf(TImageNtHeaders) - SizeOf(TImageOptionalHeader) + ImageNtHeaders^.FileHeader.SizeOfOptionalHeader); I := 1; while (I < ImageNtHeaders^.FileHeader.NumberOfSections) do begin WriteLn('Section Name:'); WriteLn(PAnsiChar(@ImageSectionHeader^.Name[0])); WriteLn('Virtual Address:'); WriteLn(IntToHex(NativeUInt(ImageBase) + ImageSectionHeader^.VirtualAddress, SizeOf(Pointer) * 2)); WriteLn('Size:'); WriteLn(IntToHex(ImageSectionHeader^.SizeOfRawData, 1)); Inc(ImageSectionHeader); Inc(I); end; end; Würde mich allerdings nicht drauf verlassen, dass sich alle Binaries an die .text bzw. .code Konvention bezüglich des Section Names halten. |
AW: .text section dumpen
Zitat:
Ja für .UPX etc. brauche ich ja keinen Support, schließlich dumpe ich ja die eigene Section und den Namen kann ich ja (wenn er wirklich != .text/.code sein sollte anpassen :) Anonsten hast du mir das Leben erleichtert, ist schon eine ganze Weile her seitdem ich was mit w32 PE zeug gemacht habe, und ich vergesse leider schnell. Ich schreibs später fertig, dann poste ich es mal :) Bis dann & nochmals danke |
AW: .text section dumpen
Zitat:
![]() 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:
Um es ganz korrekt zu machen, sollte man den String als UTF-8 kodiert ansehen und dekodieren lassen...
type
TImageSectionHeaderName = array [0..IMAGE_SIZEOF_SHORT_NAME-1] of AnsiChar; // genaugenommen UTF-8 Bytes, argh // .. WriteLn('Section Name:'); WriteLn(TImageSectionHeaderName(ImageSectionHeader^.Name)); 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; |
AW: .text section dumpen
Zitat:
Deine Funktion berechnet allerdings den Zeiger auf die erste ImageSection nicht korrekt.
Delphi-Quellcode:
funktioniert nicht immer. Ist zwar ein ziemlich synthetischer Fall, aber das PE Format sieht vor, dass der OptionalHeader eine variable Länge haben kann. Deshalb muss die korrekte Berechnung über
SectionHeader := PImageSectionHeader(NativeInt(NtHeaders) + SizeOf(NtHeaders^))
Delphi-Quellcode:
erfolgen.
ImageSectionHeader := PImageSectionHeader(PByte(ImageNtHeaders) + SizeOf(TImageNtHeaders) -
SizeOf(TImageOptionalHeader) + ImageNtHeaders^.FileHeader.SizeOfOptionalHeader) |
AW: .text section dumpen
Danke! Wieder was gelernt. :)
Der Code von mir war auch schon etwas älter, sehe ich gerade an der Benutzung von NativeInt. Heute caste ich Pointer nur noch auf vorzeichenlose Typen (NativeUInt oder UIntPtr), oder gleich auf PByte wie in deinem Beispiel. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:34 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz