vmi_utils/
hexdump.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
use vmi_core::{AccessContext, VmiCore, VmiDriver, VmiError};

/// Representation of memory for hexdump.
pub enum Representation {
    /// Display memory as 8-bit values.
    U8,

    /// Display memory as 32-bit values.
    U32,

    /// Display memory as 64-bit values.
    U64,
}

/// Print a hexdump of memory at the given address.
pub fn hexdump<Driver>(
    vmi: &VmiCore<Driver>,
    ctx: impl Into<AccessContext>,
    count: usize,
    representation: Representation,
) -> Result<(), VmiError>
where
    Driver: VmiDriver,
{
    let ctx = ctx.into();

    let mut buf = vec![0u8; count];
    vmi.read(ctx, &mut buf)?;

    println!(
        "--------------------|  0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F | 0123456789ABCDEF"
    );
    for (index, chunk) in buf.chunks(16).enumerate() {
        print!(" 0x{:016X} |", ctx.address + (index * 16) as u64);

        match representation {
            Representation::U8 => {
                for &byte in chunk {
                    print!(" {:02X}", byte);
                }

                if chunk.len() < 16 {
                    for _ in 0..(16 - chunk.len()) {
                        print!("   ");
                    }
                }
            }

            Representation::U32 => {
                for dword in chunk.chunks(4) {
                    print!(
                        "  0x{:08X}",
                        u32::from_le_bytes([dword[0], dword[1], dword[2], dword[3]])
                    );
                }

                if (chunk.len() % 4) != 0 {
                    for _ in 0..(4 - (chunk.len() % 4)) {
                        print!("            ");
                    }
                }
            }

            Representation::U64 => {
                for qword in chunk.chunks(8) {
                    print!(
                        "      0x{:016X}",
                        u64::from_le_bytes([
                            qword[0], qword[1], qword[2], qword[3], qword[4], qword[5], qword[6],
                            qword[7],
                        ])
                    );
                }

                if (chunk.len() % 8) != 0 {
                    for _ in 0..(8 - (chunk.len() % 8)) {
                        print!("                        ");
                    }
                }
            }
        }

        print!(" | ");

        for &byte in chunk {
            print!(
                "{}",
                if byte.is_ascii_graphic() {
                    byte as char
                }
                else {
                    '.'
                }
            );
        }

        if chunk.len() < 16 {
            for _ in 0..(16 - chunk.len()) {
                print!(" ");
            }
        }

        println!();
    }

    Ok(())
}