Informationen aus der Virtualbox-SAV-Datei extrahieren?

Informationen aus der Virtualbox-SAV-Datei extrahieren?

Ich habe eine .savVirtualBox-Datei, die ich wiederherstellen möchte. Das Problem ist jedoch, dass ich nur diese Datei habe (ohne weitere Informationen zur Festplattendatei und RAM-Größe usw.). Ich habe versucht, eine meiner virtuellen Maschinen zu duplizieren, einen Snapshot erstellt und den Snapshot (mit dem richtigen Dateinamen) ersetzt. Und beim Wiederherstellen des Status hat VirtualBox einen Fehler ausgegeben

Einheit „mm“ konnte nicht geladen werden (VERR_SSM_LOAD_MEMORY_SIZE_MISMATCH)

Da ich die Speichergröße nicht kenne, kann ich nicht weitermachen.

Nach dem Googeln finde ich eine Snapshot-Datei, die alle Informationen und die Konfiguration einer virtuellen Maschine enthält. Gibt es eine Möglichkeit, Informationen aus einer .savDatei zu extrahieren, damit ich die richtige Konfiguration erhalte?

Antwort1

Das Folgende bezieht sich auf die aktuellste Version von VirtualBox zum Zeitpunkt des Schreibens (4.3). Für ältere Versionen kann ich nichts sagen.

Eine SAVDatei besteht aus units. Wenn Sie Ihre SAVDatei in einem Hex-Editor öffnen, können Sie durch die Einheiten navigieren, indem Sie nach der folgenden Hex-Zeichenfolge suchen:

0A 55 6E 69 74 0A 00 00

Dies ist das Wort Unitmit einigen anderen Zeichen drumherum. 0x24 (36) Bytes nach dem Treffer sehen Sie einige ASCII-Zeichen. Das erste wird zum Beispiel wahrscheinlich sein: SSM. Dies ist der Deskriptor für die Einheit, in diesem Fall der „Saved State Manager“.

Sie möchten die mm(Memory Manager-)Unit finden. Bei mir war es immer die dritte Unit in der SAV-Datei – also das dritte Ergebnis bei der Suche:

Im Hexadezimalformat:

0A 55 6E 69 74 0A 00 00 52 01 00 00 00 00 00 00 7C 36 11 91 CE B0 E2
CE 02 00 00 00 01 00 00 00 FF FF FF FF 00 00 00 00 03 00 00 00 6D 6D
00 92 10 1E 00 08 00 00 00 00 00 00 00 00 80 00 00 00 00 91 0E 01 00
38 7E D4 06 22 00 00 00 00 00 00 00

Wie Sie sehen, sind die ersten 8 Bytes der unitHeader. 0x24 (36) Bytes später sehen wir, 6D 6D 00dass mm\0. Überspringen Sie drei Bytes ( 92 10 1E), dann haben Sie eine uint16 (Little Endian), die die Größe des Systemspeichers zum Zeitpunkt der Aufnahme des Snapshots darstellt. In meinem Beispiel: 00 08= 0x800= 2048= 2GB.

Antwort2

Sie können versuchen, dievboxmanage Status übernehmen, das gemäß der Dokumentation versucht, die VM so zu ändern, dass der aktuelle Snapshot an den vorgeschlagenen Speicherzustand angehängt wird.

Wenn es nicht funktioniert, hat parsiya ein interessantes Blog über das Parsen des SAV-Status geschrieben, das Sie hier finden:Parsiya-Blog

Laut seinem Blog wird der SAVE-Zustand beschrieben inSSM.cpp

Die neuen Informationen, die ich gefunden habe, basieren auf SSMFILEHDRV12 (aktueller als parsiya). Die Einheit von RTGCPHYS ist GIM_HV_PAGE_SIZE (4096). Es ist eher eine Einheit und beträgt im Allgemeinen 08 * 4096, wenn ich es richtig verstanden habe. Tatsächlich gibt es eine weitere Einheit für die Daten, die später erstellt werden

Wenn ich die Logik des SSM.cpp-Codes richtig verstanden habe, besteht sie, wie am Anfang erklärt, darin, einen Live-Speicherstatus durchzuführen. D. h. die Gesamtgröße ist nicht bekannt. Es könnten also mehrere Speichereinheiten aufgezeichnet sein. Wenn nur eine Einheit Rohspeicher vorhanden ist, können Sie die Größe der VM tatsächlich ableiten. Die Laufleistung variiert

Auszug vom Anfang der Akte

 * The live snapshots feature (LS) is similar to teleportation (TP) and was a
 * natural first step when implementing TP.  The main differences between LS and
 * TP are that after a live snapshot we will have a saved state file, disk image
 * snapshots, and the VM will still be running.
 *  * Compared to normal saved stated and snapshots, the difference is in that the
 * VM is running while we do most of the saving.  Prior to LS, there was only
 * one round of callbacks during saving and the VM was paused during it.  With
 * LS there are 1 or more passes while the VM is still running and a final one
 * after it has been paused.  The runtime passes are executed on a dedicated
 * thread running at at the same priority as the EMTs so that the saving doesn't
 * starve or lose in scheduling questions (note: not implemented yet). The final
 * pass is done on EMT(0).

 * The saved state units each starts with a variable sized header
 * (SSMFILEUNITHDRV2) that contains the name, instance and pass.  The data
 * follows the header and is encoded as records with a 2-8 byte record header
 * indicating the type, flags and size.  The first byte in the record header
 * indicates the type and flags:
 *  *   - bits 0..3: Record type:
 *       - type 0: Invalid.
 *       - type 1: Terminator with CRC-32 and unit size.
 *       - type 2: Raw data record.
 *       - type 3: Raw data compressed by LZF. The data is prefixed by a 8-bit
 *                 field containing the length of the uncompressed data given in
 *                 1KB units.
 *       - type 4: Zero data. The record header is followed by a 8-bit field
 *                 counting the length of the zero data given in 1KB units.
 *       - type 5: Named data - length prefixed name followed by the data. This
 *                 type is not implemented yet as we're missing the API part, so
 *                 the type assignment is tentative.
 *       - types 6 thru 15 are current undefined.
 *   - bit 4: Important (set), can be skipped (clear).
 *   - bit 5: Undefined flag, must be zero.
 *   - bit 6: Undefined flag, must be zero.
 *   - bit 7: "magic" bit, always set.  
 /**
 * Writes a record header for the specified amount of data.
 *
 * @returns VBox status code. Sets pSSM->rc on failure.
 * @param   pSSM            The saved state handle
 * @param   cb              The amount of data.
 * @param   u8TypeAndFlags  The record type and flags.
 */
static int ssmR3DataWriteRecHdr(PSSMHANDLE pSSM, size_t cb, uint8_t u8TypeAndFlags)
{
    size_t  cbHdr;
    uint8_t abHdr[8];
    abHdr[0] = u8TypeAndFlags;
    if (cb < 0x80)
    {
        cbHdr = 2;
        abHdr[1] = (uint8_t)cb;
    }
    else if (cb < 0x00000800)
    {
        cbHdr = 3;
        abHdr[1] = (uint8_t)(0xc0 | (cb >> 6));
        abHdr[2] = (uint8_t)(0x80 | (cb & 0x3f));
    }
    else if (cb < 0x00010000)
    {
        cbHdr = 4;
        abHdr[1] = (uint8_t)(0xe0 | (cb >> 12));
        abHdr[2] = (uint8_t)(0x80 | ((cb >> 6) & 0x3f));
        abHdr[3] = (uint8_t)(0x80 | (cb & 0x3f));
    }
    else if (cb < 0x00200000)
    {
        cbHdr = 5;
        abHdr[1] = (uint8_t)(0xf0 |  (cb >> 18));
        abHdr[2] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
        abHdr[3] = (uint8_t)(0x80 | ((cb >>  6) & 0x3f));
        abHdr[4] = (uint8_t)(0x80 |  (cb        & 0x3f));
    }
    else if (cb < 0x04000000)
    {
        cbHdr = 6;
        abHdr[1] = (uint8_t)(0xf8 |  (cb >> 24));
        abHdr[2] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
        abHdr[3] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
        abHdr[4] = (uint8_t)(0x80 | ((cb >>  6) & 0x3f));
        abHdr[5] = (uint8_t)(0x80 |  (cb        & 0x3f));
    }
    else if (cb <= 0x7fffffff)
    {
        cbHdr = 7;
        abHdr[1] = (uint8_t)(0xfc |  (cb >> 30));
        abHdr[2] = (uint8_t)(0x80 | ((cb >> 24) & 0x3f));
        abHdr[3] = (uint8_t)(0x80 | ((cb >> 18) & 0x3f));
        abHdr[4] = (uint8_t)(0x80 | ((cb >> 12) & 0x3f));
        abHdr[5] = (uint8_t)(0x80 | ((cb >>  6) & 0x3f));
        abHdr[6] = (uint8_t)(0x80 | (cb & 0x3f));
    }
    else
        AssertLogRelMsgFailedReturn(("cb=%#x\n", cb), pSSM->rc = VERR_SSM_MEM_TOO_BIG);

    Log3(("ssmR3DataWriteRecHdr: %08llx|%08llx/%08x: Type=%02x fImportant=%RTbool cbHdr=%u\n",
          ssmR3StrmTell(&pSSM->Strm) + cbHdr, pSSM->offUnit + cbHdr, cb, u8TypeAndFlags & SSM_REC_TYPE_MASK, !!(u8TypeAndFlags & SSM_REC_FLAGS_IMPORTANT), cbHdr));

    return ssmR3DataWriteRaw(pSSM, &abHdr[0], cbHdr);
}

Ihm fiel auch auf, wie Bridgey, dass Einheiten mit ASCII „Unit“ beginnen, die letzte Einheit aber mit „TheEnd“ endet.

Er analysierte einen Teil der Struktur der SAV-Datei basierend auf der Struktur der UNIT, die hier in SSMInternal.h beschrieben ist:Virtualbox OpenSource-Header

verwandte Informationen