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, VmiError, driver::VmiRead};
/// 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: VmiRead,
{
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!(" {byte:02X}");
}
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(())
}