3个版本 (重大更新)
0.3.0 | 2024年8月11日 |
---|---|
0.2.0 | 2024年3月11日 |
0.1.0 | 2023年5月5日 |
在Unix API中排名195
每月下载量135
35KB
648 行
Plt-rs
变更日志
0.1.0 初始版本
0.2.0 完全重写
- 移除了hooking功能
- 减少了Linux/Android的冗余
- 文档化,并使库更加易用
0.3.0 易用性改进
- 将动态库中查找函数的功能推广为公共功能
- 添加了测试
- 在依赖项中不使用补丁版本
- ci/cd 依赖项更新
灵感来源
在开发此库时参考和受到启发的项目。
- [Kubo的Plthook] https://github.com/kubo/plthook
- [字节跳动的Bhook] https://github.com/bytedance/bhook
概述
通过爬取可执行文件动态加载的对象,我们可以hook导出的函数。PLT hooking通常是一个理想的解决方案,只要你能够保证Unix Like环境。此库不进行任何内联hooking,因此没有特定的架构(i686、arm等)汇编魔法,使得跨兼容性变得非常容易。确实存在架构特定的常量,但非常少。
为什么
视频游戏模组制作、逆向工程等
- 可以hook网络调用:recv / send
- 渲染调用:eglSwapBuffers / 视频游戏模组和外挂
- 应用程序加固和监控
- 防御性和进攻性使用
支持并测试了许多目标
突出显示的构建
看看代码吧
这里我们hook了我们的可执行文件对libc getpid的使用。有关完整示例,请参阅examples/hook_getpid.rs
,支持Android和32位。大部分代码用于实际指针替换以hook函数!
/// our own get pid function
unsafe fn getpid() -> u32 {
999
}
fn main() -> Result<()> {
let my_pid = unsafe { libc::getpid() };
println!("application pid is {my_pid}");
let executable_entry = find_executable().ok_or(anyhow!("unable to find target executable"))?;
println!("successfully identified executable");
let dyn_lib = DynamicLibrary::initialize(executable_entry)?;
println!("successfully initialied dynamic library for instrumentation");
let target_function =
dyn_lib.try_find_function("getpid").ok_or(anyhow!("unable to find getpid symbol"))?;
println!(
"successfully identified libc getpid offset: {:#X?}",
target_function.r_offset
);
let base_addr = dyn_lib.library().addr();
let plt_fn_ptr = (base_addr + target_function.r_offset as usize) as *mut *mut c_void;
let page_size = unsafe { libc::sysconf(libc::_SC_PAGE_SIZE) as usize };
let plt_page = ((plt_fn_ptr as usize / page_size) * page_size) as *mut c_void;
println!("page start for function is {plt_page:#X?}");
let _stored_address = unsafe {
// Set the memory page to read, write
let prot_res = libc::mprotect(plt_page, page_size, libc::PROT_WRITE | libc::PROT_READ);
if prot_res != 0 {
println!("protection res: {prot_res}");
return Err(anyhow!("mprotect to rw"));
}
// Replace the function address
let previous_address = std::ptr::replace(plt_fn_ptr, getpid as *mut _);
// Set the memory page protection back to read only
let prot_res = libc::mprotect(plt_page, page_size, libc::PROT_READ);
if prot_res != 0 {
return Err(anyhow!("mprotect to r"));
}
previous_address as *const c_void
};
let get_pid = unsafe { libc::getpid() };
println!("new pid is: {get_pid}");
Ok(())
}
application pid is 127765
successfully identified executable
successfully initialied dynamic library for instrumentation
successfully identified libc getpid offset: 0x7E460
page start for function is 0x000061019c41b000
new pid is: 999
参考/灵感来源
在开发此库时参考和受到启发的项目。
- [Kubo的Plthook] https://github.com/kubo/plthook
- [字节跳动的Bhook] https://github.com/bytedance/bhook
依赖项
~275–770KB
~18K SLoC