Delphi-PRAXiS
Seite 3 von 4     123 4      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Auf Dateien zugreifen die gerade in Gebracuh sind (?) (https://www.delphipraxis.net/119440-auf-dateien-zugreifen-die-gerade-gebracuh-sind.html)

nicodex 14. Nov 2008 08:37

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Der Treiber löst eines der Hauptprobleme, die im Benutzermodus nicht sauber zu lösen sind. Mittels ObReferenceObjectByHandle, ObQueryNameString und ObDereferenceObject wird der Objektname zu einem Handle ermittelt.

Fridolin Walther 14. Nov 2008 11:04

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Das Ganze lässt sich teilweise auch im Usermode sauber lösen, sofern man nicht versucht die Namen von Handles aufzulösen, die bestimmte Access Flags gesetzt haben. Solang man also aufpasst was man dort tut, ist also auch das kein Problem.

Luckie 14. Nov 2008 11:07

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Zitat:

Zitat von 0xF30FC7
sofern man nicht versucht die Namen von Handles aufzulösen, die bestimmte Access Flags gesetzt haben.

Aber das ist ja Sinn und Zweck der Übung. Was will ich mit irgendwelchen Zahlenkolonen, die mir nichts sagen? Ich mache das ja extra um den Namen zu bekommen.

Fridolin Walther 14. Nov 2008 11:12

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Die Handles mit den entsprechenden Access Flags sind im Normalfall nur Named Pipes. Bedeutet bei "echten" Datei Handles kannst Du die Namen durchaus auflösen. Nur an die Namen von Named Pipes kommst Du halt nicht ran, was im hier gefragten Szenario aber nicht von Bedeutung ist. Und auch bei Named Pipes sind es nur eine gewisse Teilmenge an Handles die Du nicht auflösen kannst.

Luckie 14. Nov 2008 11:15

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Kann man das irgendwie vor der Namesauflösung unterscheiden?

Ich habe hier mal etwas probiert: http://www.michael-puff.de/Developer...leUnlocker.zip Zur Zeit werdenn erstmal nur die Dateiene aufgelistet und bei den obengenannten Fällen, bleibt das Programm hängen. Wenn man das verhindern könnte, in dem man in den Fällen die Namen nicht abfragt, wäre das super.

Fridolin Walther 14. Nov 2008 11:17

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Ja, an den Access Flags wie gesagt. Wenns Dich interessiert ... ich hab das mal implementiert. Kann Dir da einen Sample Code zukommen lassen :).

Luckie 14. Nov 2008 11:25

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Zitat:

Zitat von 0xF30FC7
Ja, an den Access Flags wie gesagt. Wenns Dich interessiert ... ich hab das mal implementiert. Kann Dir da einen Sample Code zukommen lassen :).

Gut. Aber poste das das hier imForum, dannhaben alle was davon und Nico kann auch noch mal drübergucken.

Fridolin Walther 14. Nov 2008 11:28

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Zitat:

Zitat von Luckie
Ich habe hier mal etwas probiert: http://www.michael-puff.de/Developer...leUnlocker.zip Zur Zeit werdenn erstmal nur die Dateiene aufgelistet und bei den obengenannten Fällen, bleibt das Programm hängen. Wenn man das verhindern könnte, in dem man in den Fällen die Namen nicht abfragt, wäre das super.

2 Hinweise:

1. Check ob GrantedAccess beim Handle <> $12019f. File Handles mit der Access Mask 0x12019f sind letztlich die, die dafür sorgen das Du hängst.
2. RemoteCloseHandle ist unvorteilhaft implementiert. Um ein Handle im Zielprozess zu schließen, duplizier das Handle mit dem Flag DUPLICATE_CLOSE_SOURCE. Das sorgt dafür, das das Handle im Remote Prozess geschlossen wirst, sobald Du es in Deinem Prozess schließt.

Fridolin Walther 14. Nov 2008 12:10

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Wie versprochen der Code. Es sollten keine Lock Ups produziert werden. Angezeigt werden alle Object Names aller Handles, sofern diese verfügbar sind. Das sind nicht nur Namen von geöffneten Dateien sondern auch die Namen von Memory Mapped Files, Mutexes, Registry Keys etc.. Wenn man nur eine bestimmte Art von Handle haben möchte, liesse sich das allerdings filtern. Würde den Beispiel Quellcode nur unnötig komplex machen :).

Delphi-Quellcode:
program lon;

{$APPTYPE CONSOLE}

uses
  JwaWinType,
  JwaWinNT,
  JwaWinBase,
  JwaNtStatus,
  JwaNative,
  TlHelp32,
  sysutils;

procedure NTSetPrivilege(Privilege: string; Enabled: Boolean);
var
  Token: THandle;
  TokenPriv: TOKEN_PRIVILEGES;
  PrevTokenPriv: TOKEN_PRIVILEGES;
  ReturnLength: Cardinal;
begin
  if OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES or TOKEN_QUERY, Token) then
    try
      if LookupPrivilegeValue(nil, PChar(Privilege), TokenPriv.Privileges[0].Luid) then
        begin
          TokenPriv.PrivilegeCount := 1;

          case Enabled of
            True: TokenPriv.Privileges[0].Attributes := SE_PRIVILEGE_ENABLED;
            False: TokenPriv.Privileges[0].Attributes := 0;
          end;

          ReturnLength := 0;
          PrevTokenPriv := TokenPriv;

          AdjustTokenPrivileges(Token, False, @TokenPriv, SizeOf(PrevTokenPriv), @PrevTokenPriv, @ReturnLength);
      end;
    finally
      CloseHandle(Token);
    end;
end;

procedure ListAllHandleNames;
const
  MaximumHandleCount = 100000;
var
  Buffer : Pointer;
  MemoryNeeded : ULong;
  Unused : ULong;
  HandleInformation : PSystemHandleInformation;
  HandleCount : PULong;
  ObjectName : PObjectNameInformation;
  LocalHandle : THandle;
  ProcessHandle : THandle;
  ObjectString : string;
  i : Integer;
begin

  // Initialisierung
  MemoryNeeded := MaximumHandleCount * SizeOf(TSystemHandleInformation);

  // Handle Liste holen
  GetMem(Buffer, MemoryNeeded);
  if not NT_SUCCESS(NtQuerySystemInformation(SystemHandleInformation, Buffer, MemoryNeeded, nil)) then
    begin
      writeln('NtQuerySystemInformation fehlgeschlagen (Handle Array zu klein?).');
      FreeMem(Buffer);
      Exit;
    end;

  HandleCount := Buffer;
  HandleInformation := Pointer(LongWord(Buffer) + 4);
  for i := 0 to HandleCount^ - 1 do
    begin
      ProcessHandle := OpenProcess(PROCESS_DUP_HANDLE, false, HandleInformation^.ProcessId);
      if ProcessHandle <> 0  then
        begin
          // Spezielle Named Pipes machen Probleme bei der Abfrage. Diese Pipes haben
          // als Access Mask 0x12019F. Entsprechend werden nur Handles abgefragt, die
          // nicht 0x12019F als Access Mask haben.
          if HandleInformation^.GrantedAccess <> $12019F then
            begin
              GetMem(ObjectName, 65536);
              if DuplicateHandle(ProcessHandle, HandleInformation^.Handle, GetCurrentProcess(), @LocalHandle, 0, false, DUPLICATE_SAME_ACCESS) and (ObjectName^.Name.Buffer <> nil)then
                begin
                  if NT_SUCCESS(NtQueryObject(LocalHandle, ObjectNameInformation, ObjectName, 65536, @Unused)) and (ObjectName^.Name.Buffer <> nil) then
                    begin
                      ObjectString := LowerCase(WideString(ObjectName^.Name.Buffer));
                      writeln(Format('Process: %.8x - Handle: %.8x ObjectName: %s', [HandleInformation^.ProcessId, HandleInformation^.Handle, ObjectString]));
                    end;
                  CloseHandle(LocalHandle);
                end;
              FreeMem(ObjectName);
            end;
          CloseHandle(ProcessHandle);
        end;
      inc(HandleInformation);
    end;
  FreeMem(Buffer);
end;

begin
  NTSetPrivilege('SeDebugPrivilege', True);
  ListAllHandleNames;
end.
[EDIT]Memory Leak gefixt.[/EDIT]

Luckie 14. Nov 2008 12:17

Re: Auf Dateien zugreifen die gerade in Gebracuh sind (?)
 
Delphi-Quellcode:
{*******************************************************************************
  Procedure: EnumFileHandles
  Author  : EvilSoft, mp
  Date    : 2008-09-04
  Comment : List all file handles.
*******************************************************************************}
procedure EnumFileHandles(CallBack: TEnumFileHandlesCB; FilterStr: string = '');
var
  HandlesInfo      : PSYSTEM_HANDLE_INFORMATION_EX;
  FileName         : string;
  r                : Integer;
  ObjTypeNumberFile : Integer;
  lib              : integer;
  DupHandle        : THandle;
  ProcHandle       : THandle;
  OSVer            : TOSVersionInfo;
label
  log;
begin
  // Load libraries
  lib := LoadLibrary('ntdll.dll');
  if lib = 0 then
    Exit;
  try
    @NtQuerySystemInformation := GetProcAddress(lib, 'NtQuerySystemInformation');
    @NtQueryInformationFile := GetProcAddress(lib, 'NtQueryInformationFile');
    @NtQueryObject := GetProcAddress(lib, 'NtQueryObject');

    if (@NtQuerySystemInformation = nil) or
      (@NtQueryInformationFile = nil) or
      (@NtQueryObject = nil) then
      Exit;

    // Determine ObjectTypeNumber constant for file objects
    //              Windows 95  Windows 98  Windows Me Windows NT 4.0  Windows 2000  Windows XP
    //Plattform-ID    1           1           1             2              2             2
    //Majorversion    4           4           4             4              5             5
    //Minorversion    0           10          90            0              0             1
    ZeroMemory(@OSVer, sizeof(TOSVersionInfo));
    OSVer.dwOSVersionInfoSize := sizeof(TOSVersionInfo);
    GetVersionEx(OSVer);
    ObjTypeNumberFile := 23; // ???
    if OSVer.dwMajorVersion <= 5 then
    begin
      if OSVer.dwMinorVersion = 1 then
        ObjTypeNumberFile := 28 //XP
      else
        ObjTypeNumberFile := 26; //2K
    end
    else if OSVer.dwMajorVersion >= 6 then
      ObjTypeNumberFile := 25; //VISTA

    // Get all handles
    HandlesInfo := GetInfoTable(SystemHandleInformation);
    try
      if HandlesInfo = nil then
        Exit;
      for r := 0 to HandlesInfo^.NumberOfHandles - 1 do
      begin
        begin
          // Process file handles only
          if HandlesInfo^.Information[r].ObjectTypeNumber = ObjTypeNumberFile then
          begin
            // Get process handle. Needed for DuplicateHandle
            ProcHandle := OpenProcess(PROCESS_ALL_ACCESS, false, HandlesInfo^.Information[r].ProcessId);
            if ProcHandle <> 0 then
            begin
              // Why?
              if DuplicateHandle(ProcHandle, HandlesInfo^.Information[r].Handle, GetCurrentProcess, @DupHandle, 0,
                False, DUPLICATE_SAME_ACCESS) then
              begin
                FileName := GetFileNameByHandle(DupHandle);
                CloseHandle(DupHandle);
              end
              else
                FileName := '';
              if FileName <> '' then
              begin
                if (pos(LowerCase(FilterStr), LowerCase(FileName)) > 0) or (FilterStr = '') then
                begin
                  if Assigned(CallBack) then
                  begin
                    CallBack(HandlesInfo^.Information[r].ProcessId, HandlesInfo^.Information[r].Handle, FileName)
                  end;
                end;
              end;
              CloseHandle(ProcHandle);
            end;
          end;
        end;
      end; // for HandlesInfo^.NumberOfHandles
    finally
      FreeMem(HandlesInfo);
    end;
  finally
    FreeLibrary(lib);
  end;
end;
An dieser Stelle:
Delphi-Quellcode:
// Process file handles only
          if HandlesInfo^.Information[r].ObjectTypeNumber = ObjTypeNumberFile then
müsste ich dann noch deinen Code einfügen:
Delphi-Quellcode:
// Spezielle Named Pipes machen Probleme bei der Abfrage. Diese Pipes haben
          // als Access Mask 0x12019F. Entsprechend werden nur Handles abgefragt, die
          // nicht 0x12019F als Access Mask haben.
          if HandleInformation^.GrantedAccess <> $12019F then
Richtig?


Alle Zeitangaben in WEZ +1. Es ist jetzt 02:16 Uhr.
Seite 3 von 4     123 4      

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 by Thomas Breitkreuz