Inleiding
Mijn eerste kennismaking met varints was vele jaren geleden tijdens een digitaal forensisch onderzoek van een iPhone 3GS in een onderzoek naar moord en brandstichting. Tot dan toe had mijn forensisch werk voornamelijk betrekking op feature telefoons, met name CDMA apparaten met BREW. Elk tekstbericht werd opgeslagen in een eigen bestand, met een consistente offset en een duidelijke hexadecimale waarde die de lengte van het bericht aangaf. Het was een voorspelbaar en vertrouwd proces.
De iPhone stelde me echter voor een geheel nieuwe uitdaging. Berichten werden niet langer opgeslagen als individuele bestanden, maar als records in een database. In tegenstelling tot de eenvoud van functietelefoons werd de lengte van een berichtenreeks niet gedefinieerd door een duidelijke hexadecimale waarde. In plaats daarvan moest ik door SQLite databases navigeren en de payloads van records leren ontleden. Hier kwam ik het volgende tegen varints-variabele-lengte gehele getallen-een compacte en efficiënte manier om gegevens te coderen. Het begrijpen van varints werd cruciaal toen ik de databasestructuur ontrafelde en belangrijk bewijs eruit haalde. In dit geval leidde het beheersen van varints tot belastende bevindingen die uiteindelijk hielpen bij de veroordeling van de verdachte voor brandstichting en moord.
Varints zijn een fundamenteel onderdeel van SQLite databases en maken efficiënte codering mogelijk van gehele getallen die de lengte van cellen, records en specifieke velden definiëren. Voor digitaal forensisch onderzoekers is het decoderen van varints essentieel voor het blootleggen van kritieke informatie in databasebestanden. Deze compacte integers spelen een belangrijke rol bij het in kaart brengen van tabelstructuren, het identificeren van record payloads en het herstellen van verwijderde of verborgen gegevens.
Deze blogpost onderzoekt de vitale rol die varints spelen in SQLite forensisch onderzoek. Ik introduceer mijn VarInt rekenmachine, een tool die ik heb ontworpen om het decoderingsproces te vereenvoudigen, en leidt je door een tutorial om je te helpen deze kennis toe te passen in je onderzoeken. Van het ontleden van SQLite database-items tot het reconstrueren van verwijderde records, het begrijpen van varints is een vaardigheid die elke forensisch onderzoeker in zijn gereedschapskist zou moeten hebben.
Varints begrijpen: Ze herkennen en decoderen
Om dieper in SQLite en digitaal forensisch onderzoek te duiken, is een belangrijke vaardigheid die je moet begrijpen gehele getallen met variabele lengte (varints). Deze compacte getallen komen overal voor in SQLite databases en helpen het systeem ruimte te besparen door zo weinig mogelijk bytes te gebruiken om waarden op te slaan. Maar ze kunnen ook lastig te vinden en te decoderen zijn als je niet weet waar je op moet letten. Laten we het stap voor stap uitwerken.
Wat is een Varint?
Een varint is een speciale manier om getallen op te slaan waarbij de grootte van het getal bepaalt hoeveel bytes worden gebruikt. In tegenstelling tot gehele getallen met een vaste lengte (bijvoorbeeld 4 bytes of 8 bytes), kan een varint zo klein zijn als 1 byte of zo groot als 9 bytes. Deze flexibiliteit maakt varints ruimte-efficiënt, maar ook lastiger te interpreteren.
Waar vind je Varints?
In SQLite-databases worden varints gebruikt om te coderen:
- De lengte van cellen of records in een databasepagina.
- Rij-ID's die records uniek identificeren.
- De lengte van de gegevens in de payload van een record.
- Diverse andere waarden met betrekking tot de databasestructuur.
De sleutel tot het lezen van Varints: De markeerbit
Het eerste wat je moet weten als je een varint leest, is hoe je de lengte kunt bepalen. Elke byte in een varint heeft een markeerbit (het meest significante bit, of MSB) die je vertelt of er rechts nog een byte is die deel uitmaakt van dezelfde varint:
- Als de markeerbit 1 ismaakt de volgende byte ook deel uit van de varint.
- Als de markeerbit 0 isJe hebt het einde van de varint bereikt.
Twee manieren om de lengte van Varints te decoderen
Er zijn twee methoden om uit te vinden hoe lang een varint is: de lange manier (binair) en de gemakkelijke manier (hex nibble). Laten we beide bekijken.
De lange weg: Binair gebruik
- Begin met de eerste byte van de varint.
- Converteer de byte naar binair. Kijk naar het meest significante bit (het meest linkse bit).
- Als de bit 1 is, maakt de byte rechts deel uit van de varint.
- Als de bit 0 is, heb je het einde bereikt.
- Herhaal dit proces voor elke byte totdat je een byte vindt met een MSB van 0.
Voorbeeld:
- Byte:
0xC2
→ Binair: 11000010 → MSB: 1 → Doorgaan. - Byte:
0x7F
→ Binair: 01111111 → MSB: 0 → Stop hier.
De gemakkelijke manier: De linker knobbel gebruiken
- Kijk naar de linker nibble (het eerste hexadecimale cijfer van de byte).
- Als de linker nibble 8 of hoger is (8, 9, A, B, C, D, E of F), is de volgende byte onderdeel van de varint.
- Als de linker nibble 7 of lager is (0 tot 7), heb je het einde van de varint bereikt.
Waarom dit werkt: Een linker nibble van 8 of meer betekent dat de MSB 1 is, terwijl een linker nibble van 7 of minder betekent dat de MSB 0 is.
Voorbeeld:
- Byte:
0xC2
→ Linker nibble: C (groter dan 8) → Doorgaan. - Byte:
0x7F
→ Linker nibble: 7 (minder dan 8) → Stop hier.

Variëren in cellengtes begrijpen: een praktisch voorbeeld
Varinten worden in SQLite gebruikt om de grootte van cellen op databasepagina's. Deze cellen kunnen van alles bevatten, van tabellen tot tabelrecords, en de eerste byte(s) van een cel vertellen ons hoe groot de cel is. Deze lengte-indicator is zelf een varint, die kan variëren van 1 tot 9 bytes in lengte.
Voorbeeld uit de praktijk: WAL-bestand
In dit voorbeeld bevat de cel de berichten tabel. De eerste byte van de cel is 0x81
, die een varint van twee bytes aangeeft.
- Indeling:
- Byte 1:
0x81
→ Binair: 10000001 → Markeerbit: 1 → Doorgaan. - Byte 2:
0x07
→ Binair: 00000111 → Markeerbit: 0 → Stop.
- Byte 1:
Decodde Varint
Nu moeten we de varint decoderen. Als we gewoon de waarde 0x8107
naar een geheel getal, zouden we per ongeluk een enorme 33.031 berekenen, wat duidelijk niet overeenkomt met de werkelijke grootte van de cel.
Waarom?
De markeerbits dragen niet bij aan de werkelijke waarde van de varint. Om de varint goed te decoderen, moeten we de markeerstiften verwijderen en interpreteer alleen de betekenisvolle delen van de binaire representatie. Dit is hoe het gedaan wordt:
- Decodeer:
- Verwijder de markeringsbits: 0000001 en 0000111.
- Combineer de twee septetten: 00000000 10000111 → Decimaal: 135.
- De lengte van de cel is 135 bytes (exclusief de varint en ROWID).
De Varint-calculator gebruiken voor efficiëntie
De Varint rekenmachine vereenvoudigt dit proces. Voer de hexadecimale waarde in (bijvoorbeeld 8107) om de varint snel te decoderen. In het bovenstaande voorbeeld geeft de rekenmachine 135 terug, wat de lengte bevestigt.

Varints in Record Headers decoderen
In SQLite gebruiken recordheaders varints om te definiëren:
- Lengte: Hoeveel gegevens u moet lezen.
- Type: Hoe de gegevens te interpreteren (integer, string, BLOB, enz.).

Voorbeeld: Lengte van een string
Laten we een varint in een recordkop decoderen:- Varint:
0x25
- Linker nibble: 2 (minder dan 8) → Single-byte varint.
- Decimaal: 37.
- Lading: Stringlengte = 12 bytes (+97444455667).

Afsluitende gedachten
Het begrijpen en decoderen van varints is een belangrijke vaardigheid voor elke digitaal forensisch onderzoeker die met SQLite databases werkt. Deze compacte integers zijn de sleutel tot het interpreteren van databasestructuren, het bepalen van celgroottes en het efficiënt herstellen van gegevens.
Met hulpmiddelen zoals de Varint Calculator wordt het proces toegankelijker, zodat forensische beoefenaars zich kunnen richten op het blootleggen van de waarheid die verborgen zit in digitaal bewijsmateriaal. Het beheersen van varints is meer dan een technische vaardigheid, het is een essentiële vaardigheid die de uitkomst van onderzoeken direct kan beïnvloeden.
Je kunt hier meer lezen en de Varint Calculator downloaden: