2个不稳定版本
0.2.0 | 2023年6月16日 |
---|---|
0.1.0 | 2023年4月13日 |
在 过程宏 中排名第824
21KB
380 行
mutself
创建自修改的可执行文件。
目的
// TODO
用法
mutself::mutself! {
DATA = "alice"
}
fn main() {
if let Some(arg) = std::env::args().nth(1) {
println!("Hello {}", &arg);
mutself("new.exe", Some(&arg)).unwrap();
} else {
println!("Hello {}", &*DATA);
}
}
运行我们的可执行文件会得到
$ cargo run
Hello alice
现在带有参数
$ cargo run -- bob
Hello bob
# This creates another executable named 'new.exe'
$ new
Hello bob
是的,数据大小可以改变。
$ cargo run -- someverylongstringthatwouldntfitinsidethespace
如何?
库解析正在运行的可执行文件并更改值,然后输出一个新的可执行文件。
深入了解
简单来说:对 #[link_section = ".custom"]
属性的滥用。没有汇编修复或任何其他操作。在 mutself!
宏中的数据条目存储在可执行文件的自定义部分。运行的代码只有一个指向该部分顶端的指针(该指针始终有效,因为自定义部分在虚拟内存中始终位于同一位置)。该部分中的所有条目都相对于这个指针进行引用。
内存布局如下(考虑对齐)
#ENTRY0 size (usize) <-- hardcoded pointer
#ENTRY0
#ENTRY1 size (usize)
#ENTRY1
// And so on
由于每个条目都是相对于基址定义的,因此它们可以自由地增长或缩小,而不必担心运行时代码无法访问它们。
限制
初始化表达式必须是可以内联存储的类型(例如,不是切片)。切片只会在自定义可执行文件部分存储一个ptr和一个大小,引用 .data
,这意味着我们无法修改它。
依赖项
~4MB
~74K SLoC