En las entradas anteriores, @nicky69es explico las distintas partes que entran en juego en la recuperación de datos en SQLite. En esta entrada, nos muestra un caso practico basándose en un terminal IPhone 4S con IOS actualizado a la última versión a la fecha del documento.
El archivo a examinar tiene el nombre “Accounts3.sqlite” y contiene las cuentas sociales del usuario. Es un archivo interesante de examinar si queremos saber el acceso a diferentes servicios por parte del usuario pese a que no tenga la app instalada.
Su estructura es la siguiente:
Se compone de 15 tablas, siendo la principal la denominada “ZACCOUNT” donde encontramos los usuarios y el tipo de acceso (password, token, etc).
Visto con un editor hexadecimal:
✓2 bytes del offset 16 (10 00) nos dicen que las páginas y hojas son formadas por bloques de 4096 bytes.
✓4 bytes del offset 28 (00 00 00 34) nos dice que hay un total de 52 páginas. Que multiplicado por 4096bytes de cada página da un total de 212992 bytes que tiene el archivo.
✓4 bytes del offset 32 (00 00 00 27) indica que la primera “freelist” de tronco es la página 39.
✓4 bytes del offset 38 (00 00 00 05) indica que existen un total de 5 hojas libres.
El byte 100 es el inicio de la primera página, siendo esta del tipo x05 (Tabla interior). La navegación entre las páginas en uso es a través de esta página llamada “root” (puede consultarse en la web de sqlite la forma del programa de navegar entre páginas).
Si cogemos la página 39 (indicada como freelist en la cabecera), le restamos 1 y multiplicamos el resultado por 4096bytes (tamaño establecido de las hojas), nos da 155648 que es el offset de la primera freelist. Una vez en la dirección (offset) obtenida…
Los primeros 4 bytes (00 00 00 00) indican que no hay otro tronco de páginas libres (freelist). Los segundos 4 bytes (00 00 00 04) indican que existen 4 hojas más que corresponden con las páginas 43 (00 00 00 2B) offset 172032, página 37 (00 00 00 25) offset 147456, página 52 (00 00
00 34) offset 208896 y página 36 (00 00 00 24) offset 143360.
El resto de bytes hasta completar los 4096 de los que se componen la página pueden contener información que ya no es indexada en la base de datos en las consultas a la misma. Dependiendo de la cantidad de veces que haya sido reutilizada, puede mezclarse información de diferentes fechas. Hay que tener en cuenta que la parte que se sobre-escribe puede ser de mayor o menor tamaño que el contenido anterior.
Observando los datos de otras páginas que estén en uso, podemos establecer un criterio sobre cómo están formados los datos, si pertenecen a los índices de la base de datos o si se trataban de datos de la bbdd (tablas x0D). Igualmente podemos comparar con los datos de páginas activas para tratar de descubrir el formato de las celdas (inicio, longitud y bloques de datos); con el fin de hacer una separación lógica de los mismos.
FREEBLOCK
Como hemos visto, a partir del byte 8 de la página, los grupos de 2 bytes indican las celdas activas. Si tenemos un buen editor hexadecimal podemos ir marcando las celdas que están activas y quedarán más fácilmente identificables aquellas celdas y bytes que componen los bloques libres, los que en teoría no salen en las consultas a la base de datos. Además del “unallocated space”.
En la captura se aprecia a simple vista un bloque desde el offset 41541 con un tamaño de 68 bytes (seleccionado en azul), este bloque corresponde con la dirección que indican los bytes 1 y 2 (02 45) de la página, que recordamos indican la dirección relativa del primer freeblock, en este caso 581+40960=41541.
En este primer bloque libre, pese a que por el tamaño del espacio es similar a los bloques activos, sus primeros bytes no corresponden con los bytes de cabecera de las celdas, los 4 primeros han sido sustituidos por las cabeceras de los freeblock, 2 primeros bytes (09 F9) indican la posición del siguiente freeblock y los segundos 2 bytes (00 44) indican el tamaño libre de este bloque incluídos estos 4 bytes; 68 bytes que coinciden con lo que habíamos obtenido en la selección.
Estos bloques libres (freeblocks) pueden componer celdas enteras o haber sido sobre-escrito su espacio por un contenido de menor tamaño, lo que dejará algo de información anterior.
Teniendo en cuenta que las celdas se escriben desde el final de la hoja hasta el principio y consultando el byte 2 de cada celda que indica el rowid, podemos llegar a establecer un margen de tiempo en el que esa información se insertó en la bbdd y, aunque un poco más difícil, establecer un espacio de tiempo en que la información se borró teniendo en cuenta cuando se llenó ese espacio y el anterior.
En este bloque libre las celdas que tiene cerca indican el orden: 0B(11) – 0E(14) – bloque – 2D(45) – 2C(44) – 2B(43). Recordamos que los datos se graban desde el final de la pagina hacia el principio. Se observa que el rowid sigue un orden (43->44->45) y lo siguiente carece del mismo orden. Si las celdas con rowid 11 y 14 contuvieran un timestamp en sus datos, tendríamos una fecha desde la que nuestro freeblock habría sido borrado, ya que de haber sido borrado con anterioridad al registro de estas últimas celdas, habrían sobre-escrito el espacio de nuestro freeblock. Igualmente podemos establecer que que esa celda borrada fue creada después de la celda 45, ya que no se encuentran “huecos” libres entre celdas. Lo que nos hace pensar que son fijas y no han sido modificadas desde el inicio.
Examinemos el contenido del freeblock:
Sabemos que los dos primeros grupos de bytes de una celda indican con un varint el tamaño de la celda, el rowid y la cantidad de bytes con indicadores a los grupos de datos que componen la información de la celda. Para que el varint de datos ocupe más de un byte, debe contener un valor decimal superior a 80 (x50), como nuestro bloque de datos ocupa 68 bytes, determinamos que el varint del tamaño es de 1 byte, el rowid 1 byte y el varint de la cantidad de grupos también es de 1 byte (no puede haber más grupos de datos que bytes). Por ello los bytes 0 a 3 de la celda (09 F9 00 44) no son los originales, el resto de datos sí. Restando los 3 bytes que sabemos son del tamaño-rowid-grupos, el cuarto byte ocupado por la marca de freeblock nos indicaría el primero de los grupos de datos. Y como no sabemos si era un varint de varios bytes vamos a obtener los bloques a la inversa.
Se observa que los grupos de datos de esta celda siguen la misma estructura que las otras celdas.
Si cogemos los últimos 19 bytes de la celda, que componen en ASCII el texto “com.apple.accountsd”, multiplicamos el número de bytes 19 x 2, y le sumamos 13, el resultado es 51 (x33). El siguiente bloque formado por 22 bytes que forman en ASCII “com.apple.account.idms” daría como resultado en la misma operación x39. Podemos ya observar que existen el los offset 13 y 14 valores hexadecimales de 39 y 33. Si el valor anterior a estos x17 (23) le hacemos la operación que indica en servicio (23-13)/2 nos da como resultado 5, que sería el siguiente bloque compuesto por el texto “token”. Así hasta el principio de la celda obtenemos la estructura completa de los datos.
Pasemos a explicar cómo son los datos de las celdas.
La celda elegida contiene los datos
- x43 – 67 – 01000011 – No es un varint porque el bit 7 es 0. Valor 67 bytes de tamaño.
- x25 – 37 – indica el número de orden de la celda (rowid).
- x0D – 13 – 00001101 – No es un varint. Valor 13 bytes de tipos de datos.
- x00 – byte 2, tipo 0, valor NULL
- x01 – byte 3, tipo 1, ancho 1 byte
- 09h .., tipo 9, ancho 0 bytes, valor 1
- 08h .., tipo 8, ancho 0 bytes, valor 0
- x08.., tipo 8, ancho 0 bytes, valor 0
- x09 .., tipo 9, ancho 0 bytes, valor 1
- x08 .., tipo 8, ancho 0 bytes, valor 0
- x13 .., tipo impar >13 (19), ancho 3 bytes (19-13 /2), valor strings
- x11 .., tipo impar >13 (17), ancho 2 bytes, valor strings
- x1D .., tipo impar >13 (29), ancho 8 bytes, valor strings
- x37 .., tipo impar >13 (55), ancho 21 bytes, valor strings
- x33 .., tipo impar >13 (51), ancho 19 bytes, valor strings
- 04 31 36 33 63 6B 70 61 73 73 77 6F 72 64 63 6F 6D 2E 61 70 70 6C 65 2E 61 63 63 6F 75 6E 74 2E 31 36 33 63 6F 6D 2E 61 70 70 6C 65 2E 61 63 63 6F 75 6E 74 73 64