extrair informações do arquivo .sav do virtualbox?

1

Eu tenho um arquivo .sav do VirtualBox que eu quero restaurar. Mas o problema é que eu só tenho esse arquivo (sem qualquer outra informação do arquivo de disco e tamanho da RAM e assim por diante). Tentei duplicar uma das minhas máquinas virtuais, fiz um instantâneo e substituí o instantâneo (com o nome do arquivo correto). E ao restaurar o estado, o VirtualBox gerou um erro

Failed to load unit 'mm' (VERR_SSM_LOAD_MEMORY_SIZE_MISMATCH)

Como não sei o tamanho da memória, não consigo seguir em frente.

Após googling eu acho um arquivo de instantâneo contém todas as informações e configurações de uma máquina virtual. Existe alguma maneira possível de extrair informações de um arquivo .sav para que eu possa obter a configuração correta?

    
por JACK M 16.05.2015 / 19:51

2 respostas

4

O seguinte se refere à versão mais recente do VirtualBox no momento da escrita (4.3). Eu não posso falar por versões mais antigas.

Um arquivo SAV é composto de units . Se você abrir o arquivo SAV em um editor hexadecimal, poderá navegar pelas unidades procurando pela seguinte sequência hexadecimal:

0A 55 6E 69 74 0A 00 00

Esta é a palavra Unit com alguns outros caracteres em torno dela. 0x24 (36) bytes após o hit, você verá alguns caracteres ASCII. Por exemplo, o primeiro provavelmente será: SSM . Este é o descritor da unidade, neste caso o 'Gerenciador de estado salvo'.

Você deseja encontrar a unidade mm (Gerenciador de memória). Para mim, sempre foi a terceira unidade no arquivo SAV - então o terceiro resultado na pesquisa:

Em hexadecimal:

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

Como você pode ver, os primeiros 8 bytes são o unit header. Então, 0x24 (36) bytes depois, vemos 6D 6D 00 , que é mm92 10 1E . Pule três bytes ( 00 08 ) e você terá um uint16 (little endian) que é a quantidade de memória do sistema no momento em que o instantâneo foi tirado. No meu exemplo: 0x800 = 2048 = 2GB = %code% .

    
por 05.07.2015 / 20:01
0

Você pode tentar executar o estado de adoção do vboxmanage , que, de acordo com a documentação, será tente alterar a VM para anexar o instantâneo atual ao estado de salvamento proposto.

Se isso não funcionar, parsiya fez um blog interessante sobre a análise do estado SAV, que pode ser encontrado aqui: blog parsiya

De acordo com seu blog, o estado SAVE é descrito em SSM. cpp

A nova informação que encontrei é baseada em SSMFILEHDRV12 (mais recente que parsiya) A unidade de RTGCPHYS está em GIM_HV_PAGE_SIZE (4096). É mais uma unidade e geralmente é 08 * 4096 se eu entendi corretamente. Na verdade, há outra unidade para os dados criados mais adiante

Se eu entendi corretamente, a lógica do código SSM.cpp, conforme explicado no início, é executar o estado de salvar ao vivo. IE o tamanho total não é conhecido. Portanto, pode haver várias unidades de memória gravadas. Se houver apenas uma unidade de memória bruta, então, sim, você poderá deduzir o tamanho da VM. Quilometragem varia

Extrair desde o início do arquivo

 * 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);
}

Ele também notou, como Bridgey, que Units começam com ascii "Unit", mas também que a última unidade termina com "TheEnd"

Ele analisou parte da estrutura do arquivo SAV com base na estrutura da UNIT descrita no SSMInternal.h aqui: cabeçalho do opensource do virtualbox

    
por 11.05.2018 / 07:21