
Generate Proxy DLLs in Rust
cargo install rustdllproxy
В настоящее время этот крейт поддерживает только стандартный PE-формат DLL.
Rustdllproxy поставляется с двумя подкомандами:
| Команда | Назначение |
|---|
rustdllproxy new | Сгенерировать новый крейт-cdylib-прокси из одной или нескольких существующих DLL. |
rustdllproxy build | Синхронизировать файл .def с src/lib.rs и собрать крейт. |
rustdllproxy --help # общая справка
rustdllproxy new --help # флаги генерации
rustdllproxy build --help # флаги сборки
Перед генерацией крейта решите, как должен работать ваш прокси. Типичный подход — перехват через порядок поиска (search order hijacking): вы переименовываете целевую DLL, например в target_.dll, и используете скомпилированный прокси как target.dll. Это создаёт поток вида binary -> target.dll -> target_.dll
Дальнейшие шаги зависят от вашего сценария использования. Если же вам нужно переименовать проксируемую DLL, обновите сгенерированный файл .def соответствующим образом.
rustdllproxy new -p path/to/target_.dll -n my_proxy
Совет: rustdllproxy — это CLI, построенный на clap. Выполните rustdllproxy --help, чтобы увидеть все опции и флаги.
Библиотека макросов поддерживает 3 основных типа хуков: prehook, posthook и fullhook.
Замените директиву #[no_mangle] на макрос хука (оставьте завершающий комментарий //<dllname>.dll на месте)
#[prehook("dllbeingproxied.dll", "function_name")] //dllbeingproxied.dll
Заполните сигнатуру функции (объявите входные параметры как mut, чтобы иметь возможность их изменять)
Соберите проект с помощью rustdllproxy build.
prehookВыполняет код до оригинальной функции. Позволяет добавить функциональность или изменить входные переменные.
#[prehook("target.dll", "my_function")] //target.dll
fn my_function(mut param1: i32, mut param2: &str) {
// Ваш код здесь — выполняется до оригинальной функции
param1 *= 2; // При необходимости измените параметры
}
posthookВыполняет код после оригинальной функции. Просматривайте и изменяйте возвращаемое значение с помощью магической переменной ret.
#[posthook("target.dll", "calculate")] //target.dll
fn calculate(input: i32) -> i32 {
// Сначала выполняется оригинальная функция
// Затем выполняется ваш код с доступом к 'ret'
ret = ret * 2; // Изменение возвращаемого значения
}
Примечание: Переменная
retавтоматически определяется как изменяемая. Если она не нужна, её можно не использовать.
fullhookПредоставляет полный контроль над выполнением функции. Управляйте возвращаемым значением и вызовом функции вручную.
#[fullhook("target.dll", "do_multi_add")] //target.dll
fn do_multi_add(mut a: i32, mut b: i32, mut c: i32) -> i32 {
// Предварительная обработка
a += 10;
b += 20;
// Вызов оригинальной функции с помощью магической func()
let mut return_value: i32 = func(a, b, c);
// Постобработка
return_value *= 2;
// Необходимо явно вернуть значение
return_value
}
Запускайте из каталога прокси-крейта (или передайте его первым аргументом):
rustdllproxy build [PATH] [--profile <name>] [--no-build] [-- <extra cargo args>]
| Флаг | По умолчанию | Действие |
|---|---|---|
PATH | . | Путь к корню прокси-крейта. |
--profile <name> | release | Профиль сборки Cargo (release, dev, пользовательский). |
--no-build | выкл | Перегенерировать файл .def, но пропустить cargo build. |
-- <args> | — | Передаётся в cargo build без изменений. |
.def полностью перегенерируется при каждой сборке, ручные изменения будут перезаписаны. Если вам нужно внести ручные правки в процесс сборки rustdllproxy, для этого можно использовать cargo..def и имена хуков для определения имени проксируемой DLL перед сборкой. Если информации недостаточно, будет выдана ошибка с объяснением, как восстановить ситуацию.Допустим, вы хотите изменить office.dll, используемую в офисном ПО, через перехват порядка поиска DLL:
# Переименуйте оригинальную DLL
mv office.dll office_.dll
rustdllproxy new -p office_.dll -n office_proxy
#[prehook("office_.dll", "open_window")] //office_.dll
fn open_window() {
// Ваш пользовательский код здесь...
println!("Окно сейчас откроется!");
}
cd office_proxy
rustdllproxy build
Файлы сборки находятся в каталоге
/target
Можно проксировать несколько целевых DLL одним крейтом. Эта возможность используется редко и имеет ряд важных ограничений.
При объединении нескольких DLL:
Примечания к релизам находятся в CHANGELOG.md.
Вклад приветствуется! Пожалуйста, свободно создавайте issue и pull request.