-
Notifications
You must be signed in to change notification settings - Fork 179
Description
Hi, I was wondering if it's possible to add a custom section/segment to an ELF file. For context, I'm currently working on a tool to patch PlayStation 3 ELFs to allow custom code. I need to add a bit of shellcode into the executable, so I wanted to make a custom section to store my code in and then modify the entrypoint. My code to modify the executable is a little complex, so I made this simple example:
fn main() {
let input = std::fs::read("hbtest.elf").unwrap();
let mut builder = object::build::elf::Builder::read(input.as_slice()).unwrap();
// 32 NOPs (0x60000000 in PowerPC)
let mut custom_data: Vec<u8> = Vec::new();
for _ in 0..32 {
custom_data.push(0x60);
custom_data.push(0x00);
custom_data.push(0x00);
custom_data.push(0x00);
}
let section_id = {
let section = builder.sections.add();
section.name = ".sprxpatcher".into();
section.sh_type = object::elf::SHT_PROGBITS;
section.sh_flags = (object::elf::SHF_ALLOC | object::elf::SHF_EXECINSTR) as u64;
section.sh_addralign = 16;
section.sh_size = custom_data.len() as u64;
section.data = object::build::elf::SectionData::Data(custom_data.into());
section.id()
};
let section_addr = {
let segment = builder
.segments
.add_load_segment(object::elf::PF_R | object::elf::PF_X, builder.load_align);
let section = builder.sections.get_mut(section_id);
segment.append_section(section);
section.sh_addr
};
println!("Section address: 0x{:x}", section_addr);
let output = std::fs::File::create("hbtest.modified.elf").unwrap();
let mut buffer = object::write::StreamingBuffer::new(output);
builder.write(&mut buffer).unwrap();
}
However, when running this, it panics:
Section address: 0x267b10
thread 'main' panicked at src/main.rs:38:32:
called `Result::unwrap()` on an `Err` value: Error("Unsupported sh_offset value 0x200 for section '.init', expected at least 0x238")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
error: process didn't exit successfully: `target\debug\sprxpatcher.exe` (exit code: 101)
I assume this is because the addition of the new section/segment into the program header table has shifted the file offsets by 0x38 (the size of the new entry). Is it possible to repair these offsets such that the modified ELF writes successfully? I tried just shifting every sh_offset by 0x38, but that didn't seem to work. I suspect there is more work to be done here (or it's just flat out impossible).