Biome-SEGB-Dateiformat: Referenz für v1 und v2
Byte-genaue Referenz zu Biome SEGB v1 und v2: Header, Trailer, Record-Status, CRC32, Ausrichtung, Zeiten im Dateinamen und Protobuf-Feldnummern je Stream.
Kurz gesagt. Ein Biome-Stream ist ein Ordner mit SEGB-Dateien. v1 hat einen 56-Byte-Header mit SEGB in den Bytes 52–55 und dem End-of-Data-Offset in den Bytes 0–3; jeder Record hat einen 32-Byte-Header (Länge, Status, zwei Zeitstempel, CRC32, unbekannt) und wird auf 8 Bytes aufgefüllt. v2 beginnt mit SEGB, einer Anzahl von Einträgen und einem Erstellungszeitpunkt und indiziert seine Records über einen Trailer aus 16-Byte-Einträgen (End-Offset, Status, Zeit) am Dateiende; jeder Record besteht aus einer CRC32, einem unbekannten int32 und der Payload, ausgerichtet auf 4 Bytes. Die Status sind 1 geschrieben, 3 gelöscht, 4 leer. Payloads sind Protocol Buffers ohne veröffentlichtes Schema. Nichts davon ist von Apple dokumentiert.
Diese Referenz folgt ccl-segb von CCL Forensics (MIT-Lizenz), das sich für das v2-Layout auf die Forschung von Cellebrite beruft, und genau das implementiert KnowledgeC Parser. Wo diese Dateien liegen und warum sie wichtig sind, erklären der Leitfaden zur forensischen Analyse von knowledgeC.db und knowledgeC vs. Biome.
Wo SEGB-Dateien liegen
~/Library/Biome/streams/restricted/<Stream>/local/<file>
~/Library/Biome/streams/public/<Stream>/local/<file>
~/Library/Biome/streams/restricted/<Stream>/remote/<device UUID>/<file>
~/Library/Biome/streams/restricted/<Stream>/local/tombstone/<file>
/private/var/db/biome/streams/...
Der Stream-Name (App.InFocus, App.WebUsage, ...) steht nicht in der Datei, sondern ergibt sich aus dem Ordner. Behalten Sie bei der Sicherung die Ordnerstruktur bei, sonst verlieren Sie den Stream-Namen, die Unterscheidung zwischen local und remote sowie die Geräte-UUID. Dateien in tombstone/ sind abgelaufen (Biome-Tombstone).
Alle folgenden Ganzzahlen sind Little-Endian. Zeiten sind Mac Absolute Time, gespeichert als 64-Bit-Double: Sekunden seit 2001-01-01 00:00:00 UTC. Addieren Sie 978307200 für Unix-Zeit.
SEGB v1
Datei-Header (56 Bytes)
| Offset | Größe | Typ | Feld |
|---|---|---|---|
0x00 | 4 | uint32 | End-of-Data-Offset (absolut, ab Dateianfang) |
0x04 | 48 | Nicht dokumentiert | |
0x34 | 4 | ASCII | Magic SEGB (Bytes 52–55) |
Die Records beginnen bei Byte 56 (0x38) und reichen bis zum End-of-Data-Offset. Zeigt dieser Offset über das Dateiende hinaus, ist die Kopie abgeschnitten.
Record-Header (32 Bytes)
| Offset im Record | Größe | Typ | Feld |
|---|---|---|---|
0x00 | 4 | int32 | Länge der Payload |
0x04 | 4 | int32 | Status |
0x08 | 8 | double | timestamp1 (Mac Absolute Time) |
0x10 | 8 | double | timestamp2 (Mac Absolute Time) |
0x18 | 4 | uint32 | CRC32 der Payload |
0x1C | 4 | int32 | Unbekannt |
0x20 | Länge | bytes | Payload |
Nach der Payload beginnt der nächste Record beim nächsten Vielfachen von 8, gerechnet ab Dateianfang. Die Namen timestamp1 und timestamp2 sind rein beschreibend: Öffentliche Quellen weisen ihnen nicht für jeden Stream eine feste Bedeutung zu. Berichten Sie daher beide Rohwerte, statt einen als „Beginn“ und den anderen als „Ende“ zu bezeichnen.
SEGB v2
Datei-Header (32 Bytes)
| Offset | Größe | Typ | Feld |
|---|---|---|---|
0x00 | 4 | ASCII | Magic SEGB |
0x04 | 4 | int32 | Anzahl der Einträge (Zahl der Trailer-Einträge) |
0x08 | 8 | double | Erstellungszeitpunkt (Mac Absolute Time) |
0x10 | 16 | Nicht dokumentiert |
Trailer (16 Bytes pro Eintrag, am Dateiende)
Der Trailer belegt die letzten count × 16 Bytes der Datei.
| Offset im Eintrag | Größe | Typ | Feld |
|---|---|---|---|
0x00 | 4 | int32 | End-Offset des Records, relativ zu Byte 32 |
0x04 | 4 | int32 | Status |
0x08 | 8 | double | Zeit (Mac Absolute Time) |
Records
Die Records beginnen bei Byte 32. Jeder Record ist so aufgebaut:
| Offset im Record | Größe | Typ | Feld |
|---|---|---|---|
0x00 | 4 | uint32 | CRC32 der Payload |
0x04 | 4 | int32 | Unbekannt |
0x08 | variabel | bytes | Payload, bis zum End-Offset |
Ein v2-Record hat kein Längenfeld. Um ihn zu lesen, sortieren Sie die Trailer-Einträge nach End-Offset, beginnen bei Byte 32 und lesen bis 32 + end offset. Der nächste Record beginnt an der nächsten 4-Byte-Grenze. Da Status und Zeit im Trailer stehen, enthält ein v2-Record-Header nur die CRC und das unbekannte Wort.
Gemeinsame End-Offsets
Zwei Trailer-Einträge können denselben End-Offset tragen. Das übliche Muster ist ein Record, der geschrieben (Status 1) und später gelöscht (Status 3) wurde: Beide Einträge zeigen auf dieselben Bytes, jeder mit eigener Zeit. Ein Parser sollte beide ausgeben und den zweiten nicht als neuen Record behandeln. KnowledgeC Parser zeigt den gelöschten Eintrag mit derselben Payload an und kennzeichnet ihn als gelöscht. Trailer-Einträge mit Status 0, die auf keine Daten verweisen, ignoriert er.
Record-Status und CRC
| Status | Bedeutung | Vorgehen |
|---|---|---|
| 1 | Geschrieben | Normaler Record |
| 3 | Gelöscht | Die Payload kann noch vorhanden sein: dekodieren und als gelöscht berichten |
| 4 | Leer / unbenutzt | Kein verwertbarer Record |
Die CRC ist Standard-CRC-32, wie sie zlib berechnet (zlib.crc32), und zwar nur über die Payload. Eine Abweichung deutet auf einen teilweise geschriebenen oder beschädigten Record hin oder auf eine Kopie, die während eines Schreibvorgangs entstand. Behalten Sie solche Records, markieren Sie sie aber; verwerfen Sie sie nicht stillschweigend.
Ein kommentiertes v2-Beispiel
Die folgende Datei wurde für diesen Artikel nach dem obigen Layout erstellt: ein App.InFocus-Record, der besagt, dass Terminal in den Fokus kam. Sie ist synthetisch, und die nicht dokumentierten Header-Bytes sind hier null.
00000000 53 45 47 42 01 00 00 00 00 00 00 a6 c0 2b c8 41 SEGB.........+.A
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 67 88 af ff 00 00 00 00 18 01 21 00 00 00 80 ff g.........!.....
00000030 2b c8 41 32 12 63 6f 6d 2e 61 70 70 6c 65 2e 54 +.A2.com.apple.T
00000040 65 72 6d 69 6e 61 6c 00 27 00 00 00 01 00 00 00 erminal.'.......
00000050 66 66 66 80 ff 2b c8 41 fff..+.A
| Bytes | Wert | Bedeutung |
|---|---|---|
0x00–0x03 | SEGB | v2-Magic |
0x04–0x07 | 01 00 00 00 | 1 Trailer-Eintrag |
0x08–0x0F | double 811041100.0 | Erstellt 2026-09-14 01:11:40 UTC |
0x10–0x1F | Nullen | Nicht dokumentiert |
0x20–0x23 | 0xffaf8867 | CRC32 der Payload |
0x24–0x27 | 0 | Unbekannt |
0x28–0x46 | 31 Bytes | Protobuf-Payload (siehe unten) |
0x47 | 00 | Auffüllung bis zur 4-Byte-Grenze |
0x48–0x4B | 27 00 00 00 | End-Offset 39: 32 + 39 = 0x47, das Ende der Payload |
0x4C–0x4F | 01 00 00 00 | Status 1, geschrieben |
0x50–0x57 | double 811073280.8 | 2026-09-14 10:08:00.8 UTC |
Die Payload dekodiert sich wie folgt:
| Bytes | Tag | Feld | Wert |
|---|---|---|---|
18 01 | Feld 3, Varint | Status | 1 = im Fokus |
21 + 8 Bytes | Feld 4, 64 Bit | Zeit | 811073280.0 = 10:08:00 UTC |
32 12 + 18 Bytes | Feld 6, längenbegrenzt | Bundle-ID | com.apple.Terminal |
Eine gespeicherte Datei dieser Art wäre nach ihrem Erstellungszeitpunkt in Mikrosekunden benannt, hier 811041100000000.
Zeiten im Dateinamen
SEGB-Dateinamen sind Ganzzahlen. mac_apt liest sie als Cocoa-Zeit in Mikrosekunden, was einen ungefähren Erstellungszeitpunkt der Datei ergibt:
date -u -r $(( 811041100000000 / 1000000 + 978307200 ))
# Mon Sep 14 01:11:40 UTC 2026
Betrachten Sie ihn als Hinweis auf Dateiebene. Ereigniszeiten stammen aus den Records und bei manchen Streams aus der Payload.
Protobuf-Payloads
Wire-Typen im Überblick
Eine Protobuf-Nachricht ist eine Folge von Feldern. Jedes beginnt mit einem Varint-Schlüssel: field number << 3 | wire type (Encoding-Leitfaden).
| Wire-Typ | Kodierung | Typischer Inhalt |
|---|---|---|
| 0 | Varint | Ganzzahlen, Booleans, Enums |
| 1 | 8 Bytes | double, fixed64 |
| 2 | Varint-Länge + Bytes | Strings, Bytes, verschachtelte Nachrichten |
| 5 | 4 Bytes | float, fixed32 |
Die Wire-Typen 3 und 4 (Groups) sind veraltet und hier nicht zu erwarten.
Warum Dekodierung ohne Schema mehrdeutig ist
Apple veröffentlicht keine .proto-Dateien für Biome. Ohne Schema gilt:
- ein längenbegrenztes Feld kann ein String, rohe Bytes oder eine verschachtelte Nachricht sein, und kurze Strings wie Bundle-IDs lassen sich mitunter als gültige Nachrichten parsen;
- ein 8-Byte-Feld kann ein Double oder eine Ganzzahl sein;
- ein Varint kann ein vorzeichenbehafteter, vorzeichenloser, Zigzag-kodierter oder boolescher Wert sein.
KnowledgeC Parser versucht zuerst druckbaren UTF-8-Text, dann eine verschachtelte Nachricht, die alle Bytes aufbraucht, und schließlich rohe Bytes. 8-Byte-Werte zeigt er als Doubles an, mit einem Datum, wenn der Wert eine plausible Mac Absolute Time ist. Manche Payloads enthalten binäre Property Lists, die als solche angezeigt werden. Feldnummern bleiben immer erhalten, sodass Sie jede Interpretation mit einem anderen Werkzeug prüfen können.
Feldnummern je Stream
Diese Nummern stammen aus Reverse Engineering der Community im BIOME-Plugin von mac_apt und in iLEAPP. Sie sind keine Apple-Dokumentation; validieren Sie sie mit Testdaten desselben OS-Builds, bevor Sie sich darauf stützen.
| Stream | Feld | Bedeutung | Quelle |
|---|---|---|---|
App.InFocus | 3 | Status: 1 im Fokus, 0 nicht im Fokus | mac_apt |
App.InFocus | 4 | Zeit (double) | iLEAPP |
App.InFocus | 6 | Bundle-ID | mac_apt |
App.InFocus | 9, 10 | Versions-Strings | mac_apt |
App.WebUsage | 2 | Zeit | iLEAPP |
App.WebUsage | 4 / 5 / 6 | URL / Domain / Bundle-ID | mac_apt |
Safari.* | 1 | Domain | mac_apt |
ScreenTime.AppUsage | 1 / 3 | Status / Bundle-ID | mac_apt |
Notification.Usage | 4 / 8 / 9 | App / Titel / Untertitel | mac_apt |
Device.Wireless.WiFi | 1 / 2 | SSID / Status | mac_apt |
Device.Wireless.Bluetooth | 1 / 2 / 3 / 4 | Adresse / Name / Produkt-ID / Status | mac_apt |
SystemSettings.SearchTerms | 1 | Suchbegriff | mac_apt |
App.InFocus-Records sind Ereignisse, keine Intervalle: Auf einen Record „im Fokus“ folgt später ein Record „nicht im Fokus“ für dieselbe App. KnowledgeC Parser fasst sie zu Intervallen zusammen (gleicher Benutzer, gleiches Gerät, gleiche Bundle-ID, innerhalb von 24 Stunden) und belässt Records ohne Gegenstück als Einzelereignisse.
Was unbekannt ist
- Die 48 nicht dokumentierten Bytes des v1-Headers, die 16 des v2-Headers und das „unbekannte“ int32 in jedem Record.
- Eine feste Bedeutung von
timestamp1undtimestamp2in v1 über alle Streams hinweg. - Felder, die nicht in der obigen Tabelle stehen, sowie sämtliche Felder von Streams ohne öffentlichen Decoder.
App.MenuItem, von Unit 42 dokumentiert unter macOS Tahoe 26, hat keine öffentliche Feldzuordnung: KnowledgeC Parser dekodiert ihn ohne Schema und zeigt die rohen Feldnummern an. - Die macOS-Version, in der v2 die Version v1 abgelöst hat.
Hängt ein Bericht von einem dieser Punkte ab, sagen Sie das ausdrücklich und zeigen Sie den Rohwert.
Werkzeuge, die SEGB lesen
| Werkzeug | Funktion |
|---|---|
| ccl-segb | Referenz-Reader für einzelne v1- und v2-Dateien, rohe Records |
mac_apt, Plugin BIOME | Liest Streams aus einem Abbild oder einem Ordner und dekodiert die oben genannten Streams |
| iLEAPP | Biome-Streams unter iOS |
| KnowledgeC Parser | v1 und v2 im Browser, mit Status, CRC-Prüfung, Herkunft aus remote und tombstone sowie einer gemeinsamen Zeitleiste mit knowledgeC.db |
FAQ
Ist das SEGB-Format von Apple dokumentiert?
Nein. Die Layouts von SEGB v1 und v2 stammen aus Reverse Engineering der Community, umgesetzt in ccl-segb (CCL Forensics), das sich auf Forschung von Cellebrite beruft. Die Bedeutung der Payload-Felder stammt aus mac_apt und iLEAPP. Alles, was diese Quellen nicht abdecken, sollte als unbekannt gelten.
Wie unterscheide ich SEGB v1 von v2?
Suchen Sie die SEGB-Magic. In v1 steht sie in den Bytes 52 bis 55, am Ende eines 56-Byte-Headers. In v2 bildet sie die ersten vier Bytes der Datei, am Anfang eines 32-Byte-Headers.
Enthält ein gelöschter SEGB-Record noch Daten?
Oft ja. Status 3 kennzeichnet einen Record als gelöscht, die Payload kann aber in der Datei verbleiben. In v2 kann ein gelöschter Eintrag denselben End-Offset haben wie ein geschriebener, sodass beide auf dieselben Bytes zeigen. Berichten Sie solche Records als gelöscht, nicht als aktuelle Aktivität.
Mit welcher macOS-Version wurde SEGB v1 durch v2 abgelöst?
Diese Grenze ist für macOS nicht öffentlich dokumentiert. Für iOS wird v1 für iOS 14 bis 16 und v2 ab iOS 17 berichtet. Parser erkennen die Version am Header, Sie müssen sie also nicht im Voraus kennen.