Ver Mensaje Individual
  #12  
Antiguo 06-12-2008
Avatar de cHackAll
[cHackAll] cHackAll is offline
Baneado?
 
Registrado: oct 2006
Posts: 2.159
Reputación: 20
cHackAll Va por buen camino
Cita:
Empezado por felipe88 Ver Mensaje
...es la manera de evitar mover un documento cuando se trabaja en el; yo lo veo como una cuestión de seguridad para los datos... si guardaras algo no te dejaría. La pregunta es, ¿hasta que punto Windows permite mover un archivo, estando en uso? ... no se que piensan de esto...
Falso; pongamos un ejemplo practico, wmplayer (Windows Media Player) reproduce una canción; lee de un archivo multimedia y moverlo (en la anterior teoria), ocasionaría fallas inesperadas en el programa... sin embargo el archivo puede ser movido, y no solo eso, puede ser hasta eliminado (lo cual ocurrirá de forma "visible" cuando sea liberado su manejador)

Esto es posible porque se ha utilizado FILE_SHARE_DELETE al momento de abrir el archivo... que sucede? al ser borrado o eliminado el archivo los datos siguen allí intactos lo único que cambia son las entradas de ROOT o de MFT en el sistema de archivos.

Cita:
Empezado por dec Ver Mensaje
...Pero, si la aplicación que abre un archivo (y es lo normal) no lo abre de forma exclusiva, ya digo, puedo estar equivocado, pero, ¿cómo podría averiguarse que el archivo en cuestión está abierto?...
He visto el tema más de un par de veces y creo que es de interés...

El S.O. bloquea por alguna razón lógica un archivo, y es necesario forzar el acceso al mismo por cualquier motivo... para ello la mejor herramienta que puedo nombrar de la telaraña es "Unlocker" de Cedrick Collomb.

Por qué es tan eficaz dicha herramienta? sin ánimos de quitar el encanto y la excelente calidad del trabajo de Collomb, comentaré que dicha herramienta funciona basada en dos APIs (ObReferenceObjectByHandle & ObfDereferenceObject) las cuales a nivel de núcleo (S.O.) desbloquean los archivos a voluntad y de la mejor forma posible.

Lo anteriormente dicho es solo con fines informativos pues no tenemos el permiso del autor para crear una librería basada en su trabajo, pero si podemos apoyarnos en otras APIs que nos facilitaran el trabajo; adjunto un ejemplo que dará la idea de lo que digo:

Código Delphi [-]
program WhoUses; // by cHackAll

uses Windows;

function NtQuerySystemInformation(SystemInformationClass: Cardinal; SystemInformation: Pointer; SystemInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function NtQueryInformationFile(FileHandle: Cardinal; IoStatusBlock: PInt64; FileInformation: Pointer; FileInformationLength, FileInformationClass: Cardinal): Cardinal; stdcall external 'ntdll';
function NtQueryObject(ObjectHandle, ObjectInformationClass: Cardinal; ObjectInformation: Pointer; ObjectInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function NtQueryInformationProcess(ProcessHandle, ProcessInformationClass: Cardinal; ProcessInformation: Pointer; ProcessInformationLength: Cardinal; ReturnLength: PCardinal): Cardinal; stdcall external 'ntdll';
function GetProcessImageFileNameW(hProcess: Cardinal; lpImageFileName: PWideChar; nSize: Cardinal): Cardinal; stdcall external 'psapi';
function memcmp(lpBuffer1, lpBuffer2: PWideChar; Size: Cardinal): Integer; cdecl external 'ntdll';
function GetConsoleWindow: Cardinal; stdcall external 'kernel32';

var
 Buffer: array [0..1023] of WideChar;

function Thread(Handle: Cardinal): Cardinal; stdcall;
var IoStatusBlock: int64;
begin
 Result := NtQueryInformationFile(Handle, @IoStatusBlock, @Buffer, SizeOf(Buffer), 9);
end;

type
 TSystemHandleInformation = packed record
  uCount: Cardinal;
  Handles: array [0..0] of packed record
   uIdProcess: Cardinal;
   ObjectType,
   Flags: Byte;
   Handle: Word;
   pObject: Pointer;
   GrantedAccess: ACCESS_MASK;
  end;
 end;

var
 hToken, Size, Index, hProcess, hObject, hThread, hOutput: Cardinal;
 Info: ^TSystemHandleInformation;
 Drives: array ['A'..'Z'] of record
  cbSize: Cardinal;
  Volume: array [0..63] of WideChar;
 end;
 Drive: array [0..7] of Char = '@'#0':';

begin
 if OpenProcessToken($FFFFFFFF, TOKEN_ADJUST_PRIVILEGES, hToken) then
  AdjustTokenPrivileges(hToken, False, PTokenPrivileges(PChar(#1#0#0#0#20#0#0#0#0#0#0#0#2#0#0#0))^, 16, nil, PDWORD(0)^);

 repeat Inc(Drive[0]);
  with Drives[Drive[0]] do
   cbSize := QueryDosDeviceW(@Drive, @Volume, SizeOf(Volume)) * 2 - 4;
 until Drive[0] = 'Z';
 Drive[4] := '\';

 Size := SizeOf(TSystemHandleInformation);
 Info := Ptr(LocalAlloc(0, Size));
 NTQuerySystemInformation(16, Info, Size, @Size);
 LocalFree(Cardinal(Info));
 Info := Ptr(LocalAlloc(0, Size));
 NTQuerySystemInformation(16, Info, Size, nil);

 hOutput := 0;
 for Index := 0 to Info.uCount - 1 do
  with Info.Handles[Index] do
   begin
    hProcess := OpenProcess(PROCESS_DUP_HANDLE or PROCESS_QUERY_INFORMATION, True, Info.Handles[Index].uIdProcess);
    if hProcess = 0 then Continue;

    if DuplicateHandle(hProcess, Handle, $FFFFFFFF, @hObject, 0, True, 0) and
       (NtQueryObject(hObject, 2, @Buffer, SizeOf(Buffer), nil) = 0) and
       (lstrcmpW(@Buffer[48], 'File') = 0) then
     begin
      hThread := CreateThread(nil, 0, @Thread, Ptr(hObject), 0, PDWORD(0)^);
      if WaitForSingleObject(hThread, 666) = 0 then
       if (NtQueryObject(hObject, 1, @Buffer, SizeOf(Buffer), nil) = 0) then
        begin
         Drive[0] := 'A';
         while Drive[0] <= 'Z' do
          with Drives[Drive[0]] do
           if (cbSize <> 0) and (memcmp(@Buffer[4], @Volume, cbSize) = 0) then
            Break
           else
            Inc(Drive[0]);
         if Drive[0] > 'Z' then Continue;

         if hOutput = 0 then
          begin
           AllocConsole;
           hOutput := GetStdHandle(STD_OUTPUT_HANDLE);
           SetConsoleScreenBufferSize(hOutput, PCoord(PChar(#120#0#50#0))^);
           SetWindowPos(GetConsoleWindow, 0, 0, 0, $FFFF, 666, SWP_NOZORDER or SWP_NOMOVE);
          end;

         WriteLn(string(PWideChar(@Drive)) + string(PWideChar(@Buffer[5 + (Drives[Drive[0]].cbSize div 2)])));

         if GetProcessImageFileNameW(hProcess, @Buffer, SizeOf(Buffer)) <> 0 then
          begin
           Drive[0] := 'A';
           while Drive[0] <= 'Z' do
            with Drives[Drive[0]] do
             if (cbSize <> 0) and (memcmp(@Buffer, @Volume, cbSize) = 0) then
              Break
             else
              Inc(Drive[0]);
           if Drive[0] <= 'Z' then
            WriteLn(string(PWideChar(@Drive)) + string(PWideChar(@Buffer[Drives[Drive[0]].cbSize div 2 + 1])));
          end;
         WriteLn;
        end
       else
      else
       begin
        TerminateThread(hThread, 0);
        CloseHandle(hThread);
       end;
     end;
    CloseHandle(hProcess);
   end;

 LocalFree(Cardinal(Info));

 if hOutput <> 0 then
  ReadLn;
end.

La anterior aplicación de consola muestra todos los archivos abiertos y los programas que han abierto a dichos archivos y puede adaptarse para otros fines .

Es claro que no tiene el “poder” de Unlocker, pero es un precedente para aplicaciones a nivel de usuario que requieran de dichas funcionalidades.

Saludos
__________________
RTFM > STFW > Foro > Truco > Post > cHackAll > KeBugCheckEx
Responder Con Cita