Einzelnen Beitrag anzeigen

Benutzerbild von himitsu
himitsu
Online

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

Re: DLL-EntryPoint mit Funktion tauschen?

  Alt 4. Jul 2009, 11: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;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat