Autor
|
Tema: Interceptar borrado de archivo (Leído 8,569 veces)
|
alicia19es
Desconectado
Mensajes: 7
|
Hola a todos, estoy dando los ultimos toques a una aplicación realizada en vb.net. La aplicación detecta la introducción de usb en el pc y realiza una copia en el disco de archivos segun unos filtros determinados, comprobando previamente que ya no exista mediante codificacion md5. Pero quiero ir un poco más allá, y he pensado en que se realice una copia del fichero que el usuario intente eliminar, ya que esta eliminacion puede deberse a dos motivos: - 1. A que el archivo no le valga
- 2. Que el archivo sea digámoslo "comprometido" y le interese eliminarlo
He estado haciendo pruebas con el systemfilewatcher, pero solo detecta los eventos una vez producidos, por lo que cuando intento copiar el archivo, este ya no existe. La pregunta es, ¿Existe alguna forma de interceptar ese intento de borrado para realizar una copia previa de dicho archivo? Gracias.
|
|
|
En línea
|
|
|
|
alicia19es
Desconectado
Mensajes: 7
|
Bueno, no consigo encontrar nada por ahí referente al tema. Pienso que quizás podría intentar algo como capturar el proceso y los argumentos que utiliza Windows cuando recibe la orden de borrado de archivos. Pero ¿como se llama ese proceso?¿Cómo interceptarlo?, etc... Si alguien tiene alguna idea, por favor, que lo postee. Gracias y saludos
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
No es nada facil, debes crear o bien un Hook Global ( API Hook), o bien un driver ( File System Filter Driver). La función (indocumentada) NtSetFileInformation de la WinAPI es llamada para eliminar un archivo, con la estructura FileDispositionInformation , aunque también debes mirar la función DeleteFile, y no se si habrá otras, y luego está el uso de la interface ICopyHook que exclusívamente previene de la eliminación mediante la Shell. Para intentar hookear la API puedes utilizar la librería Deviare, o EasyHook, mhook (c++), u otras. Hay varios ejemplos en Google tanto para VBNET como C#, aunque parece que todas las librerías tienen sus desventajas y bugs. EDITO: En este ejemplo puedes hacerte una idea del modo de empleo de Easyhook junto a lo necesario para hookear dicha functión NtSetFileInformation. Saludos.
|
|
« Última modificación: 28 Diciembre 2013, 15:10 pm por ElektroSoft »
|
En línea
|
|
|
|
ThinkByYourself
Desconectado
Mensajes: 191
|
Puedes hacerloo bien... o puedes buscar el camino corto.
No sé si se podrá pero a lo mejor puedes listar (en un bucle infinito) los ficheros del directorio que se supone que tiene que guardar lo que haya en el usb, y cuando se liste algo diferente que nada PUM!!!!!!!! Bacap al canto, cifrado y ocultamiento. Dime si te sirve, no sería la primera vez que lo he pensado! Un saludo!
|
|
|
En línea
|
No te voy a engañar. Todos hemos sido programados para normalizar la psicopatía de las élites económicas y políticas, y para realimentar su patrón de ciega codicia.
|
|
|
alicia19es
Desconectado
Mensajes: 7
|
Muchas gracias a los dos. En principio quiero hacerlo bien, pero me parece Elektrosoft que eso puede sobrepasar mi nivel de conocimientos. De todas formas lo miraré. Una pregunta: ¿Con kernel.dll y user32.dll no podría conseguir algo? Por ejemplo con las deletefile, etc...? Gracias
|
|
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
user32.dll ... deletefile ... Esa es precísamente una de las funciones que nombré: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363915%28v=vs.85%29.aspxIguálmente deberías hookear esa función para interceptar cuando el SO llama a la función, pero ya puestos mejor prueba con NtSetFileInformation (se encuentra en la ntdll.dll) porque según he leido es la función por la que pasa cualquier método de eliminación (y otros), aunque está indocumentada así que mucha información no tengo, pero DeleteFile ahora que lo leo la documentación es posible que no tenga nada que ver con tu propósito puesto que no tiene parámetros para enviar a la papelera, es una función que debe estar limitada a la Shell (supongo). Saludos
|
|
« Última modificación: 28 Diciembre 2013, 19:51 pm por ElektroSoft »
|
En línea
|
|
|
|
alicia19es
Desconectado
Mensajes: 7
|
Hola ElectroSoft, gracias por la ayuda. En principio voy a descartar el hacerlo mediante la interface ICopiHook y el DeleteFile del kernel.dll, ya que si solo intercepta el borrado mediante shell, pues creo que no me vale. Mi intención es que intecepte los eventos habituales de un borrado de archivo, seleccionarlo y pulsa la tecla suprimir, quizás se pueda inteceptar esas pulsaciones y actuar en consecuencia, aunque tendría que realizar un bucle infinito, algo que no me gusta demasiado. He estado un par de hora investigando sobre la función NtSetFileInformation, pero la verdad es que hay bien poco. Alguna orientación más que me puedas dar. Tus consejos son bienvenidos, gracias a ellos voy viendo por donde tirar. Saludos y gracias de nuevo.
He localizado este enlace donde se puede extraer alguna informacion, ahora es necesario descifrarlo http://undocumented.ntinternals.net/UserMode/Undocumented%20Functions/NT%20Objects/File/NtDeleteFile.html [MOD]: No hagas doble post, utiliza el botón 'MODIFICAR'.
|
|
« Última modificación: 29 Diciembre 2013, 02:04 am por ElektroSoft »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
No se si te das cuenta de la cantidad de conocimientos que se requieren para llevar a cabo esta tarea, además de la experiencia en intentos fallidos, si ...porque hookear APIS es lo que tiene, que por alguna chorrada insignificante un hook puede ir perféctamente en Windows XP, pero no funcionar en otra versión de Windows, y lo mismo con las arquitecturas, además entre las diferentes versiones de windows pueden modificar los parámetros de "X" funciones. Fíjate si es dificil que resulta necesario utilizar librerías de terceros para realizar estos hooks de forma decente los cuales ya se encargan de inyectar y etc... Este campo no lo he tocado prácticamente nada, no vayas a pensar que soy un experto en el tema, los únicos hooks que he realizado han sido de bajo nivel con las funciones que la WinAPI proporciona para instalar los hooks, pero a lo que voy ...implementar ICopyHook sería una manera más limpia (y estable) sin necesidad de Hookear, y te permitiria tener control sobre los archivos eliminados desde el Explorer, pero sigue siendo una pesadilla llevarlo a cabo. Ahora bien, hay otra alternativa mucho más facil que se me ha ocurrido, sirviéndote del FileSystemWatcher. No pongo la mano en el fuego de haberlo dejado 100% efectivo, deberías testear en profundidad lo que sucede cuando eliminas dos archivos/carpetas con el mismo nombre pero con distinta fecha de modificación para comprobar si se restaura la que se debe restaurar, yo solo te dejo la idea: EDITO: Para proceder a usar el siguiente código necesitas referenciar Microsoft Shell Controls And Automation. EDITO2: Le añadí un par de cosas más, y también lo documenté un poco mejor... Imports System.IO Imports Shell32 Public Class Test Private SH As New Shell Private RecycleBin As Folder = SH. NameSpace(ShellSpecialFolderConstants. ssfBITBUCKET) Private WithEvents FSW As New FileSystemWatcher Private Shadows Sub Load() _ Handles MyBase.Load ' Seteo las propiedades del objeto 'FileSystemWatcher'. With FSW .Path = "C:\Test" .IncludeSubdirectories = True .Filter = "*" .NotifyFilter = NotifyFilters.FileName Or NotifyFilters.DirectoryName .EnableRaisingEvents = True End With End Sub Private Sub OnItemDeleted(sender As FileSystemWatcher, e As FileSystemEventArgs) _ Handles FSW.Deleted ' Almacenamos una colección de los items de la papelera de reciclaje. ' Tanto archivos, carpetas, y accesos directos .lnk (que no se tratan como archivos ni carpetas), ' cuyo nombre sea el mismo nombre que el elemento que se acaba de eliminar. ' Y los ordenamos por su fecha de modificación. Dim DeletedItems As IEnumerable(Of FolderItem) = RecycleBin.Items.Cast(Of FolderItem). Where(Function(Item) Item.Name = e.Name). OrderBy(Function(Item) Item.ModifyDate) ' Si hubiera más de un elemento con el mismo nombre, ' seleccionamos el último elemento que se eliminó (o al menos, eso se supone que debería suceder.) Dim LastDeletedItem As Shell32.FolderItem = DeletedItems.LastOrDefault If LastDeletedItem IsNot Nothing Then ' Esto es un simple checkeo por prevención, ' considero que solo hay un 0,00001% de posibilidades de que se de la condición... ' Esto podría deberse a que el usuario haya desecho manuálmente la acción de borrado (CTRL+Z), ' en un tiempo menor del que la aplicación ha procesado los elementos de la papelera. ' ' También está el caso de las incontrolables acciones de terceros, ' Como por ejemplo el editor de texto 'Sublime Text', que al modificar un archivo, ' lo elimina dando un falso positivo. If (LastDeletedItem.IsFolder AndAlso Directory.Exists(e.FullPath)) _ OrElse (Not LastDeletedItem. IsFolder AndAlso File. Exists(e. FullPath)) Then Throw New Exception(String.Format("¿ El elemento ha sido restaurado ?: {0}", e.FullPath)) Exit Sub End If ' Invocamos el verbo "undelete" para deshacer la acción de borrado sin necesidad de escribir más isntrucciones. ' Otros verbos que se pueden usar por ejemplo "delete" para eliminar el elemento de forma permanente, ' u "open" para abrir las propiedades del elemento. LastDeletedItem.InvokeVerb("undelete") ' O bien hacemos otra cosa distinta, como por ejemplo un backup del archivo/directorio eliminado... ' 'Dim BackupPath = String.Format("C:\Backup\{0}", e.Name) ' 'Select Case LastDeletedItem.IsFolder ' ' Case True ' FileIO.FileSystem.CopyDirectory(LastDeletedItem.Path, BackupPath, ' FileIO.UIOption.AllDialogs, FileIO.UICancelOption.ThrowException) ' ' Case False ' FileIO.FileSystem.CopyFile(LastDeletedItem.Path, BackupPath, ' FileIO.UIOption.AllDialogs, FileIO.UICancelOption.ThrowException) ' 'End Select End If End Sub End Class
Saludos
|
|
« Última modificación: 29 Diciembre 2013, 02:23 am por ElektroSoft »
|
En línea
|
|
|
|
alicia19es
Desconectado
Mensajes: 7
|
ElectroZoider (¿Te has cambiado el nick?, te has salido. Vaya tela, la clase que me acabas de ofrecer. Voy a analizarla un poco y ya te cuento. De verdad muchas gracias. Yo no tengo ese nivel todavía, algunas cosas se me escapan, sobre todo a la hora de buscar las declaraciones correctas, funciones de las namespaces, tipo de atributos segun su estructura.... En fin poco a poco voy aprendiendo con gente como tú. Muchas gracias, en cuanto lo pruebe te lo comento.
----------------------------------------------------------------------------- Ya he hecho las comprobaciones. Me da error en la declaración que realizas en la línea 38: Dim LastDeletedItem As Shell32.FolderItem = DeletedItems.LastOrDefault me dice:
'LastOrDefault' no es un miembro de 'System.Collections.Generic.IEnumerable(Of Shell32.FolderItem)'.
y si le doy a ignorar errores y lo ejecuto, una vez elimino un archivo se rompe el programa mostrándome lo siguiente:
No se controló MissingMemberException No se encuentra el miembro público 'Cast' en el tipo 'FolderItems3'.
Alguna idea del porqué? Saludos y gracias.
|
|
« Última modificación: 29 Diciembre 2013, 16:14 pm por alicia19es »
|
En línea
|
|
|
|
Eleкtro
Ex-Staff
Desconectado
Mensajes: 9.878
|
No se controló MissingMemberException No se encuentra el miembro público 'Cast' en el tipo 'FolderItems3'.
Alguna idea del porqué? Saludos y gracias. En el código de arriba utilizo algunos métodos de LINQ (.Cast, .Last), para utilizarlos es necesario utilizar la versión Framework 3.5 como mínimo, entonces tienes que actualizar la versión del objetivo de Framework en las propiedades de tu proyecto e importa LINQ: Imports System.Linq
http://msdn.microsoft.com/en-us/library/system.linq.enumerable_methods%28v=vs.100%29.aspx
ElectroZoider (¿Te has cambiado el nick?). Si jeje, es posible que me vuelva a cambiar de nick antes de acabar el añoSaludos
|
|
|
En línea
|
|
|
|
|
|