Announcement

Collapse
No announcement yet.

Module ermitteln

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Module ermitteln

    Hi,
    gibt es eine Möglichkeit mit Delphi 3 P. festzustellen, welche Module (DLL-Dateien, Exe-Dateien) von einem Programm gerade benötigt werden ?

    Danke

  • #2
    Hallo,

    ja - jede Anwendung kann die explizit oder implizit nachgeladenen DLLs mitprotokollieren, die in den eigenen Adressraum geladen werden. Win32 schafft mit dem <i>Debug API</i> die dafür notwendigen Voraussetzungen (d.h. das Programm meldet sich bei Win32 als "Debugger" an). Allerdings ist der Implementierungsaufwand nicht unerheblich. In meinen Büchern <b>Delphi 3 Lösungen</b> (leider bereits vergriffen) und dem demnächst erscheinenden <b>Delphi Win32-Lösungen</b> stelle ich ein derartiges Programm vor, das "fremde" Anwendungen starten kann und dabei alle geladenen DLLs auflistet

    Comment


    • #3
      Hallo Andreas,,
      ist ja schön, daß es so eine Möglichkeit gibt. Nur würde ich gerne wissen, wie man soetwas realisiert.
      Ich glaube Die, daß der Implementierungsaufwand nicht unerheblich ist.
      Nur kannst Du nicht einen kleinen Tip geben ?

      Dank

      Comment


      • #4
        Hallo,

        der folgende Programmauszug demonstriert das Prinzip. Das zu überwachende Programm wird als Prozess mit dem Flag DEBUG_ONLY_THIS_PROCESS gestartet - somit informiert Windows das eigene Programm über bestimmte Ereignisse in dem gestarteten Prozess. Über den Aufruf von <b>WaitForDebugEvent</b> legt sich die eigene Anwendung auf die Lauer, um beim Eintreffen von Load_DLL_Debug_Event im fremden Prozess nachzuschauen, welche DLL aus welchem Verzeichnis gerade geladen wurde.
        <pre>
        procedure TDebugThread.Execute;
        var
        dwContinue : DWord;
        aEvent : TDebugEvent;
        begin
        bBreakFlag := False;
        // Größe der Struktur in Byte eintragen
        FSI.cb := SizeOf(FSI);
        // das zu untersuchende Programm als neuen Prozeß starten
        Win32Check(CreateProcess(PChar(FEXEName), nil, nil, nil, False,
        Debug_Only_This_Process,
        nil, nil, FSI, FPI));
        // in TProcessInformation.hProcess liegt das Prozeß-Handle bereit
        FProcess := FPI.hProcess;
        CloseHandle(FPI.hThread);
        // Auf Debug-Botschaften von Windows warten
        while WaitForDebugEvent(aEvent, Infinite) do begin
        case aEvent.dwDebugEventCode of
        Create_Process_Debug_Event : ListCreateProcess(aEvent);
        Create_Thread_Debug_Event : begin
        FMemoText := ' Create Thread ...';
        Synchronize(MemoAdd);
        end;
        Exit_Thread_Debug_Event : begin
        FMemoText := ' ... Exit Thread';
        Synchronize(MemoAdd);
        end;
        Load_DLL_Debug_Event : ListLoadDLL(aEvent);
        Output_Debug_String_Event : ListOutputDebugString(aEvent);
        Exception_Debug_Event : ListException(aEvent);
        end;
        // Abbruch-Bedingung erreicht ?
        if (aEvent.dwDebugEventCode = Exit_Process_Debug_Event) then begin
        FMemoText := '... Programm wurde beendet (Exit_Process_Debug_Event)';
        Synchronize(MemoAdd);
        break;
        end;
        // Weitermachen bis zum nächsten Debug-Ereignis
        if bBreakFlag then dwContinue := DBG_EXCEPTION_NOT_HANDLED
        else dwContinue := DBG_CONTINUE;
        ContinueDebugEvent(aEvent.dwProcessId, aEvent.dwThreadId,
        dwContinue);
        end;
        // Ressourcen wieder freigeben
        CloseHandle(FProcess);
        end;
        </pre>
        Dazu wird die Win32-API-Funktion <b>ReadProcessMemory</b> verwendet, die in der Lage ist, Daten aus fremden (!) Adressräumen auszulesen:
        <pre>
        procedure TDebugThread.ListLoadDLL(aEvent : TDebugEvent);
        var
        aDOSHdr : IMAGE_DOS_HEADER;
        aNTHdr : IMAGE_NT_HEADERS;
        dwNumRead : DWord;
        aPointer : Pointer;
        szDLLName : array[0..199] of Char;
        hDLLModule : DWord;
        dwExportRVA: DWord;
        aIEDHdr : IMAGE_EXPORT_DIRECTORY;
        bBadRead : Boolean;
        begin
        Inc(FDLLCount);
        // Modul-Namen der DLL nachschlagen
        hDLLModule := hModule(aEvent.LoadDLL.lpBaseOfDLL);
        GetModuleFileName(hDLLModule, szDLLName, SizeOf(szDLLName));
        // DOS-Header der EXE auslesen
        ReadProcessMemory(FProcess, aEvent.LoadDLL.lpBaseOfDLL,
        @aDOSHdr, SizeOf(aDOSHdr), dwNumRead);
        // DOS-EXE-Kennung "MZ" vorhanden ?
        if aDOSHdr.e_magic <> IMAGE_DOS_SIGNATURE then Abort;
        // Offset zum PE-Header berechnen
        aPointer := Pointer(DWord(aEvent.LoadDLL.lpBaseOfDLL) +
        DWord(aDOSHdr.e_lfanew));
        // gültige Adresse ?
        if IsBadReadPtr(aPointer, Sizeof(aNTHdr)) then bBadRead := True
        else bBadRead := False;
        // PE-Headerstruktur auslesen
        ReadProcessMemory(FProcess, aPointer, @aNTHdr,
        SizeOf(aNTHdr), dwNumRead);
        // PE-EXE-Kennung "PE" vorhanden ?
        if aNTHdr.Signature <> IMAGE_NT_SIGNATURE then Abort;
        // Magic vom IMAGE_OPTIONAL_HEADER vergleichen
        if aNTHdr.OptionalHeader.Magic <> $10B then Abort;
        // DLL-Pfad ist leer -> Modulenamen suchen
        if StrLen(szDLLName) = 0 then begin
        dwExportRVA := aNTHdr.OptionalHeader.DataDirectory[0].VirtualAddress;

        Comment


        • #5
          Hi John

          Eine andere Möglichkeit die benutzten DLL's einer Anwendung durch die Anwendung selber und WÄHREND der Laufzeit zu ermitteln ist diese:

          <pre>

          var
          I: Integer;
          N: array[0..MAX_PATH] of Char;
          begin
          for I := 0 to $FFFF do
          begin
          if GetModuleFileName(I shl 16, @N, SizeOf(N)) > 0 then
          // es gibt ein Modul mit (I shl 16) als HInstance
          end;
          end;

          </pre>

          Im Grunde wird einfach ausprobiert ob ein Modul mit (I shl 16) als HInstance existiert. Diese Methode funktioniert bei mir unter allen Windows-Version, verursacht keinerlei Abstürze, ist schneller als die Funktionen aus Unit ToolHlp32 oder denen von NT. Bis jetzt habe ich festgestellt das sie sogar Module aufzählt die NICHT direkt von der Application benutzt werden, also auch Module die durch ein Modul der Anwendung geladen wurden. Der Links-Shift um 16 Bits ist kein problem da generell ALLE Modul-Instanzen die unteren 16Bits nicht nutzen.

          Gruß Hage

          Comment

          Working...
          X