this slowpoke moves

Unlock blocked Files

Wer sehr viel mit Windows arbeitet, hat bestimmt schon mal die Erfahrung gemacht, auf eine Datei zu stoßen, die vollkommen blockiert ist.

Sie lässt sich nicht verändern oder löschen und sogar nicht kopieren. 

Wohl möglich, dass der User des Systems nicht der Inhaber dieser Datei ist und der eigentliche Inhaber jeglichen Zugriff auf diese Datei verweigert. 

Das ist auf dem Windows-System möglich, denn selbst Microsoft hat Dateien, die für jeden User tabu sind.

Aber auch diese Dateien lassen sich vollkommen vom System trennen und den Zugriff ermöglichen.

Der folgende Code zeigt wie..
uses ShellApi, ComCtrls, tlHelp32

public
    procedure WMDropFiles(var Msg: Tmessage); message WM_DROPFILES;
    
type
  NTStatus = cardinal;

CONST
  STATUS_SUCCESS = NTStatus($00000000);
  STATUS_ACCESS_DENIED = NTStatus($C0000022);
  STATUS_INFO_LENGTH_MISMATCH = NTStatus($C0000004);
  SEVERITY_ERROR = NTStatus($C0000000);
  ObjectNameInformation = 1;

type
  PSYSTEM_HANDLE_INFORMATION = ^SYSTEM_HANDLE_INFORMATION;
  SYSTEM_HANDLE_INFORMATION = packed record
    ProcessId: dword;
    ObjectTypeNumber: byte;
    Flags: byte;
    Handle: word;
    pObject: pointer;
    GrantedAccess: dword;
  end;

  PSYSTEM_HANDLE_INFORMATION_EX = ^SYSTEM_HANDLE_INFORMATION_EX;
  SYSTEM_HANDLE_INFORMATION_EX = packed record
    NumberOfHandles: dword;
    Information: array [0 .. 0] of SYSTEM_HANDLE_INFORMATION;
  end;

type
  UNICODE_STRING = packed record
    Length: word;
    MaximumLength: word;
    Buffer: PWideChar;
  end;

type
  OBJECT_NAME_INFORMATION = record
    Name: UNICODE_STRING;

  end;

  PIO_STATUS_BLOCK = ^IO_STATUS_BLOCK;
  IO_STATUS_BLOCK = packed record
    Status: NTStatus;
    Information: dword;
  end;

  PFILE_NAME_INFORMATION = ^FILE_NAME_INFORMATION;
  FILE_NAME_INFORMATION = packed record
    FileNameLength: ULONG;
    FileName: array [0 .. MAX_PATH - 1] of WideChar;
  end;

type
  TInject = record
    del: pointer;
    FileName: dword;
  end;

function NtQueryInformationFile(FileHandle: THandle;
  IoStatusBlock: PIO_STATUS_BLOCK; FileInformation: pointer; Length: dword;
  FileInformationClass: dword): NTStatus; stdcall; external 'ntdll.dll';

Function NtQuerySystemInformation(ASystemInformationClass: dword;
  ASystemInformation: pointer; ASystemInformationLength: dword;
  AReturnLength: PCardinal): NTStatus; stdcall; external 'ntdll.dll';

function NtQueryObject(ObjectHandle, ObjectInformationClass: Integer;
  ObjectInformation: pointer; Length: Integer; var ResultLength: Integer)
  : Integer; stdcall; external 'ntdll.dll';
  
//

function InjectedCode(param: pointer): dword; stdcall;
var
  injected: TInject;
begin
  injected := TInject(param^);
  asm
    push injected.filename;
    call injected.del;
  end;
  Result := 0;
end;

procedure code_end;
begin
end;

procedure Unlock(PI: dword; hnd: dword);
var
  trad, mdh, task: THandle;
  dwCodeSize: dword;
  thead, btwn: dword;
  InjData: TInject;
  injdataaddr, writeaddr: pointer;
begin
  dwCodeSize := dword(@code_end) - dword(@InjectedCode);

  task := OpenProcess(PROCESS_ALL_ACCESS, false, PI);
  if task <> 0 then
  begin
    mdh := GetModuleHandle('kernel32.dll');
    InjData.del := GetProcAddress(mdh, 'CloseHandle');
    InjData.FileName := hnd;
    injdataaddr := VirtualAllocEx(task, nil, SizeOf(InjData), MEM_COMMIT,
      PAGE_READWRITE);
    WriteProcessMemory(task, injdataaddr, @InjData, SizeOf(InjData), btwn);
    writeaddr := VirtualAllocEx(task, nil, dwCodeSize, MEM_COMMIT,
      PAGE_EXECUTE_READWRITE);
    WriteProcessMemory(task, writeaddr, @InjectedCode, dwCodeSize, btwn);
    trad := CreateRemoteThread(task, nil, 0, writeaddr, injdataaddr, 0, thead);
    if trad <> 0 then
      ShowMessage('UNBLOCK!')
    else
      ShowMessage('Error :(');
  end;
end;

function GetHandleTable: pointer;
var
  memal: pointer;
  res: cardinal;
  sz: dword;
  actualsize: dword;
begin
  sz := $400;
  memal := VirtualAlloc(nil, sz, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  NtQuerySystemInformation(16, memal, sz, @actualsize);
  VirtualFree(memal, sz, MEM_RELEASE);
  sz := actualsize;
  memal := VirtualAlloc(nil, sz, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
  res := NtQuerySystemInformation(16, memal, sz, @actualsize);
  if res = STATUS_SUCCESS then
    Result := memal
  else
    Result := nil;
end;

function GetFileNameFromHandle(const hFile: THandle): string;
var
  IO_STATUSBLOCK: IO_STATUS_BLOCK;
  FileNameInfo: FILE_NAME_INFORMATION;
  szFile: String;
begin
  FillChar(FileNameInfo.FileName, SizeOf(FileNameInfo.FileName), 0);
  NtQueryInformationFile(hFile, @IO_STATUSBLOCK, @FileNameInfo, 500, 9);
  szFile := WideCharToString(FileNameInfo.FileName);
  Result := szFile;
end;

function GetNameFromPID(PID: dword): String;
var
  PE32: TProcessEntry32;
  snap: THandle;
  res: String;
begin
  PE32.dwSize := SizeOf(PE32);
  snap := CreateToolHelp32SnapShot(TH32CS_SNAPALL, 0);
  Process32First(snap, PE32);
  repeat
    if PE32.th32ProcessID = PID then
      res := PE32.szExeFile;
  until
  Process32Next(snap, PE32) = false;
  Result := res;
end;

procedure ListPids(srch: String);
var
  HandlesInfo: PSYSTEM_HANDLE_INFORMATION_EX;
  i: Integer;
  tmpHandle, phand, myHandle: THandle;
  szFl: String;
  lstItem: TListItem;
begin

  HandlesInfo := GetHandleTable;
  if HandlesInfo = nil then
    exit;
  for i := 0 to HandlesInfo^.NumberOfHandles - 1 do
    if HandlesInfo^.Information[i].ObjectTypeNumber = 28 then
    begin
      tmpHandle := HandlesInfo^.Information[i].Handle;
      phand := OpenProcess(PROCESS_DUP_HANDLE, false,
        HandlesInfo^.Information[i].ProcessId);
      if phand <> 0 then
      begin
        DuplicateHandle(phand, tmpHandle, GetCurrentProcess, @myHandle, 0,
          false, DUPLICATE_SAME_ACCESS);
        szFl := GetFileNameFromHandle(myHandle);
        if pos(srch, LowerCase(szFl)) > 0 then
        begin
          lstItem := Form1.ListView1.Items.Add;
          lstItem.Caption := IntToStr(HandlesInfo^.Information[i].ProcessId);
          lstItem.SubItems.Add
            (GetNameFromPID(HandlesInfo^.Information[i].ProcessId));
          lstItem.SubItems.Add(IntToStr(HandlesInfo^.Information[i].Handle));
        end;
        CloseHandle(myHandle);
      end;
    end;
  if Form1.ListView1.Items.Count = 0 then
  begin
    lstItem := Form1.ListView1.Items.Add;
    lstItem.Caption := ' - ';
    lstItem.SubItems.Add(' - ');
    lstItem.SubItems.Add(' - ');
  end;
end;

procedure TForm1.WMDropFiles(var Msg: Tmessage);
var
  buf: array [0 .. 255] of char;
  szF: String;
  icon: TIcon;
  icoindex: word;

begin
  ListView1.Items.Clear;
  DragQueryFile(THandle(Msg.WParam), 0, @buf, SizeOf(buf));
  szF := buf;
  Edit1.Text := szF;
  icon := TIcon.Create;
  icoindex := 0;
  icon.Handle := ExtractAssociatedIcon(Handle, Pchar(szF), icoindex);
  Image1.Picture.icon.Handle := icon.Handle;
  ListPids(ExtractFileName(LowerCase(szF)));

  DragFinish(THandle(Msg.WParam));
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DragAcceptFiles(Handle, true);
end;

procedure term(dwPI: dword);
var
  ph: THandle;
begin
  ph := OpenProcess(PROCESS_TERMINATE, false, dwPI);
  if TerminateProcess(ph, 0) = true then
    ShowMessage('Procesul :' + IntToStr(dwPI) + ' TERMINATE!')
  else
    ShowMessage('ERROR :(');
end;
Prozess Terminieren :
procedure TForm1.SpeedButton4Click(Sender: TObject);
var
  i: Integer;
  PID: dword;
begin
  for i := 0 to ListView1.Items.Count - 1 do
  begin
    try
      PID := StrToInt(ListView1.Items.Item[i].Caption);
      term(PID);
    except
      MessageDlg('You have no reason to unlocked', mtError, [mbOk], 0);
    end;
  end;
end;
Blockade aufheben :
procedure TForm1.SpeedButton2Click(Sender: TObject);
var
  i: Integer;
  PID: dword;
  target: THandle;
begin
  for i := 0 to ListView1.Items.Count - 1 do
  begin
    try
      PID := StrToInt(ListView1.Items.Item[i].Caption);
      target := StrToInt(ListView1.Items.Item[i].SubItems[1]);
      Unlock(PID, target);
    except
      MessageDlg('You have no reason to unlocked', mtError, [mbOk], 0);
    end;
  end;
end;
Datei löschen :
procedure TForm1.SpeedButton3Click(Sender: TObject);
var
  i: Integer;
  PID: dword;
  target: THandle;
begin
  for i := 0 to ListView1.Items.Count - 1 do
  begin
    try
      PID := StrToInt(ListView1.Items.Item[i].Caption);
      target := StrToInt(ListView1.Items.Item[i].SubItems[1]);
      Unlock(PID, target);
      Sleep(100);
      DeleteFile(Edit1.Text);
    except
      MessageDlg('You have no reason to unlocked', mtError, [mbOk], 0);
    end;
  end;
end;
Fazit :
Man sollte vorsichtig sein und genau wissen, ob es sich um eine Systemdatei handelt, um nicht einen System-Crash zu verursachen.

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate