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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
//! A library for injecting shared libraries into running processes via ptrace.
//!
//! # Platform support
//!
//! This library currently only supports x64 \*nix systems, mainly because that's
//! what I have. Support for other architectures should be possible - the only
//! barrier being that I cannot test it. In theory though, it would just be
//! a matter of re-writing the shellcode for each architecture and selecting the
//! correct one with conditional compilation.
//!
//! For Windows, use other projects like [`dll-syringe`][1].
//!
//! # Example
//!
//! ```no_run
//! use std::{process::Command, path::PathBuf};
//! use ptrace_inject::{Injector, Process};
//!
//! # fn main() -> eyre::Result<()> {
//! let library = PathBuf::from("path/to/library.so");
//!
//! // Spawn a new process and inject the library into it.
//! let target = Command::new("target-process");
//! Injector::spawn(target)?.inject(&library)?;
//!
//! // Or attach to an existing process.
//! let proc = Process::by_name("target-process")?.expect("to find target process");
//! Injector::attach(proc)?.inject(&library)?;
//! # Ok(())
//! # }
//! ```
//!
//! # Ptrace note
//!
//! This library was inspired by [`linux-inject`][2]. As noted by that project:
//!
//! > On many Linux distributions, the kernel is configured by default to
//! > prevent any process from calling ptrace() on another process that it did
//! > not create (e.g. via `fork()`). This is a security feature meant to prevent
//! > exactly the kind of mischief that this tool causes. You can temporarily
//! > disable it until the next reboot using the following command:
//! > ```text
//! > echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
//! > ```
//!
//! This library uses [`log`][3] for logging.
//!
//! [1]: https://crates.io/crates/dll-syringe
//! [2]: https://github.com/gaffe23/linux-inject
//! [3]: https://crates.io/crates/log
use ;
use Injection;
pub use LibcAddrs;
pub use Process;
/*
/// Any error this library might encounter.
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error("couldn't read the procfs filesystem (`/proc`)")]
ProcFs(#[from] procfs::ProcError),
#[error("interacting with the traced process via ptrace failed")]
Ptrace(#[from] pete::Error),
#[error("failed to get information about the locally loaded libc via `dlopen` and related functions")]
LocalDlopen(#[from] libloading::Error),
#[error("couldn't get absolute path from given library path")]
InvalidLibraryPath(#[source] std::io::Error),
#[error("no executable region was found in the target process' address space")]
NoExecutableRegionInTarget,
#[error("the target process does not appear to have the libc library loaded")]
TargetDoesNotHaveLibc,
#[error("calling `malloc` in the target process failed")]
InjectedMalloc,
#[error("calling `dlopen` in the target process failed")]
InjectedDlopen,
#[error("the shellcode was meant to trap, but the target quietly exited instead")]
ShellcodeDidntTrap,
#[error("the target exited quietly as soon as we started tracing it")]
TargetExitedImmediately,
#[error("the target sent an unexpected signal while running the shellcode")]
UnexpectedSignal(pete::Signal),
}
/// A type alias for `Result<T, Error>`.
pub type Result<T> = std::result::Result<T, Error>;
*/
/// A type capable of loading libraries into a ptrace'd target process.
///
/// When this struct is dropped it will detach from the target process.