AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Sprachen und Entwicklungsumgebungen Sonstige Fragen zu Delphi Delphi DLL-EntryPoint mit Funktion tauschen?

DLL-EntryPoint mit Funktion tauschen?

Ein Thema von himitsu · begonnen am 4. Jul 2009 · letzter Beitrag vom 5. Jul 2009
Antwort Antwort
Seite 1 von 3  1 23   
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.124 Beiträge
 
Delphi 12 Athens
 
#1

DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 00:17
Die Frage ist ganz einfach:

(Wie) Kann kann man den DLL-EntryPoint mit einer Exportfunktion tauschen?


Der Hintergrund ist eben so einfach:

Ich möchte praktisch, daß z.B. Unit-Initialisierungen etwas später vorgenommen werden,
speziell die von der SysUtils und Co.

Es handelt sich um eine statisch verlinkte DLL und ich hätt gern, daß diese Initialisierungen erst nach den Intitialisierungen der EXE geschehen (indem ich's dann manuell über eine "Init"-Prozedur aufrufe).

Ansonsten müßte ich Einiges mehr umstellen und ...
es handelt sich um die DLL-Version mit Objekten meines himXML
... und außerdem würde dann der MemoryManager der DLL und nicht wie in der aktuell hochgeladenen Version der der EXE verwendet. (obwohl das notfalls auch ginge, nur daß man dann, wie bei ShareMem etwas mehr mit der Unitreihenfolge aufpassen muß)

Obwohl ... wo ich das hier grad so schreib ... das ShareMem-Problem wäre ja nicht soooo schlimm, aber ich wollte halt ungern unbedingt am MemoryManagement fremder Anwendungen rumspielen und wenn da dann wer einen "alternativen" MemoryManager verwenden wöllte, dann müßte er diesen in der DLL einbauen, da dann der der EXE mit dem der DLL überschrieben würde (im aktuellen himXML ist es ja so, daß die DLL da noch dynamisch geladen wird und den MM der EXE verpaßt bekommt ... in etwa so).

Außerdem hab ich jetzt schon etwas Zeit in dieses Problem gesteckt
und die direkte External-Verlinkung der Objekte gefällt mir halt besser, als das "verbigen" eines Objektes mit virtuellen Methoden, wie es in der aktuell onlinestehenden Version der Fall ist.
Und zusätzlich hatte ich es geschafft die RTTIs der Objekte in der DLL und Exe abzugleichen (is und as funktionieren mit der selben Objektinstanz in beiden Modulen) ... wäre schade das jetzt wieder ändern zu müssen
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
0xF48CBFF

Registriert seit: 30. Mär 2009
22 Beiträge
 
#2

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 00:55
Du kannst din der PE-Datei einfach unter IMAGE_NT_HEADERS->OptionalHeader.AddressOfEntryPoint den Einstiegspunkt überschreiben und dort den Offset deiner Prozedur oder Funktion abgeben. Aber das ist nicht gerade die beste Lösung in meinen Augen.

An deiner Stelle würde ich ein neues Datensegment anlegen, wo sich ein einfacher CALL befindet, der deine gewünschte Prozedur oder Funktion aufruft. Aus der PE kannst du den Entrypoint auslesen und dort den CALL aus den Datensegment aufrufen. Das sollte eigentlich ohne Probleme bei Funktionieren. Im Grunde kannst du dir das wie eine "Umleitung" vorstellen.

0xF48CBFF
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.124 Beiträge
 
Delphi 12 Athens
 
#3

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 10:45
OK, den EntryPoint hab ich nun, jetzt muß ich wohl nur noch die Sections durchsehn, die Export-Tabelle finden und da meine Init-Prozedur finden

Aber in dem Code da seh ich noch nicht so durch und Brechi hat seinen Code ja nicht veröffentlicht.
Nja, ich versuch mich noch durchzuwurteln und hoff bald die Sectionen zu finden.


Nur das mit dem neuen Datensegment hab ich jetzt nicht so verstanden, also wie mir dieses helfen soll,
bzw. wie ich dann den "Call" zum "alten" EntryPoint darin aufrufen müßte?


[add]
OK, ich hab endlich die SectionHeader-Liste gefunden, jetzt nur noch des komische Offset x+$d0 in dem Record suchen und als x.Irgendwas schreiben.

Und dann mal sehn wo ich die Exporttabelle finde.

[add]
ich glaub .edata klingt gut
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#4

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 11:05
Zitat von himitsu:
Aber in dem Code da seh ich noch nicht so durch und Brechi hat seinen Code ja nicht veröffentlicht.
Nja, ich versuch mich noch durchzuwurteln und hoff bald die Sectionen zu finden.
Da kann ich dir evt. helfen:
Code:
--Also am Anfang der Echse befindet sich der DOS-Header. Den einfach auslesen - am besten in eine Variable des Typs _Image_Dos_Header
--Im _lfanew von diesem Typ steht der Offset zum nächsten Header, dem NT-Header; Typbezeichnung: _IMAGE_NT_HEADERS
--_IMAGE_NT_HEADERS besteht seinerseits aus folgenden 3 Typen:
Signature, FileHeader, OptionalHeader.
Im FileHeader findest du dann folgendes: NumberOfSections-> Das ist die Anzahl der Sections, welche gleich nach diesem Header (_Image_NT_Headers) folgen.
--Die Sections liest du dann anschließend am besten in ein Array aus TImageSectionHeader ein.
Zitat von himitsu:
... wie ich dann den "Call" zum "alten" EntryPoint darin aufrufen müßte?
Falls du die Echse Hex-weise bearbeiten willst (asm), dann reicht das hier schon vollkommen aus:
Code:
  mov eax, <AdresseVomOrginalenEntryPoint>
  jmp eax
Hoffe ich konnt' helfen

MfG
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#5

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 11:11
Was wäre denn das Problem dabei, einfach die RVAs der exportierten Funktion im Export-Directory und des Entry Points zu vertauschen? Dann muss man keinerlei tiefgreifende Veränderungen in der Datei vornehmen.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.124 Beiträge
 
Delphi 12 Athens
 
#6

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 12:57
@Apollonius: so hatte ich es mir auch gedacht ... nur muß ich es erstmal hinbekommen.

@Aphton: das Aufrufen selber wäre dann nicht das Problem, aber ich müßte dann im Programm doch auch erstmal diese Section finden, um sie aufzurufen .... bei deiner Progedur laß ich mir dagegen einfach von GetProcAddress helfen.

Inzuwischen bin ich so weit ... ich hab die ganzen Sections gefunden, den EntryPoint und auch die Export-Tabele,

aber dann komm ich nicht weiter .. beim Auslesen der Funktionsnamen.

P := ImageSection + Integer(ExportDirectory.AddressOfNames); P müßte hier auf den ersten Namen stehen, aber wenn ich drauf zugreifen will, dann knallt's

In IMAGE_EXPORT_DIRECTORY.AddressOfNames steht die Adresse als RVA (Relative Virtual Adress), also relativ zur ImageBase in der geladenen DLL, wenn ich das richtig verstanden hab.

Nun hab ich die DLL aber nicht geladen und dachte mir, ich nehm das "einfach" relativ zum Imageabbild (.data Sektion) in der Datei, aber da bekomm ich ja eine Exception und grad eben geht es zufällig mal, aber er ließt nur unverständlichen Mißt (also irgendwas Anderes, nur keine Namen)

[edit]
OK, hab grad mitbekommen, daß Namensliste nicht aus den Namen selber besteht, sondern aus einem Array of "Zeigern" auf die Namen ...

vorher so
Delphi-Quellcode:
Var
  ImageSection, P: PAnsiChar;

asm int 3 end;
                WriteLn('search the init procedure');
                InitProcedure := 0;
                P := ImageSection + Integer(ExportDirectory.AddressOfNames);
                i := -1;
                While i < ExportDirectory.NumberOfNames do Begin
                  WriteLn(' procedure/function "' + P + '" found');
                  If P = 'initDLLThen
                    If InitProcedure <> -1 Then Begin
                      InitProcedure := -2;
                      WriteLn(' found more than one init procedures');
                    End Else InitProcedure := i;
                  Inc(P, lstrlenA(P) + 1);
                  Inc(i);
                End;
                If InitProcedure >= 0 Then Begin

jetzt so , aber geht immernoch nicht

ich vermute erstmal, daß ich irgendwas bei der Verwendung des RVA falsch mach

Delphi-Quellcode:
Program himXML_DLL_Modifizierer;

{$APPTYPE CONSOLE}

Uses Windows, SysUtils;

Procedure WriteLn(Const S: String);
  Var OEMBuffer: Array[0..2047] of AnsiChar;

  Begin
    CharToOem(PChar(S), @OEMBuffer);
    System.WriteLn(OEMBuffer);
  End;

Procedure WriteError(Const S: String);
  Var S2: String;

  Begin
    S2 := SysErrorMessage(GetLastError);
    WriteLn(S + ' >> ' + S2);
  End;

Type TSectionName = packed Array[0..IMAGE_SIZEOF_SHORT_NAME-1] of AnsiChar;

Var N: String;
  H, M: THandle;
  DOSHeader: ^IMAGE_DOS_HEADER;
  NTHeaders: ^IMAGE_NT_HEADERS;
  SectionHeader: ^IMAGE_SECTION_HEADER;
  ImageSection: PAnsiChar;
  ExportDirectory: ^IMAGE_EXPORT_DIRECTORY;
  Names: PCardinal;
  InitProcedure, i: Integer;

Begin
  Try
    N := ExtractFilePath(ParamStr(0)) + 'himXML_DLL.dll';
    WriteLn('open "' + N + '"');
    H := CreateFile(PChar(N), GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
    If H <> INVALID_HANDLE_VALUE Then Begin
      WriteLn('load file data');
      M := CreateFileMapping(H, nil, PAGE_READWRITE, 0, 0, nil);
      DOSHeader := MapViewOfFile(M, FILE_MAP_READ or FILE_MAP_WRITE, 0, 0, 0);
      If (M <> 0) and Assigned(DOSHeader) Then Begin
        WriteLn('check IMAGE_DOS_HEADER');
        If DOSHeader.e_magic = IMAGE_DOS_SIGNATURE Then Begin
          WriteLn('search and check IMAGE_NT_HEADERS');
          NTHeaders := Pointer(Integer(DOSHeader) + DOSHeader._lfanew);
          If NTHeaders.Signature = IMAGE_NT_SIGNATURE Then Begin
            WriteLn('search image and export section');
            SectionHeader := Pointer(Integer(NTHeaders) + SizeOf(IMAGE_NT_HEADERS));
            ImageSection := nil;
            ExportDirectory := nil;
            i := 0;
            While i < NTHeaders.FileHeader.NumberOfSections do Begin
              WriteLn(' section "' + TSectionName(SectionHeader.Name) + '" found');
              If TSectionName(SectionHeader.Name) = '.dataThen
                If ImageSection <> nil Then Begin
                  ImageSection := Pointer(1);
                  WriteLn(' found more than one .data sections');
                End Else ImageSection := Pointer(Integer(DOSHeader) + SectionHeader.PointerToRawData);
              If TSectionName(SectionHeader.Name) = '.edataThen
                If ExportDirectory <> nil Then Begin
                  ExportDirectory := Pointer(1);
                  WriteLn(' found more than one .edata sections');
                End Else ExportDirectory := Pointer(Integer(DOSHeader) + SectionHeader.PointerToRawData);
              Inc(SectionHeader);
              Inc(i);
            End;
            If Cardinal(ImageSection) > 1 Then Begin
              If Cardinal(ExportDirectory) > 1 Then Begin
asm int 3 end;
                WriteLn('search the init procedure');
                InitProcedure := 0;
                Names := Pointer(ImageSection + Integer(ExportDirectory.AddressOfNames));
                i := -1;
                While i < ExportDirectory.NumberOfNames do Begin
                  WriteLn(' procedure/function "' + PAnsiChar(Integer(ImageSection) + Names^) + '" found');
                  If PAnsiChar(Integer(ImageSection) + Names^) = 'initDLLThen
                    If InitProcedure <> -1 Then Begin
                      InitProcedure := -2;
                      WriteLn(' found more than one init procedures');
                    End Else InitProcedure := i;
                  Inc(Names);
                  Inc(i);
                End;
                If InitProcedure >= 0 Then Begin


                  If NTHeaders.OptionalHeader.AddressOfEntryPoint <> 0 Then ;


                  WriteLn('OK');
                End Else WriteError('not found');
              End Else WriteLn('export section not found');
            End Else WriteLn('image section not found');
          End Else WriteError('not found');
        End Else WriteError('not found');
        UnmapViewOfFile(DOSHeader);
      End Else WriteError('can''t load');
      CloseHandle(M);
    End Else WriteError('no access to file or not exists');
    CloseHandle(H);
  Except
    On E:Exception do WriteLn(E.Classname + ': ' + E.Message);
  End;
  ReadLn;
End.

[add]
in meinen Anfängen dieses Codes hatte ich ja Codes von Anderen verwendet, z.B. Beispiele aus Google und der DP
und dem MSDN, also die Beschreibungen Structuren.

Delphi-Quellcode:
// so in etwa hatte es mr_emre_d
SectionHeader := Pointer(Integer(NTHeaders) + $D0);
// das hatte ich übersetzt und mir gedacht, was is'n das für'n Sch***,
// und warum sollte die Textionstabelle dort anfangen *schonrauchendenkopfhatte*
SectionHeader := @NTHeaders.OptionalHeader.DataDirectory[11].VirtualAddress;

// aber mr_emre_d hatte ja in seiner Schleife quasi Inc(SectionHeader) vorher
// und daher der komisch Offset

SectionHeader := Pointer(Integer(NTHeaders) + $D0);
i := 0;
While i < NTHeaders.FileHeader.NumberOfSections do Begin
  Inc(SectionHeader);
  If TSectionName(SectionHeader.Name) = '.edataThen Break;
  Inc(i);
End;

// also warum einfach, wenn schwer geht -.-°
SectionHeader := Pointer(Integer(NTHeaders) + SizeOf(IMAGE_NT_HEADERS));
i := 0;
While i < NTHeaders.FileHeader.NumberOfSections do Begin
  If TSectionName(SectionHeader.Name) = '.edataThen Break;
  Inc(SectionHeader);
  Inc(i);
End;
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#7

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 13:08
Das Export-Directory hat grundsätzlich erstmal nichts mit der Export-Section zu tun (klar, normalerweise liegt das Directory in der Section, aber das ist nicht verpflichtend). Du findest einen Directory Header am Ende des Optional Headers.
Du stehst hier vor dem Problem, eine RVA in einen Dateioffset umzurechnen. Dazu musst du über alle Sections iterieren, überprüfen, in welcher Section die RVA liegt und dann über den Dateioffset der Section zum Dateioffset der RVA kommen.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.124 Beiträge
 
Delphi 12 Athens
 
#8

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 13:24
Zitat von Apollonius:
Das Export-Directory hat grundsätzlich erstmal nichts mit der Export-Section zu tun (klar, normalerweise liegt das Directory in der Section, aber das ist nicht verpflichtend). Du findest einen Directory Header am Ende des Optional Headers.
Hmmmm, also wenn du IMAGE_NT_HEADERS.OptionalHeader.DataDirectory meinst ... k.A. was ich mit den Daten darin anfangen soll.

Naj, zumindestens handelt es sich immer um eine bestimmte Delphi-Datei und ich vertraue jetzt einfach mal drauf, daß Borland äh Codegar oder Embarcadero da nicht einfach mal was dran ändern werden und ich es weiterhin da finde.

Zitat von Apollonius:
Du stehst hier vor dem Problem, eine RVA in einen Dateioffset umzurechnen. Dazu musst du über alle Sections iterieren, überprüfen, in welcher Section die RVA liegt und dann über den Dateioffset der Section zum Dateioffset der RVA kommen.
Na dann versuch ich mir da mal 'ne RVA2RealPointer (oder so) zu basteln
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PosEx im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Aphton
Aphton

Registriert seit: 31. Mai 2009
1.198 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 13:28
@Himitsu[Addendum]

Sorry wegen der blöden, kryptischen Beschreibung...
(Ja, ich bin der Emre)

Ich häng mal ein Projekt von mir, welche noch nicht beendet wurde und auch nicht wird, weils mich nicht mehr interessiert bzw. meine Ziele im jetztigen Zustand erfüllt...
Evt. kannst du dir da was abschaun.
PS: Ich hatte nie vor, das Programm zu veröffentlichen. Sourcecode ist leider diesmal auch ein wenig kryptisch UND ich weiß, dass es einen Memory-leak gibt..

MfG
Angehängte Dateien
Dateityp: rar peies_imports_exports__980.rar (201,9 KB, 6x aufgerufen)
das Erkennen beginnt, wenn der Erkennende vom zu Erkennenden Abstand nimmt
MfG
  Mit Zitat antworten Zitat
Apollonius

Registriert seit: 16. Apr 2007
2.325 Beiträge
 
Turbo Delphi für Win32
 
#10

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 13:33
Zitat von himitsu:
Hmmmm, also wenn du IMAGE_NT_HEADERS.OptionalHeader.DataDirectory meinst ... k.A. was ich mit den Daten darin anfangen soll.
Das PE-Format gibt bestimmte Directories vor, z.B. Imports, Exports, Relocations, Ressourcen usw. Jedes dieser Directories hat eine Nummer, beispielsweise ist das Export-Directory das Erste, hat also die Nummer Null. Alle Directories findest du bei MSDN-Library durchsuchenIMAGE_DATA_DIRECTORY.

Edit: Die PE-Spezifikation schreibt übrigens keine Section-Namen vor - niemand kann dich hindern, deine Code-Section "Klaus" zu nennen.
Wer erweist der Welt einen Dienst und findet ein gutes Synonym für "Pointer"?
"An interface pointer is a pointer to a pointer. This pointer points to an array of pointers, each of which points to an interface function."
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23   

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 20:36 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz