Sprawdzenie z jakiego pliku korzysta obcy proces.

0

Witam
Aplikacja x otwiera jakiś plik dbf. W jaki sposób po uchwyceniu aplikacji mogę uzyskać informacje z jakiego pliku w danej chwili aplikacja korzysta

0

Jeżeli aplikacja nie korzysta z obsługi DDE ani nie podaje tej nazwy w pasku tytułowym, to spróbował bym wyciągnąć to z pamięci tegoż procesu. Ewentualnie injekcja dllki lub spoofnięcie, którejś z wykorzystywanych systemowych. A w samym kodzie hook na funkcje otwierania plików przez systemowe Open dialogi o ile tak otwiera się tam pliki. Można też próbować odczytać parametry z jakimi został wywołany proces. Ale może nie być tam pełnej ścieżki do pliku. Chociaż podejrzewam, że są pewnie jakieś funkcje, może nawet WinAPI. Skoro są watchery do sprawdzania zmian w katalogu. Ewentualnie pogoogluj pytając o rozwiązania, któruch mogą używać programy unlockujące dostęp do pliku czy katalogu.

EDIT: No niestety rozwiązania w drugą stronę czyli pid na podstawie nazwy pliku znajduje się od ręki. A w drugą stronę ciężko. O ile nikt nie doradzi nic lepszego ja przeszukiwał bym jednak pamięć procesu.

5

Wypociłem, częściowo znalazłem w Google jak pobrać listę otwartych plików na podstawie ścieżki i nazwy procesu, kod był testowany tylko na Delphi 7 więc nie wiem jak będzie działał na nowszych z Unicode ale to na pewno łatwo będzie dostosować gdyby coś:

uses PsApi;

const
  KERNEL32 = 'kernel32.dll';
  NTDLL    = 'NTDLL.dll';
  QUERY_FULL_PROCESS_IMAGE_NAME = 'QueryFullProcessImageNameA';
  NT_QUERY_SYSTEM_INFORMATION   = 'NtQuerySystemInformation';
  NT_QUERY_OBJECT               = 'NtQueryObject';

  STATUS_SUCCESS                = $000000;
  STATUS_BUFFER_OVERFLOW        = $80000005;
  STATUS_INFO_LENGTH_MISMATCH   = $C0000004;

  DefaultBUFFERSIZE             = $100000;
  SYSTEM_HANDLE_INFO            = $00000010;
  DUPLICATE_CLOSE_SOURCE        = $00000001;
  DUPLICATE_SAME_ACCESS         = $00000002;

type
  OBJECT_INFORMATION_CLASS = (ObjectBasicInformation,ObjectNameInformation,
        ObjectTypeInformation,ObjectAllTypesInformation,ObjectHandleInformation);

  SYSTEM_HANDLE = packed record
    uIdProcess: ULONG;
    ObjectType: UCHAR;
    Flags: UCHAR;
    Handle: Word;
    pObject: Pointer;
    GrantedAccess: ACCESS_MASK;
  end;

  PSYSTEM_HANDLE      = ^SYSTEM_HANDLE;
  SYSTEM_HANDLE_ARRAY = Array[0..0] of SYSTEM_HANDLE;
  PSYSTEM_HANDLE_ARRAY = ^SYSTEM_HANDLE_ARRAY;

  SYSTEM_HANDLE_INFORMATION = packed record
    uCount: ULONG;
    Handles: SYSTEM_HANDLE_ARRAY;
  end;

  PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;

  UNICODE_STRING=packed record
    Length       :Word;
    MaximumLength:Word;
    Buffer       :PWideChar;
  end;

  OBJECT_NAME_INFORMATION = UNICODE_STRING;
  POBJECT_NAME_INFORMATION = ^OBJECT_NAME_INFORMATION;


  function QueryFullProcessImageName(hProcess: Thandle; dwFlags: DWORD;
        lpExeName: PChar; nSize: PDWORD): BOOL; stdcall; external KERNEL32
        name QUERY_FULL_PROCESS_IMAGE_NAME;
  function NtQuerySystemInformation(SystemInformationClass:DWORD;
        SystemInformation:pointer; SystemInformationLength:DWORD;
        ReturnLength:PDWORD):THandle; stdcall; external NTDLL name
        NT_QUERY_SYSTEM_INFORMATION;
  function NtQueryObject(ObjectHandle:cardinal;
        ObjectInformationClass:OBJECT_INFORMATION_CLASS; ObjectInformation:Pointer;
        Length:ULONG;ResultLength:PDWORD):THandle;stdcall; external NTDLL name
        NT_QUERY_OBJECT;

procedure EnumerateDevicePaths(const ADeviceNames, ADevicePaths: TStringList);
var
  drives     : array[0..4095] of Char;
  pdrive     : PChar;
  drive      : String;
  drive_path : array[0..4095] of Char;
  sdrive_path: String;
begin
  ADeviceNames.Clear;
  ADevicePaths.Clear;

  if GetLogicalDriveStrings(SizeOf(drives), drives) = 0 then
    Exit;

  pdrive := drives;
  while pdrive^ <> #0 do
  begin
    drive := Copy(pdrive, 0, 4);
    if drive <> '' then
    begin
      if drive[Length(drive)] = '\' then
        Delete(drive, Length(drive), 1);

      QueryDosDevice(PChar(drive), drive_path, SizeOf(drive_path));
      sdrive_path := drive_path;

      ADeviceNames.Add(drive);
      ADevicePaths.Add(sdrive_path);
    end;
    Inc(pdrive, 4);
  end;
end;

function GetProcessPathFromPID(const PID: Cardinal): string;
var
  hProcess: THandle;
  buff: array[0..MAX_PATH - 1] of Char;
  cSize: Cardinal;
begin
  result:= '';
  ZeroMemory(@buff, MAX_PATH);
  cSize:= SizeOf(buff);
  hProcess:= OpenProcess(PROCESS_QUERY_INFORMATION or PROCESS_VM_READ, False, PID);
  if (hProcess <> INVALID_HANDLE_VALUE) then
  begin
    if QueryFullProcessImageName(hProcess, 0, buff, @cSize) then
      result:= buff;
    CloseHandle(hProcess);
  end;
end;


function GetObjectInfo(hObject:cardinal; objInfoClass:OBJECT_INFORMATION_CLASS):LPWSTR;
var
 pObjectInfo: POBJECT_NAME_INFORMATION;
 HDummy     :THandle;
 dwSize     :DWORD;
begin
  Result:=nil;
  dwSize:= sizeof(OBJECT_NAME_INFORMATION);
  pObjectInfo:= AllocMem(dwSize);
  HDummy:= NTQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, @dwSize);

  if((HDummy = STATUS_BUFFER_OVERFLOW) or (HDummy = STATUS_INFO_LENGTH_MISMATCH)) then
  begin
    //ReallocMem(pObjectInfo, dwSize); //nie wiem czemu nie dziala trzeba zwolnic i od nowa alokowac :/
    FreeMem(pObjectInfo);
    pObjectInfo := AllocMem(dwSize);
    HDummy:= NTQueryObject(hObject, objInfoClass, pObjectInfo, dwSize, @dwSize);
  end;

  if((HDummy = STATUS_SUCCESS) and (pObjectInfo.Buffer <> nil)) then
  begin
    Result:= AllocMem(pObjectInfo.Length + sizeof(WCHAR));
    CopyMemory(result, pObjectInfo.Buffer, pObjectInfo.Length);
  end;
  FreeMem(pObjectInfo);
end;

procedure EnumerateOpenFiles(AFullProcessPath: string; const AFilesList: TStrings);
var
  pHandlesInfo: PSYSTEM_HANDLE_INFORMATION;
  pHandleInfo: PSYSTEM_HANDLE;
  slDeviceNames, slDevicePaths: TStringList;
  hProcess, hProcessDup: THandle;
  FileName: String;
  ResultLength: Cardinal;
  BufferSize: Cardinal;
  i, j: Integer;
begin
  AFilesList.Clear;
  slDeviceNames:= TStringList.Create;
  slDevicePaths:= TStringList.Create;
  try
    EnumerateDevicePaths(slDeviceNames, slDevicePaths);
    BufferSize:= DefaultBUFFERSIZE;
    pHandlesInfo:= AllocMem(BufferSize);
    try
      if NTQuerySystemInformation(Dword(SYSTEM_HANDLE_INFO), pHandlesInfo,
              BufferSize, @ResultLength) = STATUS_SUCCESS then
      begin
        for i:=0 to pHandlesInfo^.uCount -1 do
        begin
          pHandleInfo:= Pointer(Integer(@pHandlesInfo^.Handles) + i * SizeOf(SYSTEM_HANDLE));

          if (pHandleInfo^.ObjectType <> 28) or
               (pHandleInfo^.GrantedAccess = $0012019F) or
               (pHandleInfo^.GrantedAccess = $001A019F) or
               (pHandleInfo^.GrantedAccess = $00120189) then
            Continue;

          if SameText(AFullProcessPath,
                  GetProcessPathFromPID(pHandlesInfo.Handles[i].uIdProcess)) then
          begin
            hProcess:= OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION
                  or PROCESS_VM_READ, False, pHandlesInfo.Handles[i].uIdProcess);
            if (hProcess <> INVALID_HANDLE_VALUE) then
            begin
              if DuplicateHandle(hProcess, pHandlesInfo.Handles[i].Handle,
                  GetCurrentProcess(), @hProcessDup, STANDARD_RIGHTS_REQUIRED,
                  False, DUPLICATE_SAME_ACCESS) then
              begin
                FileName:= GetObjectInfo(hProcessDup, ObjectNameInformation);
                CloseHandle(hProcessDup);

                for j:= 0 to slDevicePaths.Count - 1 do
                  if Copy(FileName, 1, Length(slDevicePaths[j])) = slDevicePaths[j] then
                  begin
                    Delete(FileName, 1, Length(slDevicePaths[j]));
                    FileName:= slDeviceNames[j] + FileName;
                    break;
                  end;

                if (Length(FileName) > 0) then
                  AFilesList.Add(FileName);;
              end;
              CloseHandle(hProcess);
            end;
          end;
        end;
      end;
    finally
      FreeMem(pHandlesInfo, BufferSize);
    end;
  finally
    slDeviceNames.Free;
    slDevicePaths.Free;
  end;
end;

Przykład użycia:

EnumerateOpenFiles('c:\Program Files (x86)\VideoLAN\VLC\vlc.exe', Memo1.Lines);

Uwaga: Część aplikacji choćby głupi notatnik z Windows nie trzyma cały otwartych plików a jedynie podczas odczytu i zapisu więc nie należy się tym sugerować że niby nie działa.

PS: Kod trochę taki niedbały, brak spójności formatowania i nazywania zmiennych ale jak pisałem część jest moja a część kopiuj/wklej z Google a nie chciało mi się tego poprawiać.

0

A Ci którzy mają starego, poczciwego XP, zamiast:

if QueryFullProcessImageName(hProcess, 0, buff, @cSize) then

niech użyją

if GetModuleFileNameEx(hProcess, 0, buff, cSize) > 0 then

1 użytkowników online, w tym zalogowanych: 0, gości: 1