Historia Safari sin History.plist

Regresé a partir de 7 días de entrenamiento a una pesadilla : los investigadores criminales impacientes arrancado un Macbook de Apple de «ver» lo que el dueño había estado haciendo en Internet en los días previos a un crimen. El portátil ha estado en pruebas durante más de un año, pero nunca examinados (no se hizo ninguna solicitud de examen), y el juicio se avecina. Un cambio en la súplica acusados ​​menos de dos semanas antes del juicio requería un examen, pero no hay examinadores calificados estaban disponibles de inmediato. Así, alguien pensó que era una buena idea sólo para arrancar el Macbook y echar un vistazo alrededor />.
Safari, decidió que la Historia . plist era vieja herramienta y creó una nueva con los sitios web que los investigadores trataron de visitar – al parecer de marcadores. Por lo tanto, me enfrenté a tratar de determinar un historial de navegación en ausencia de la History.plist relevante.

Asumiendo el viejo History.plist no se ha sobrescrito, tallando 500gb para un plist no era una buena opción en la cantidad de tiempo que tenía que hacer el trabajo. Yo era consciente de los exámenes anteriores que Safari mantiene elementos de la página web en una base de datos SQLite llamado cache.db. Se encuentra en «/ Users / / Library / Caches / com.apple.Safari «. Usted puede estar familiarizado con la ubicación, ya que es el hogar de un directorio llamado «Página Web» Avances en la que se almacenan las imágenes JPEG de las páginas web visitadas

El cache.db contiene cuatro tablas:. Cfurl_cache_schema_version , cfurl_cache_response, sqlite_sequence, cfurl_cache_blob_data. Los cuadros relevantes a esta discusión son cfurl_cache_response y cfurl_cache_blob_data, que me referiré como respuesta y Blob para facilitar la discusión. No voy a tratar de describir todos los elementos de estas tablas, sólo los que yo elegí para poner en práctica mi solución

la tabla de respuesta La tabla de respuesta tiene el siguiente esquema:.

CREAR cfurl_cache_response MESA (
entry_id INTEGER PRIMARY KEY autoincrement UNIQUE,
Versión INTEGER, INTEGER hash_value, />
TEXTO request_key UNIQUE,
indicación_horaria NOT NULL DEFAULT CURRENT_TIMESTAMP)

El request_key campo contiene la dirección URL del elemento de página web (html, imágenes, flash, javascript , css, etc.) Indicación_horaria El campo se encuentra en un lenguaje sencillo (aaaa-mm-dd hh: mm: ss) y no requiere la conversión de un tiempo época. El entry_id es un entero único que se relaciona directamente con los datos de la tabla con un Blob entry_id correspondiente .

La tabla BLOB

La tabla Blob tiene el siguiente esquema:

CREAR cfurl_cache_blob_data MESA (
entry_id INTEGER PRIMARY KEY,
; BLOB response_object, BLOB request_object, />
proto_props BLOB,
USER_INFO BLOB)

El

receiver_data campo contiene el objeto descargado de la dirección URL en el cuadro de respuesta request_key . Response_object y receiver_data Los campos contienen XML que proporcionan metadatos sobre el receiver_data contenido. Y, de nuevo, la entry_id es un entero único para esta tabla que corresponde directamente un entry_id en la Tabla de respuestas.

Making History

La tabla de respuesta y la tabla de Blob tiene una correspondencia 1 a 1, es decir, hay el mismo número de registros en cada tabla. Respuesta entry_id 1 corresponde a Blob entry_id 1, y así sucesivamente. Sin embargo, no todos los registros de un interés para un historial de páginas web visitadas. La mayoría son elementos de las páginas web, y no el HTML que representa la página web.

Las direcciones URL en el cuadro de respuesta request_key de campo no nos ayudan mucho aquí: muchas páginas no terminan con «. html «. Un rápido vistazo a los resultados de búsqueda de Google se hará cargo de esto. Por lo tanto, no podemos filtrar las URLs de una manera significativa. Podríamos tratar de excluir a ciertos objetos, como. Jpg,. Gif,. Js,. Css,. Swf, etc, pero esto es difícil y no es confiable.

me decidí por el filtrado de la tabla Blob receiver_data el contenido de la etiqueta HTML que representa una página web (o al menos contenido HTML). La consulta utiliza un «natural join» sintaxis que se casa a las tablas en el campo entry_id y sólo devuelve los registros que tienen el principal «» la etiqueta:

sqlite3-header cache.db» seleccione r.entry_ID, indicación_horaria, request_key de cfurl_cache_blob_data c, cfurl_cache_response r donde c.entry_id = r.entry_id y receiver_data como « % » «

La consulta anterior reduce una base de datos que contiene 6.700 elementos en 187 páginas. Amplié esto a cualquier elemento con una etiqueta HTML, en el caso de páginas manipuladas, mediante la colocación de un comodín que lleva antes de la etiqueta:

# sqlite3-header cache.db» seleccione r.entry_ID, indicación_horaria, request_key de cfurl_cache_blob_data c, cfurl_cache_response r donde c.entry_id = r.entry_id y receiver_data como ‘% % ‘»

Al añadir el comodín líder, mi historia aumentado a 261 registros. Puedo redirigir la salida a un archivo para su análisis, y puedo modificar la consulta para exportar realmente los datos en el campo receiver_data para ver el contenido real de las páginas de interés.

EDITAR :
Mejor aún, ya que los encabezados de archivos pueden muy en documentos HTML (piense «doctype» cuerdas), es la búsqueda de la etiqueta de pie de página HTML «/ html» (corchetes excluyen intencionalmente):
Courier New, Courier, monospace; font-size: x-small;»> sqlite3-header cache.db «seleccione r.entry_ID, indicación_horaria, request_key de cfurl_cache_blob_data c, cfurl_cache_response r donde c.entry_id = r.entry_id y receiver_data como ‘% / html%’ «

Por lo que permite una cadena de encabezado variables, mi historia HTML aumentó a 328 registros . Ya que he escrito una utilidad para exportar los archivos en el cache.db y he comprobado los archivos por tipo mime: hubo 349 archivos html detectados. Espero reconciliar esto en el futuro próximo.

Making Sense

No puedo tomar el tiempo para romper las consultas en este momento, pero me gustaría destacar una expresión que puede no ser familiar para los usuarios casuales sqlite:

sqlite3-header cache.db» seleccione r.entry_ID, indicación_horaria, request_key de cfurl_cache_blob_data c, cfurl_cache_response r , donde c.entry_id = r.entry_id y receiver_data como « % ‘»

En la parte resaltada anteriormente, enumero los dos tablas que son objeto de la consulta. El arrastre «c» y «r» detrás de los nombres completos de tabla son alias para los nombres completos. Los alias de ahorrar un montón de escribir, y se los ve de empleados en la cláusula select, que narra sqlite que entry_id deseo (ya que existe en ambas tablas) y en la cláusula where.

Si alguien tiene otra idea sobre cómo realizar esta tarea o es consciente de las deficiencias de este enfoque, por favor comente. Después de todo, yo estoy tratando de hacer limonada de los limones me han dado …

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *