Skip to content

Commit

Permalink
promote try find function to api
Browse files Browse the repository at this point in the history
  • Loading branch information
ohchase committed Aug 11, 2024
1 parent feeed55 commit 0e3fa3e
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 92 deletions.
96 changes: 4 additions & 92 deletions examples/hook_getpid.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::anyhow;
use anyhow::Result;
use libc::c_void;
use plt_rs::{collect_modules, DynamicLibrary, DynamicSymbols};
use plt_rs::{collect_modules, DynamicLibrary};

unsafe fn getpid() -> u32 {
999
Expand All @@ -24,92 +24,6 @@ fn find_executable<'a>() -> Option<plt_rs::LoadedLibrary<'a>> {
.next()
}

/// Finding target function differs on 32 bit and 64 bit.
/// On 32 bit we want to check the relocations table only, opposed to the addend relocations table.
/// Additionally, we will fall back to the plt given it is an addendless relocation table.
#[cfg(target_pointer_width = "32")]
fn try_find_function<'a>(
dyn_lib: &'a DynamicLibrary,
dyn_symbols: &'a DynamicSymbols,
) -> Option<&'a plt_rs::elf32::DynRel> {
let string_table = dyn_lib.string_table();
if let Some(dyn_relas) = dyn_lib.relocs() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq("getpid"))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}

if let Some(dyn_relas) = dyn_lib.plt_rel() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq("getpid"))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}
return None;
}

/// Finding target function differs on 32 bit and 64 bit.
/// On 64 bit we want to check the addended relocations table only, opposed to the addendless relocations table.
/// Additionally, we will fall back to the plt given it is an addended relocation table.
#[cfg(target_pointer_width = "64")]
fn try_find_function<'a>(
dyn_lib: &'a DynamicLibrary,
dyn_symbols: &'a DynamicSymbols,
) -> Option<&'a plt_rs::elf64::DynRela> {
let string_table = dyn_lib.string_table();
if let Some(dyn_relas) = dyn_lib.addend_relocs() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq("getpid"))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}

if let Some(dyn_relas) = dyn_lib.plt_rela() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq("getpid"))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}
return None;
}

fn main() -> Result<()> {
let my_pid = unsafe { libc::getpid() };
println!("application pid is {my_pid}");
Expand All @@ -120,11 +34,9 @@ fn main() -> Result<()> {
let dyn_lib = DynamicLibrary::initialize(executable_entry)?;
println!("successfully initialied dynamic library for instrumentation");

let dyn_symbols = dyn_lib
.symbols()
.ok_or(anyhow!("dynamic lib should have symbols"))?;
let target_function =
try_find_function(&dyn_lib, &dyn_symbols).ok_or(anyhow!("unable to find getpid symbol"))?;
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
Expand Down
81 changes: 81 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,87 @@ impl<'a> DynamicLibrary<'a> {
})
}

/// Finding target function differs on 32 bit and 64 bit.
/// On 32 bit we want to check the relocations table only, opposed to the addend relocations table.
/// Additionally, we will fall back to the plt given it is an addendless relocation table.
#[cfg(target_pointer_width = "32")]
pub fn try_find_function(&self, symbol_name: &str) -> Option<&'_ elf32::DynRel> {
let string_table = self.string_table();
let dyn_symbols = self.symbols()?;
if let Some(dyn_relas) = self.relocs() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq(symbol_name))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}

if let Some(dyn_relas) = self.plt_rel() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
dyn_symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq(symbol_name))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}
return None;
}

/// Finding target function differs on 32 bit and 64 bit.
/// On 64 bit we want to check the addended relocations table only, opposed to the addendless relocations table.
/// Additionally, we will fall back to the plt given it is an addended relocation table.
#[cfg(target_pointer_width = "64")]
pub fn try_find_function(&self, symbol_name: &str) -> Option<&'_ elf64::DynRela> {
let string_table = self.string_table();
let symbols = self.symbols()?;
if let Some(dyn_relas) = self.addend_relocs() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq(symbol_name))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}

if let Some(dyn_relas) = self.plt_rela() {
let dyn_relas = dyn_relas.entries().iter();
if let Some(symbol) = dyn_relas
.flat_map(|e| {
symbols
.resolve_name(e.symbol_index() as usize, string_table)
.map(|s| (e, s))
})
.filter(|(_, s)| s.eq(symbol_name))
.next()
.map(|(target_function, _)| target_function)
{
return Some(symbol);
}
}
return None;
}
/// Access the plt as a dynamic relocation table if possible
/// can fail if the plt is not available or the plt is with addend
pub fn plt_rel(&self) -> Option<&DynamicRelocations<'_>> {
Expand Down

0 comments on commit 0e3fa3e

Please sign in to comment.