pub struct MemBlock<'a> {
pub range: Range<u64>,
pub allocation_base: u64,
pub allocation_protect: u32,
pub state: u32,
pub protect: u32,
pub type_: u32,
pub data: &'a [u8],
}
Expand description
Fields§
§range: Range<u64>
Range over the start/end address of the memory region.
allocation_base: u64
The base of the allocation that gave life to this memory region.
allocation_protect: u32
The page protection used at allocation time.
state: u32
The state of the memory region. See State.
protect: u32
The page protection currently applied to the memory region.
type_: u32
The type of memory region. See Type.
data: &'a [u8]
The MemBlock
’s data.
Implementations§
Source§impl<'a> MemBlock<'a>
impl<'a> MemBlock<'a>
Sourcepub fn is_readable(&self) -> bool
pub fn is_readable(&self) -> bool
Is the memory region readable?
Sourcepub fn is_writable(&self) -> bool
pub fn is_writable(&self) -> bool
Is the memory region writable?
Sourcepub fn is_executable(&self) -> bool
pub fn is_executable(&self) -> bool
Is the memory region executable?
Sourcepub fn state_as_str(&self) -> &str
pub fn state_as_str(&self) -> &str
Stringify the memory region state.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}
Sourcepub fn type_as_str(&self) -> &str
pub fn type_as_str(&self) -> &str
Stringify the memory region type.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}
Sourcepub fn protect_as_str(&self) -> String
pub fn protect_as_str(&self) -> String
Stringify the memory region protection.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}
Sourcepub fn data_from(&self, addr: u64) -> Option<&[u8]>
pub fn data_from(&self, addr: u64) -> Option<&[u8]>
Get a slice over the MemBlock
’s data from its absolute address.
If the dump had a memory block of size 4 bytes starting at address
0xdead then calling data_from(0xdead+1)
returns a slice over the
last 3 bytes of the memory block. This is useful when you don’t need
to reason about offsets.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}
Sourcepub fn start_addr(&self) -> u64
pub fn start_addr(&self) -> u64
Get the address of where this MemBlock
was at in memory.
Sourcepub fn end_addr(&self) -> u64
pub fn end_addr(&self) -> u64
Get the end address of where this MemBlock
was at in memory.
Note that the underlying range is not inclusive, so this address is pointing right after the last byte’s address.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}
Sourcepub fn len(&self) -> u64
pub fn len(&self) -> u64
Get the size of the MemBlock
.
Note that a region of memory can exists without having any data
associated with it. This method returns the range len, not data
’s len.
An example is a memory region mapped as PAGE_NOACCESS
; it exists in
the address space but has no content.
Examples found in repository?
152fn main() -> Result<(), String> {
153 // If we don't have any arguments, display the help.
154 if env::args().len() == 1 {
155 help();
156 return Ok(());
157 }
158
159 // Parse the command line arguments.
160 let cli = parse_args()?;
161
162 // Let's try to parse the dump file specified by the user.
163 let dump = UserDumpParser::new(cli.dump_path).map_err(|e| e.to_string())?;
164
165 // Do we want to display modules?
166 if cli.show_mods || cli.show_all {
167 println!("Loaded modules:");
168
169 // Iterate through the module and display their base address and path.
170 for (base, module) in dump.modules() {
171 println!("{:016x}: {}", base, module.path.display());
172 }
173 }
174
175 // Do we want the memory map?
176 if cli.show_memmap || cli.show_all {
177 println!("Memory map:");
178
179 // Iterate over the memory blocks.
180 for block in dump.mem_blocks().values() {
181 // Grab the string representation about its state, type, protection.
182 let state = block.state_as_str();
183 let type_ = block.type_as_str();
184 let protect = block.protect_as_str();
185
186 // Print it all out.
187 print!(
188 "{:016x} {:016x} {:016x} {:11} {:11} {:22}",
189 block.range.start,
190 block.range.end,
191 block.len(),
192 type_,
193 state,
194 protect
195 );
196
197 // Do we have a module that exists at this address?
198 let module = dump.get_module(block.range.start);
199
200 // If we do, then display its name / path.
201 if let Some(module) = module {
202 print!(
203 " [{}; \"{}\"]",
204 module.file_name().unwrap(),
205 module.path.display()
206 );
207 }
208
209 // Do we have data with this block? If so display the first few
210 // bytes.
211 if block.data.len() >= 4 {
212 print!(
213 " {:02x} {:02x} {:02x} {:02x}...",
214 block.data[0], block.data[1], block.data[2], block.data[3]
215 );
216 }
217
218 println!();
219 }
220 }
221
222 // Do we want threads?
223 if cli.show_threads || cli.show_all {
224 println!("Threads:");
225
226 // Grab the foreground tid.
227 let foreground_tid = dump.foreground_tid;
228
229 // Iterate through all the threads.
230 for (tid, thread) in dump.threads() {
231 // If the user specified a pid..
232 if let Some(wanted_tid) = cli.thread {
233 // .. skip an threads that don't match what the user wants..
234 if *tid != wanted_tid {
235 continue;
236 }
237
238 // Otherwise we keep going.
239 }
240
241 // If the user only wants the main thread, and we haven't found it,
242 // skip this thread until we find it.
243 if cli.show_foreground_thread
244 && *tid != foreground_tid.expect("no foreground thread id in dump")
245 {
246 continue;
247 }
248
249 // Print out the thread info.
250 println!("TID {}, TEB {:016x}", tid, thread.teb);
251 println!("Context:");
252 println!("{}", thread.context());
253 }
254 }
255
256 // Do we want to dump memory?
257 if let Some(address) = cli.address {
258 println!("Memory:");
259
260 // Try to find a block that contains `address`.
261 let block = dump.get_mem_block(address);
262
263 // If we have one..
264 if let Some(block) = block {
265 // .. and it has data, dump it..
266 if let Some(data) = block.data_from(address) {
267 println!("{:016x} -> {:016x}", address, block.end_addr());
268 hexdump(address, data.iter().take(0x1_00).copied());
269 }
270 // .. otherwise, inform the user..
271 else {
272 println!(
273 "The memory at {:016x} (from block {:016x} -> {:016x}) has no backing data",
274 address, block.range.start, block.range.end
275 );
276 }
277 }
278 // .. otherwise, inform he user.
279 else {
280 println!("No memory block were found for {:016x}", address);
281 }
282 }
283
284 // All right, enough for today.
285 Ok(())
286}