[feat] more powerful modules
This commit is contained in:
111
01/project-hbj-hook/src/elf.rs
Normal file
111
01/project-hbj-hook/src/elf.rs
Normal file
@@ -0,0 +1,111 @@
|
||||
use anyhow::{Context, bail};
|
||||
use goblin::elf::{Elf, ProgramHeader, Sym, program_header::PT_DYNAMIC, program_header::PT_LOAD, reloc::R_X86_64_JUMP_SLOT, Reloc};
|
||||
use memmap2::Mmap;
|
||||
use std::fs::File;
|
||||
use std::ops::Deref;
|
||||
use ouroboros::self_referencing;
|
||||
|
||||
fn open_mem_map(path: &str) -> Result<Mmap, Box<dyn std::error::Error>> {
|
||||
let file = File::open(path)?;
|
||||
unsafe { Ok(Mmap::map(&file)?) }
|
||||
}
|
||||
|
||||
#[self_referencing]
|
||||
pub struct ExecuteLinkFile {
|
||||
data: Vec<u8>,
|
||||
|
||||
#[borrows(data)]
|
||||
#[covariant]
|
||||
elf: Elf<'this>
|
||||
}
|
||||
|
||||
impl ExecuteLinkFile {
|
||||
pub fn prase(path: &str) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let data = open_mem_map(path)?.deref().to_owned();
|
||||
let s = ExecuteLinkFileTryBuilder {
|
||||
data,
|
||||
elf_builder: |data_ref| {
|
||||
Elf::parse(&data_ref)
|
||||
}
|
||||
}.try_build()?;
|
||||
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
pub fn get_loads(&self) -> Result<Vec<ProgramHeader>, Box<dyn std::error::Error>> {
|
||||
let loads = self.borrow_elf()
|
||||
.program_headers
|
||||
.iter()
|
||||
.filter_map(|ph| match ph.p_type {
|
||||
PT_LOAD => Some(ph.to_owned()),
|
||||
_ => None,
|
||||
})
|
||||
.collect::<Vec<ProgramHeader>>();
|
||||
|
||||
Ok(loads)
|
||||
}
|
||||
|
||||
pub fn get_dynamic(&self) -> Result<ProgramHeader, Box<dyn std::error::Error>> {
|
||||
let dynamic = self.borrow_elf()
|
||||
.program_headers
|
||||
.iter()
|
||||
.find(|ph| ph.p_type == PT_DYNAMIC)
|
||||
.context("No PT_DYNAMIC segment found")?;
|
||||
|
||||
Ok(dynamic.clone())
|
||||
}
|
||||
|
||||
pub fn get_rela_sym(&self, name: &str) -> Result<Reloc, Box<dyn std::error::Error>> {
|
||||
let rela_plt = self.borrow_elf().pltrelocs.iter();
|
||||
|
||||
let sym = rela_plt
|
||||
.filter(|rela| {
|
||||
matches!(rela.r_type, R_X86_64_JUMP_SLOT) // R_X86_64_JUMP_SLOT
|
||||
})
|
||||
.filter_map(|rela| {
|
||||
let sym_index = rela.r_sym;
|
||||
let Ok(sym) = self.get_dyn_sym(sym_index) else {
|
||||
return None;
|
||||
};
|
||||
let Ok(sym_name) = self.get_dyn_str(sym.st_name) else {
|
||||
return None;
|
||||
};
|
||||
|
||||
if sym_name == name { Some(rela) } else { None }
|
||||
})
|
||||
.collect::<Vec<Reloc>>();
|
||||
|
||||
let first = sym
|
||||
.first()
|
||||
.context(format!("No symbol found with name {}", name))?;
|
||||
|
||||
Ok(first.clone())
|
||||
}
|
||||
|
||||
pub fn get_dyn_sym(&self, location: usize) -> Result<Sym, Box<dyn std::error::Error>> {
|
||||
let dyn_sym = self.borrow_elf()
|
||||
.dynsyms
|
||||
.get(location)
|
||||
.context(format!("No symbol found at location {}", location))?;
|
||||
|
||||
Ok(dyn_sym.clone())
|
||||
}
|
||||
|
||||
pub fn prase_dyn_sym(&self, name: &str) -> Result<Sym, Box<dyn std::error::Error>> {
|
||||
let dyn_sym = self.borrow_elf()
|
||||
.dynsyms.iter()
|
||||
.find(|sym| self.get_dyn_str(sym.st_name).ok().as_deref() == Some(name))
|
||||
.context(format!("No symbol found with name {}", name))?;
|
||||
|
||||
Ok(dyn_sym.clone())
|
||||
}
|
||||
|
||||
pub fn get_dyn_str(&self, location: usize) -> Result<String, Box<dyn std::error::Error>> {
|
||||
let str = self.borrow_elf()
|
||||
.dynstrtab
|
||||
.get_at(location)
|
||||
.context(format!("Could not get dynstr at location {}", location))?;
|
||||
|
||||
Ok(str.to_owned())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user