Last active
April 29, 2023 14:56
-
-
Save tandasat/960653187242cf4615f373f3d0853225 to your computer and use it in GitHub Desktop.
Part of snapshot taking code in C
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file Ide.c | |
| * @author Satoshi Tanda (tanda.sat@gmail.com) | |
| * @brief Write data into the IDE storage device. | |
| * @date 2022-01-16 | |
| * | |
| * @copyright Copyright (c) 2022, Satoshi Tanda. All rights reserved. | |
| * | |
| */ | |
| #include "Ide.h" | |
| #include "HostUtils.h" | |
| // | |
| // See | |
| // https://wiki.osdev.org/PCI_IDE_Controller#Read.2FWrite_From_ATA_Drive | |
| // https://wiki.osdev.org/ATA_PIO_Mode | |
| // | |
| #define IDE_SECTOR_SIZE 512 | |
| #define IDE_IO_ADDR_BASE 0x1f0 | |
| #define IDE_DATA (IDE_IO_ADDR_BASE + 0) | |
| #define IDE_SECCOUNT0 (IDE_IO_ADDR_BASE + 2) | |
| #define IDE_SECCOUNT1 (IDE_IO_ADDR_BASE + 2) | |
| #define IDE_LBA0 (IDE_IO_ADDR_BASE + 3) | |
| #define IDE_LBA3 (IDE_IO_ADDR_BASE + 3) | |
| #define IDE_LBA1 (IDE_IO_ADDR_BASE + 4) | |
| #define IDE_LBA4 (IDE_IO_ADDR_BASE + 4) | |
| #define IDE_LBA2 (IDE_IO_ADDR_BASE + 5) | |
| #define IDE_LBA5 (IDE_IO_ADDR_BASE + 5) | |
| #define IDE_HDDEVSEL (IDE_IO_ADDR_BASE + 6) | |
| #define IDE_COMMAND (IDE_IO_ADDR_BASE + 7) | |
| #define IDE_COMMAND_WRITE_PIO 0x30 | |
| #define IDE_COMMAND_CACHE_FLUSH 0xe7 | |
| #define IDE_STATUS (IDE_IO_ADDR_BASE + 7) | |
| #define IDE_STATUS_BUSY (1 << 7) | |
| #define IDE_CONTROL 0x3f6 | |
| #define IDE_CONTROL_NIEN (1 << 1) | |
| #define IDE_CONTROL_SRST (1 << 2) | |
| /** | |
| * @brief Wait until the IDE complete its processing and ready for another request. | |
| */ | |
| STATIC | |
| VOID | |
| IdeWait ( | |
| VOID | |
| ) | |
| { | |
| while (IoRead8(IDE_STATUS) & IDE_STATUS_BUSY); | |
| } | |
| /** | |
| * @brief Write data into an IDE-related IO port and wait for IDE to complete it. | |
| * | |
| * @param Port - The IO port address to write. | |
| * @param Value - The value to write to the IO port. | |
| */ | |
| STATIC | |
| VOID | |
| IdeWriteRegister ( | |
| IN UINT64 Port, | |
| IN UINT8 Value | |
| ) | |
| { | |
| IoWrite8(Port, Value); | |
| IdeWait(); | |
| } | |
| STATIC BOOLEAN mIdeHasBeenReset = FALSE; | |
| /** | |
| * @brief Writes one sector (512 bytes) at the specified LBA of the master IDE device. | |
| * | |
| * @param LogicalBlockAddress - The logical block address to start writing. | |
| * @param Data - The pointer to the data to write. | |
| * @param DataSize - The size of the data to write in bytes. | |
| */ | |
| STATIC | |
| VOID | |
| IdeWriteDisk ( | |
| UINT64 LogicalBlockAddress, | |
| CONST UINT8* Data, | |
| UINT64 DataSize | |
| ) | |
| { | |
| MV_HOST_ASSERT((DataSize % 2) == 0); | |
| // | |
| // Reset the device on the first use, or when it is left as busy. | |
| // | |
| if ((mIdeHasBeenReset == FALSE) || | |
| (IoRead8(IDE_STATUS) & IDE_STATUS_BUSY)) | |
| { | |
| IoWrite8(IDE_CONTROL, IDE_CONTROL_SRST); | |
| IdeWriteRegister(IDE_CONTROL, 0); | |
| mIdeHasBeenReset = TRUE; | |
| } | |
| // | |
| // Disable interrupts. | |
| // | |
| IdeWriteRegister(IDE_CONTROL, IDE_CONTROL_NIEN); | |
| // | |
| // Select master drive with LBA addressing mode. | |
| // | |
| IdeWriteRegister(IDE_HDDEVSEL, 0xe0); | |
| // | |
| // Set up to write one sector with the LBA specified. | |
| // | |
| IdeWriteRegister(IDE_SECCOUNT1, 0); | |
| IdeWriteRegister(IDE_LBA5, (LogicalBlockAddress >> (8 * 5)) & 0xff); | |
| IdeWriteRegister(IDE_LBA4, (LogicalBlockAddress >> (8 * 4)) & 0xff); | |
| IdeWriteRegister(IDE_LBA3, (LogicalBlockAddress >> (8 * 3)) & 0xff); | |
| IdeWriteRegister(IDE_SECCOUNT0, 1); | |
| IdeWriteRegister(IDE_LBA2, (LogicalBlockAddress >> (8 * 2)) & 0xff); | |
| IdeWriteRegister(IDE_LBA1, (LogicalBlockAddress >> (8 * 1)) & 0xff); | |
| IdeWriteRegister(IDE_LBA0, (LogicalBlockAddress >> (8 * 0)) & 0xff); | |
| // | |
| // Send the 28-bit LBA PIO write request command and write data onto the disk. | |
| // Note that the large IDE devices cannot work with this. Change this to | |
| // IDE_COMMAND_WRITE_PIO_EX and IDE_COMMAND_CACHE_FLUSH_EX if desired. | |
| // | |
| IdeWriteRegister(IDE_COMMAND, IDE_COMMAND_WRITE_PIO); | |
| for (UINT64 i = 0; i < DataSize; i += sizeof(UINT16)) | |
| { | |
| IoWrite16(IDE_DATA, *(UINT16*)(Data + i)); | |
| } | |
| IdeWriteRegister(IDE_COMMAND, IDE_COMMAND_CACHE_FLUSH); | |
| } | |
| VOID | |
| IdeWrite4Kb ( | |
| IN UINT64 Offset, | |
| IN CONST UINT8* Data | |
| ) | |
| { | |
| // | |
| // Write sectors (512 bytes for each) one by one while convert the offset to | |
| // the LBA. | |
| // | |
| for (UINT64 i = 0; i < SIZE_4KB / IDE_SECTOR_SIZE; i++) | |
| { | |
| IdeWriteDisk(Offset / IDE_SECTOR_SIZE + i, | |
| Data + IDE_SECTOR_SIZE * i, | |
| IDE_SECTOR_SIZE); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file Ide.h | |
| * @author Satoshi Tanda (tanda.sat@gmail.com) | |
| * @brief Write data into the IDE storage device. | |
| * @date 2022-01-16 | |
| * | |
| * @copyright Copyright (c) 2022, Satoshi Tanda. All rights reserved. | |
| * | |
| */ | |
| #pragma once | |
| #include "Common/Common.h" | |
| /** | |
| * @brief Writes 4KB of data onto at the specified offset of the IDE master device. | |
| * | |
| * @param Offset - The offset in the device to start writing. | |
| * @param Data - The pointer to 4KB data to write to the device. | |
| */ | |
| VOID | |
| IdeWrite4Kb ( | |
| IN UINT64 Offset, | |
| IN CONST UINT8* Data | |
| ); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file Snapshot.c | |
| * @author Satoshi Tanda (tanda.sat@gmail.com) | |
| * @brief Takes the snapshot of the guest onto a disk. | |
| * @date 2022-01-16 | |
| * | |
| * @copyright Copyright (c) 2022, Satoshi Tanda. All rights reserved. | |
| * | |
| */ | |
| #include "Snapshot.h" | |
| #include "Ide.h" | |
| #include "HostUtils.h" | |
| #include "Common/VtxUtils.h" | |
| CONST SNAPSHOT_MEMORY_RANGE* gMemoryRanges; | |
| UINT64 gRangeCount; | |
| VOID | |
| TakeSnapshot ( | |
| IN CONST VMEXIT_CONTEXT* VmExitContext | |
| ) | |
| { | |
| SNAPSHOT_HEADER snapshotHeader; | |
| UINT64 offset; | |
| UINT64 pageBase; | |
| // | |
| // The first 4KB of the snapshot file is a header containing memory ranges | |
| // and register values. Capture them and write it into the disk. | |
| // | |
| offset = 0; | |
| ZeroMem(&snapshotHeader, sizeof(snapshotHeader)); | |
| snapshotHeader.Magic = SNAPSHOT_SIGNATURE; | |
| CopyMem(&snapshotHeader.MemoryRanges[0], gMemoryRanges, sizeof(*gMemoryRanges) * gRangeCount); | |
| snapshotHeader.Registers.Gdtr.Limit = (UINT16)VmxRead(VMCS_GUEST_GDTR_LIMIT); | |
| snapshotHeader.Registers.Gdtr.Base = VmxRead(VMCS_GUEST_GDTR_BASE); | |
| snapshotHeader.Registers.Idtr.Limit = (UINT16)VmxRead(VMCS_GUEST_IDTR_LIMIT); | |
| snapshotHeader.Registers.Idtr.Base = VmxRead(VMCS_GUEST_IDTR_BASE); | |
| snapshotHeader.Registers.Es = (UINT16)VmxRead(VMCS_GUEST_ES_SELECTOR); | |
| snapshotHeader.Registers.Cs = (UINT16)VmxRead(VMCS_GUEST_CS_SELECTOR); | |
| snapshotHeader.Registers.Ss = (UINT16)VmxRead(VMCS_GUEST_SS_SELECTOR); | |
| snapshotHeader.Registers.Ds = (UINT16)VmxRead(VMCS_GUEST_DS_SELECTOR); | |
| snapshotHeader.Registers.Fs = (UINT16)VmxRead(VMCS_GUEST_FS_SELECTOR); | |
| snapshotHeader.Registers.Gs = (UINT16)VmxRead(VMCS_GUEST_GS_SELECTOR); | |
| snapshotHeader.Registers.Ldtr = (UINT16)VmxRead(VMCS_GUEST_LDTR_SELECTOR); | |
| snapshotHeader.Registers.Tr = (UINT16)VmxRead(VMCS_GUEST_TR_SELECTOR); | |
| snapshotHeader.Registers.Efer = VmxRead(VMCS_GUEST_EFER); | |
| snapshotHeader.Registers.SysenterCs = VmxRead(VMCS_GUEST_SYSENTER_CS); | |
| snapshotHeader.Registers.Cr0 = VmxRead(VMCS_GUEST_CR0); | |
| snapshotHeader.Registers.Cr3 = VmxRead(VMCS_GUEST_CR3); | |
| snapshotHeader.Registers.Cr4 = VmxRead(VMCS_GUEST_CR4); | |
| snapshotHeader.Registers.FsBase = VmxRead(VMCS_GUEST_FS_BASE); | |
| snapshotHeader.Registers.GsBase = VmxRead(VMCS_GUEST_GS_BASE); | |
| snapshotHeader.Registers.LdtrBase = VmxRead(VMCS_GUEST_LDTR_BASE); | |
| snapshotHeader.Registers.TrBase = VmxRead(VMCS_GUEST_TR_BASE); | |
| snapshotHeader.Registers.Rsp = VmxRead(VMCS_GUEST_RSP); | |
| snapshotHeader.Registers.Rip = VmxRead(VMCS_GUEST_RIP); | |
| snapshotHeader.Registers.Rflags = VmxRead(VMCS_GUEST_RFLAGS); | |
| snapshotHeader.Registers.SysenterEsp = VmxRead(VMCS_GUEST_SYSENTER_ESP); | |
| snapshotHeader.Registers.SysenterEip = VmxRead(VMCS_GUEST_SYSENTER_EIP); | |
| snapshotHeader.Registers.Rax = VmExitContext->Guest.StackSaved->Rax; | |
| snapshotHeader.Registers.Rbx = VmExitContext->Guest.StackSaved->Rbx; | |
| snapshotHeader.Registers.Rcx = VmExitContext->Guest.StackSaved->Rcx; | |
| snapshotHeader.Registers.Rdx = VmExitContext->Guest.StackSaved->Rdx; | |
| snapshotHeader.Registers.Rdi = VmExitContext->Guest.StackSaved->Rdi; | |
| snapshotHeader.Registers.Rsi = VmExitContext->Guest.StackSaved->Rsi; | |
| snapshotHeader.Registers.Rbp = VmExitContext->Guest.StackSaved->Rbp; | |
| snapshotHeader.Registers.R8 = VmExitContext->Guest.StackSaved->R8; | |
| snapshotHeader.Registers.R9 = VmExitContext->Guest.StackSaved->R9; | |
| snapshotHeader.Registers.R10 = VmExitContext->Guest.StackSaved->R10; | |
| snapshotHeader.Registers.R11 = VmExitContext->Guest.StackSaved->R11; | |
| snapshotHeader.Registers.R12 = VmExitContext->Guest.StackSaved->R12; | |
| snapshotHeader.Registers.R13 = VmExitContext->Guest.StackSaved->R13; | |
| snapshotHeader.Registers.R14 = VmExitContext->Guest.StackSaved->R14; | |
| snapshotHeader.Registers.R15 = VmExitContext->Guest.StackSaved->R15; | |
| IdeWrite4Kb(offset, (void*)&snapshotHeader); | |
| offset += sizeof(snapshotHeader); | |
| // | |
| // According with the memory range information, write the contents of memory | |
| // for each 4KB onto the disk. This is not limited to the guest memory and | |
| // does include hypervisor-owned memory which is unused for the purpose of | |
| // fuzzing. | |
| // | |
| pageBase = 0; | |
| for (UINT64 i = 0; i < gRangeCount; ++i) | |
| { | |
| CONST SNAPSHOT_MEMORY_RANGE* range; | |
| range = &gMemoryRanges[i]; | |
| MV_HOST_INFO("%16llx - %16llx : Processing %llx pages", | |
| range->PageBase, | |
| range->PageBase + range->PageCount * SIZE_4KB, | |
| range->PageCount); | |
| for (UINT64 pageCount = 0; pageCount < range->PageCount; ++pageCount) | |
| { | |
| if ((pageCount != 0) && (pageCount % 1000) == 0) | |
| { | |
| MV_HOST_INFO("... done with %llu / %llu pages", | |
| pageCount, | |
| range->PageCount); | |
| } | |
| pageBase = range->PageBase + (SIZE_4KB * pageCount); | |
| IdeWrite4Kb(pageBase + offset, (const void*)pageBase); | |
| } | |
| } | |
| // | |
| // Write the end marker for the ease of reviewing the contents of the snapshot | |
| // file. | |
| // | |
| IdeWrite4Kb(pageBase + offset + SIZE_4KB, (const void*)"END_OF_FILE"); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * @file Snapshot.h | |
| * @author Satoshi Tanda (tanda.sat@gmail.com) | |
| * @brief Takes the snapshot of the guest onto a disk. | |
| * @date 2022-01-16 | |
| * | |
| * @copyright Copyright (c) 2022, Satoshi Tanda. All rights reserved. | |
| * | |
| */ | |
| #pragma once | |
| #include "Common/Common.h" | |
| #include "VmExitContext.h" | |
| /** | |
| * @brief Writes the snapshot at the offset 0 of the IDE master device. | |
| * | |
| * @param VmExitContext - The pointer to the VM-exit context. | |
| */ | |
| VOID | |
| TakeSnapshot ( | |
| IN CONST VMEXIT_CONTEXT* VmExitContext | |
| ); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment