Me puse en contacto con un colega que necesitaba un poco de ayuda el análisis de una base de datos SQLite. Fue la base de datos myspace.messaging.database # ubicada en el » Users
los desafíos de SQLite
Seamos realistas: SQLite está en todas partes. La comprensión es esencial para los buenos exámenes, y una gran parte de esa comprensión viene de aprender las instrucciones SQL. Hay muchas fuentes en línea buenos para aprender SQL, y uno de mis favoritos es w3schools.comPero, para los médicos forenses digitales, hay otro desafío más allá de comandos SQL comprensión -. Entender la construcción y relaciones de las tablas. SQLite es un relacional de base de datos, y las mesas están destinados a ser relacionados entre sí para producir un resultado no es posible o práctico de una sola tabla. Saber cómo se pretendía la tabla a utilizar puede ser muy difícil … después de todo, una base de datos SQLite es más parecido a un gabinete de archivos, no una secretaria que utiliza el archivo de gabinete.
Por ejemplo, el secretario puede colocar registros bancarios de la compañía en un archivo llamado «registros financieros» o ella puede ponerlos en un archivo llamado «Alcachofas». Realmente no importa, porque ella sabe lo que pasa en el archivo. Alguien que viene detrás de ella no tendrá mucho problema para encontrar los registros de los bancos en el archivo de registros financieros, pero podría pasar por alto por completo en el archivo de alcachofas. El punto es, sin el secretario, que podría ser muy difícil de entender el sistema de archivo.
Bases de datos SQLite pueden ser muy parecido a eso. Se puede ver la estructura o el esquema como se le llama, con mucha facilidad. Pero lo que no se entiende tan fácilmente es cómo se destina el dispositivo a utilizar. Ese misterio es por lo general encerrado en la aplicación que utiliza la base de datos, pero no se explica en la propia base de datos.
Conseguir una pista h2> Para estar seguros, no puede ser pistas sobre cómo las tablas de una base de datos se relacionan entre sí. Los nombres de tabla y de campo hablan volúmenes. Una base de datos llamada «AddressBook.db» con dos tablas llamadas «Nombres» y «Direcciones» que tienen un campo en común que se llama «SubjectID» no es demasiado difícil de entender. Si tenemos la suerte de poder ejecutar la aplicación que utiliza la base de datos y probar nuestras inferencias sobre la base de la salida de solicitudes, nuestra confianza crece (y nuestra comprensión, si es compatible con el resultado, podría ahora ser considerado fiable).
Mis pistas favoritas por el momento son sentencias SQL ‘Ver’. Estas son tablas virtuales que dibujan sus datos de otras tablas de la base de datos (o una base de datos adjunta). Mediante el estudio de una declaración vista, se obtiene una visión del creador de base de datos de cómo se pretendía la base de datos que se utilizará … al menos en uno de capacidad. Piense en una vista como una macro: se ahorra al usuario la molestia de la base de datos repetidos escribir una consulta de uso frecuente. Y, si la consulta se utiliza con frecuencia, entonces usted tiene una buena idea de cómo se pretendía la base de datos que se utilizará.
¿Qué si no hay pistas?
¿Qué pasa con las circunstancias en las que no hay pistas en la base de datos para ayudar a comprender su uso. Bueno, si hay realidad no hay pistas, entonces la única respuesta segura es nos fijamos en los datos plana, es decir, nos fijamos en las tablas de forma individual y no nos relacionamos ellos de ninguna manera. Pero, a menudo hay pistas menos obvias que pueden revelar una relación subyacente … lo que me lleva al punto de este artículo.
Filas latentes
examinadores de huellas latentes conocen el término «latente» significa oculto o invisible. Huellas dactilares latentes deben ser reveladas a ser visto por algún método externo, como polvo de huellas dactilares. Tablas de SQLite tienen un campo latente, por así decirlo. Y, podemos revelarla para ayudar a formar relaciones en una base de datos SQLite />.
Considere la base de datos # myspace.messaging.database he mencionado en el párrafo abierta. Cuenta con el siguiente esquema:
CREATE TABLE AuthorData_content (c0AuthorDisplayName , c1AuthorUserName);
CREAR TABLA AuthorData_segdir ( entero nivel, idx entero, número entero start_block, entero leaves_end_block, entero end_block, gota raíz, clave primaria (nivel, idx));
CREAR AuthorData_segments DE MESA (bloque blob);
CREATE TABLE AuthorMetaData (AuthorId INTEGER PRIMARY KEY, AuthorImageUrl TEXT);
CREATE TABLE MessageData virtual usando fts2 (asunto, cuerpo);
CREAR TABLA MessageData_content (c0Subject, c1Body);
CREATE TABLE MessageData_segdir (entero nivel, idx entero, número entero start_block, leaves_end_block entero, entero end_block, gota raíz, clave primaria (nivel, idx));
CREAR MessageData_segments DE MESA (bloque blob);
CREAR MessageMetaData DE MESA (IdMensaje INTEGER PRIMARY KEY, RecipientId INTEGER, INTEGER AuthorId, Carpeta INTEGER, INTEGER Estado, CreatedDate INTEGER);
CREAR UserSettings DE MESA (UserId INTEGER PRIMARY KEY, MachineID texto, entero Habilitado, marca_de_tiempo, LastSyncTimeStamp INTEGER, FirstRunIndexPass INTEGER, INTEGER FirstRunIndexTargetCount, OldestMessageId INTEGER, INTEGER LastServerTotalCount);
CREATE INDEX AuthorIdIndex EN MessageMetaData (AuthorId, RecipientId);
CREATE INDEX StatusIndex EN MessageMetaData (Estado, CreatedDate);
Ahora mira más de cerca en dos mesas de interés, MessageMetaData y MessageData_content:
CREAR MessageMetaData DE MESA (IdMensaje INTEGER PRIMARY KEY, RecipientId INTEGER, INTEGER AuthorId, Carpeta INTEGER, INTEGER Estado, CreatedDate INTEGER);
Al parecer, según los nombres de las tablas que MessageMetaData contiene información acerca de los mensajes, y MessageData_content contiene los mismos mensajes. Pero, ellos no comparten ningún campo que permiten las dos tablas que se relacionan. En otras palabras, que las filas de la tabla de metadatos corresponden a la fila de la tabla de contenido? ? Acaso ellos se corresponden en absoluto
$ sqlite3 myspace.messaging.database # database.db
$ sqlite3 myspace.messaging.database # database.db
1358
Ambos cuadros tener el mismo número de registros. Hmm, una pista? Es muy probable, sobre todo al estudio del contenido de la tabla y las tablas de contenido restante. De hecho la realización de un estudio similar, nos encontramos con otro grupo de la tabla de correspondencia:. AuthorMetaData y AuthorData_content también tienen el mismo número de registros (172, para ser exactos), pero no hay, campos interrelacionados obvias
A menos usted ha estudiado la construcción de SQLite en cualquier profundidad, es probable que no sepa que crea un campo de ‘rowid’ para cada mesa para que actúe como una clave principal. Si se crea una tabla con una clave principal definida, que la clave principal es sólo un alias a la rowid incorporado (con una excepción fuera del alcance de esta discusión). Pero el rowid no está representada en la tabla o esquema de la base, que es probablemente por eso que no sabía nada de él (al menos, no lo hice hasta que me compré un libro SQLite).
Conocer la existencia de la rowid, ahora puedo comprobar para ver si las dos tablas se emparejan campos ROWID:
$ sqlite3 myspace.messaging.database # database.db ‘select count (*) del MessageMetaData m, MessageData_content c donde m.rowid = c.rowid’
1358
No tenemos que confiar en el función de contar, echar un vistazo por ti mismo:
$ sqlite3 myspace . messaging.database # database.db ‘select m.rowid, c.rowid de MessageMetaData m, MessageData_content c donde m.rowid = c.rowid’
…
81407357 | 81407357
81416917 | 81416917
81504605 | 81504605
81505714 | 81505714
81530947 | 81530947
81569294 | 81569294
La prueba está en el pudín
sqlite> crear números de la tabla (entero dígitos);
sqlite> insertar en números de valores (dígitos) (1);
sqlite> insertar en números (dígitos) valores (2);
sqlite> Insertar en números valores (dígitos) (3);
sqlite> seleccione rowid, dígitos de los números;
1 | 1
2 | 2
3 | 3
4 | 3
sqlite> ; insertar en números (dígitos), ROWID valores (1000, 4);
sqlite> seleccione rowid, dígitos de los números;
1 | 1
2 | 2
3 | 3
4 | 3
1000 | 4
Uniendo todas las piezas
$ sqlite3-header myspace.messaging.database # database.db ‘select * from límite MessageMetaData 1;’
IdMensaje | RecipientId | AuthorId | Carpeta | Estado | CreatedDate
1289081 | 544962655 | 41265701 | 0 | 2 | 1280870820000
$ sqlite3-header myspace.messaging.database # database.db ‘select * from límite MessageData_content 1;’
c0Subject | c1Body
Hola | Oye, ¿qué pasa
$ sqlite3-header myspace.messaging.database # database.db ‘select * from límite AuthorMetaData 1;’
AuthorId | AuthorImageUrl
-1930729470 | http://some_url/img/some_image . png
$ sqlite3-header myspace.messaging.database # database.db ‘select * from límite AuthorData_content 1; ‘
c0AuthorDisplayName | c1AuthorUserName
Un usuario | auser
sqlite3-header myspace.messaging.database # database.db ‘select idmensaje, fecha y hora (CreatedDate / 1000, «unixepoch», «localtime») como Date, mm.AuthorID, c0AuthorDisplayName como «Autor Display Name», c1AuthorUserName como «Autor Nombre de usuario», c0subject como Asunto, c1Body como Cuerpo de MessageMetaData mm, MessageData_content mc, AuthorData_Content ac, AuthorMetaData am donde mm.AuthorID = am.AuthorID y am.rowid = ac.rowid y mm.rowid = mc.rowid límite 2; ‘
IdMensaje | Fecha | AuthorId | Autor Display Name | Autor Usuario | Asunto | Body1289081 | 2010-08-03 14:27:00 | 41265701 | Un usuario | auser | Hola |?? Hey, ¿qué pasa
Me pregunto, en el que la producción sería más bien examinar e informar
Adición
La última consulta no es realmente tan temible. Es justo el tiempo porque estamos agarrando siete campos de cuatro mesas, y la conversión de un sello de fecha. Pero, en realidad, es muy sencillo
Vamos a echar un vistazo:
seleccione
idmensaje,
datetime (createddate/1000 «unixepoch», «localtime») como Date,
<= span style "color: blue; font-family: Courier New, Courier, espacio sencillo, fuente -size: x-small; "> mm.AuthorID,
c0AuthorDisplayName como» Autor Display Name «,
c1AuthorUserName como» Autor Nombre de usuario «,
c0subject como Asunto,
c1Body como Body
de
MessageMetaData mm,
MessageData_content mc,
AuthorMetaData am,
AuthorData_Content ac
donde
mm.AuthorID = am.AuthorID
y am.rowid = ac.rowid
y mm.rowid = mc.rowid;