1pub use iced_x86::OpAccess;
2use iced_x86::{
3 Decoder, DecoderOptions, FlowControl, Formatter, Instruction, InstructionInfoFactory,
4 NasmFormatter,
5};
6const HEXBYTES_COLUMN_BYTE_LENGTH: usize = 10;
7
8pub fn disassemble(addr: u64, bytes: &[u8]) -> Vec<String> {
10 let wordsize = 64;
11 let mut decoder = Decoder::with_ip(wordsize, bytes, addr, DecoderOptions::NONE);
12
13 let mut formatter = NasmFormatter::new();
17
18 formatter.options_mut().set_digit_separator("`");
20 formatter.options_mut().set_first_operand_char_index(10);
21
22 let mut instruction = Instruction::default();
24
25 let mut res = vec![];
31 while decoder.can_decode() {
32 decoder.decode_out(&mut instruction);
36
37 let mut output = String::new();
38 formatter.format(&instruction, &mut output);
39
40 let mut prefix = format!("{:016X} ", instruction.ip());
42 let start_index = (instruction.ip() - addr) as usize;
43 let instr_bytes = &bytes[start_index..start_index + instruction.len()];
44 for b in instr_bytes.iter() {
45 prefix.push_str(&format!("{:02X}", b));
46 }
47 if instr_bytes.len() < HEXBYTES_COLUMN_BYTE_LENGTH {
48 for _ in 0..HEXBYTES_COLUMN_BYTE_LENGTH - instr_bytes.len() {
49 prefix.push_str(" ");
50 }
51 }
52 prefix.push_str(&output);
53 res.push(prefix);
54 }
55 return res;
56}
57
58pub fn disassemble_print(addr: u64, bytes: &[u8]) {
59 for line in disassemble(addr, bytes) {
60 println!("{}", line);
61 }
62}
63
64use iced_x86::Register;
65use kvm_bindings::{kvm_regs, kvm_sregs};
66
67fn get_register_value(reg: Register, regs: &kvm_regs, sregs: &kvm_sregs) -> u64 {
68 match reg {
69 Register::None => 0,
70 Register::RAX => regs.rax,
72 Register::RBX => regs.rbx,
73 Register::RCX => regs.rcx,
74 Register::RDX => regs.rdx,
75 Register::RSI => regs.rsi,
76 Register::RDI => regs.rdi,
77 Register::RBP => regs.rbp,
78 Register::RSP => regs.rsp,
79 Register::R8 => regs.r8,
80 Register::R9 => regs.r9,
81 Register::R10 => regs.r10,
82 Register::R11 => regs.r11,
83 Register::R12 => regs.r12,
84 Register::R13 => regs.r13,
85 Register::R14 => regs.r14,
86 Register::R15 => regs.r15,
87 Register::RIP => regs.rip,
88
89 Register::EAX => regs.rax as u32 as u64,
91 Register::EBX => regs.rbx as u32 as u64,
92 Register::ECX => regs.rcx as u32 as u64,
93 Register::EDX => regs.rdx as u32 as u64,
94 Register::ESI => regs.rsi as u32 as u64,
95 Register::EDI => regs.rdi as u32 as u64,
96 Register::EBP => regs.rbp as u32 as u64,
97 Register::ESP => regs.rsp as u32 as u64,
98 Register::R8D => regs.r8 as u32 as u64,
99 Register::R9D => regs.r9 as u32 as u64,
100 Register::R10D => regs.r10 as u32 as u64,
101 Register::R11D => regs.r11 as u32 as u64,
102 Register::R12D => regs.r12 as u32 as u64,
103 Register::R13D => regs.r13 as u32 as u64,
104 Register::R14D => regs.r14 as u32 as u64,
105 Register::R15D => regs.r15 as u32 as u64,
106 Register::EIP => regs.rip as u32 as u64,
107
108 Register::AX => (regs.rax & 0xFFFF) as u64,
110 Register::BX => (regs.rbx & 0xFFFF) as u64,
111 Register::CX => (regs.rcx & 0xFFFF) as u64,
112 Register::DX => (regs.rdx & 0xFFFF) as u64,
113 Register::SI => (regs.rsi & 0xFFFF) as u64,
114 Register::DI => (regs.rdi & 0xFFFF) as u64,
115 Register::BP => (regs.rbp & 0xFFFF) as u64,
116 Register::SP => (regs.rsp & 0xFFFF) as u64,
117 Register::R8W => (regs.r8 & 0xFFFF) as u64,
118 Register::R9W => (regs.r9 & 0xFFFF) as u64,
119 Register::R10W => (regs.r10 & 0xFFFF) as u64,
120 Register::R11W => (regs.r11 & 0xFFFF) as u64,
121 Register::R12W => (regs.r12 & 0xFFFF) as u64,
122 Register::R13W => (regs.r13 & 0xFFFF) as u64,
123 Register::R14W => (regs.r14 & 0xFFFF) as u64,
124 Register::R15W => (regs.r15 & 0xFFFF) as u64,
125
126 Register::AL => (regs.rax & 0xFF) as u64,
128 Register::BL => (regs.rbx & 0xFF) as u64,
129 Register::CL => (regs.rcx & 0xFF) as u64,
130 Register::DL => (regs.rdx & 0xFF) as u64,
131 Register::SIL => (regs.rsi & 0xFF) as u64,
132 Register::DIL => (regs.rdi & 0xFF) as u64,
133 Register::BPL => (regs.rbp & 0xFF) as u64,
134 Register::SPL => (regs.rsp & 0xFF) as u64,
135 Register::R8L => (regs.r8 & 0xFF) as u64,
136 Register::R9L => (regs.r9 & 0xFF) as u64,
137 Register::R10L => (regs.r10 & 0xFF) as u64,
138 Register::R11L => (regs.r11 & 0xFF) as u64,
139 Register::R12L => (regs.r12 & 0xFF) as u64,
140 Register::R13L => (regs.r13 & 0xFF) as u64,
141 Register::R14L => (regs.r14 & 0xFF) as u64,
142 Register::R15L => (regs.r15 & 0xFF) as u64,
143
144 Register::AH => ((regs.rax >> 8) & 0xFF) as u64,
146 Register::BH => ((regs.rbx >> 8) & 0xFF) as u64,
147 Register::CH => ((regs.rcx >> 8) & 0xFF) as u64,
148 Register::DH => ((regs.rdx >> 8) & 0xFF) as u64,
149 Register::CS => sregs.cs.base,
151 Register::DS => sregs.ds.base,
152 Register::SS => sregs.ss.base,
153 Register::ES => sregs.es.base,
154 Register::FS => sregs.fs.base,
155 Register::GS => sregs.gs.base,
156
157 reg => panic!("unhandled memory access with register {:?}", reg),
159 }
160}
161
162pub fn get_memory_accesses(
164 instr: &Instruction,
165 regs: &kvm_regs,
166 sregs: &kvm_sregs,
167) -> Vec<(u64, OpAccess)> {
168 let mut factory = InstructionInfoFactory::new();
169 let info = factory.info(instr);
170 let page_size = crate::mem::PAGE_SIZE;
171 let page_mask = !(page_size - 1);
172 let mut accesses = Vec::new();
173 for mem in info.used_memory().iter() {
174 let base = get_register_value(mem.base(), regs, sregs) as i128;
175 let index = get_register_value(mem.index(), regs, sregs) as i128;
176 let scale = mem.scale() as i128;
177 let displacement = mem.displacement() as i128;
178 let segment = get_register_value(mem.segment(), regs, sregs) as i128;
179
180 let addr = (segment + base + (index * scale) + displacement) as u64;
181 let access = mem.access();
182 accesses.push((addr, access));
183
184 let size_bytes = mem.memory_size().size();
185 if size_bytes == 0 {
186 continue;
187 }
188 let end = addr.saturating_add(size_bytes as u64 - 1);
189 let mut next_page = (addr & page_mask).saturating_add(page_size);
190 while next_page <= end {
191 accesses.push((next_page, access));
192 next_page = next_page.saturating_add(page_size);
193 }
194 }
195 accesses
196}
197
198pub fn disassemble_memory_accesses(
199 data: &[u8],
200 regs: &kvm_regs,
201 sregs: &kvm_sregs,
202) -> Vec<(u64, OpAccess)> {
203 let mut decoder = Decoder::with_ip(64, data, regs.rip, DecoderOptions::NONE);
204 let mut instruction = Instruction::default();
205 if decoder.can_decode() {
206 decoder.decode_out(&mut instruction);
207 } else {
208 return vec![];
209 }
210 return get_memory_accesses(&instruction, regs, sregs);
211}
212
213pub fn is_control_flow(addr: u64, bytes: &[u8]) -> bool {
214 let mut decoder = Decoder::with_ip(64, bytes, addr, DecoderOptions::NONE);
215 let mut instruction = Instruction::default();
216 if !decoder.can_decode() {
217 return false;
218 }
219 decoder.decode_out(&mut instruction);
220 !matches!(instruction.flow_control(), FlowControl::Next)
221}