Skip to content

Write memory - #41

Merged
bjorn3 merged 13 commits into
headcrab-rs:masterfrom
nbaksalyar:writemem
Aug 23, 2020
Merged

Write memory#41
bjorn3 merged 13 commits into
headcrab-rs:masterfrom
nbaksalyar:writemem

Conversation

@nbaksalyar

@nbaksalyar nbaksalyar commented Jul 24, 2020

Copy link
Copy Markdown
Member

Implements #7

  • Write memory using process_vm_write on Linux.
  • Write memory using ptrace on Linux.
  • Automatically choose mem write strategy on Linux.
  • Write memory using mach_vm_write on macOS.
  • Add tests for writing to write-protected pages.

Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs
@nbaksalyar nbaksalyar changed the title Write memory Write memory [WIP] Jul 24, 2020
Comment thread src/target/linux/mod.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
}

/// Executes the memory write operation.
pub unsafe fn apply(self) -> Result<(), Box<dyn std::error::Error>> {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is safe as it can only crash the remote process, right?

Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
@JJendryka

Copy link
Copy Markdown
Contributor

I can help with adding test for writing to write-protected pages if you want?

@nbaksalyar

Copy link
Copy Markdown
Member Author

I can help with adding test for writing to write-protected pages if you want?

No worries, I should finish this today. :) Thanks!

nbaksalyar and others added 9 commits August 19, 2020 00:17
- Use immutable ref for lifetime invariance in WriteMemory
- Allow to pass slices to write

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
- Use ptr::read_volatile for volatile read operations
- Simpler capacity calc expression

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
Memory write operations are split into those which are applicable
to memory pages which are writable, and those which need to resort to ptrace for
writing to write-protected memory pages.
Use a single type for both writing and reading memory instead of a trait.
This approach simplifies generic memory operations (like splitting memory ops
based on page permissions or splitting memory ops on page boundary), while
still leaving place for introducing write- or read- specific functions in the
future.

This commit also changes the approach used for splitting write operations into
word-sized groups. Instead of allocating a new vector, we now use a custom iterator.
This should reduce a number of unnecessary allocations.

Finally, this commit also introduces a delay before reading written values in
ptrace writing tests.
- Add `LinuxTarget::write()`
- Also make `WriteMem::apply` safe as it operates only on the debuggee process.
@nbaksalyar nbaksalyar changed the title Write memory [WIP] Write memory Aug 22, 2020
Comment thread src/target/linux/memory.rs Outdated
Comment thread src/target/linux/memory.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/linux/writemem.rs Outdated
Comment thread src/target/macos/writemem.rs Outdated
Comment thread src/target/macos/writemem.rs Outdated
- Reduce `linux::MemoryOp` visibility to `pub(crate)`
- Improve doc comments.
- Make macOS `WriteMem` conforming to Linux API.

Co-authored-by: bjorn3 <bjorn3@users.noreply.github.com>
@nbaksalyar

nbaksalyar commented Aug 22, 2020

Copy link
Copy Markdown
Member Author

Hmm, writemem tests fail sporadically. This seems to be caused by fork deadlock (pthread_cond_wait originating in LinuxTarget::memory_maps -> procfs -> lazy_static). I'm fixing this.

Edit:
This is caused by std::sync::Once being fork-unsafe, ref: rust-lang/rust#43448

lazy_static can fail if it's used in a forked process, so this commit uses
an explicit apply_ptrace() instead of reading debuggee memory maps and determining
what memory write operation to use.
This is a temporary workaround until we find a better approach.
@nbaksalyar

Copy link
Copy Markdown
Member Author

This is caused by std::sync::Once being fork-unsafe

It looks like there's no quick fix for this. I've used a workaround - the test that was failing now uses an explicit apply_ptrace() instead of reading memory maps to determine which memory write operation to use. This is a bit fragile though, and we should keep an eye on this. Probably, a better long-term solution would be not to rely on fork for tests.

@bjorn3
bjorn3 merged commit 8222149 into headcrab-rs:master Aug 23, 2020
@nbaksalyar
nbaksalyar deleted the writemem branch August 23, 2020 11:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants