From 2246c9e8a73fee10dc8ffcfe178538ff678df8bc Mon Sep 17 00:00:00 2001 From: tzlil Date: Wed, 22 Mar 2023 01:08:16 +0200 Subject: add program headers --- src/main.rs | 68 +++++++++++++++++++++-------- src/structs.rs | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 181 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/main.rs b/src/main.rs index 5e6a07c..6032500 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ // #![allow(incomplete_features)] // #![feature(unsized_locals)] mod structs; -use crate::structs::{ElfHeader, ElfSectionHeader, ElfSectionType, ElfSymbol}; +use crate::structs::{ + ElfHeader, ElfProgramHeader, ElfProgramType, ElfSectionHeader, ElfSectionType, ElfSymbol, +}; use std::io::Read; #[repr(C)] @@ -10,7 +12,9 @@ struct Elf { header: &'static ElfHeader, sections: &'static [ElfSectionHeader], symbols: &'static [ElfSymbol], - strtab: *const u8, + programs: &'static [ElfProgramHeader], + shstrtab: *const u8, + start: *const u8, } impl Elf { @@ -25,17 +29,25 @@ impl Elf { ) }; - let strtab = unsafe { + let shstrtab = unsafe { bytes .as_ptr() .add((§ions[header.shstrndx as usize]).offset as usize) }; + let programs = unsafe { + std::slice::from_raw_parts( + bytes.as_ptr().add(header.phoff as usize) as *const ElfProgramHeader, + header.phnum as usize, + ) + }; + // dbg!(program); + let symtab = sections .iter() .find(|&&sec| sec.r#type == ElfSectionType::SymTab) .expect("No symbol table!"); - //dbg!(§ions[symtab.link as usize]); + // //dbg!(§ions[symtab.link as usize]); let symstrtab = §ions[symtab.link as usize]; let symbols = unsafe { std::slice::from_raw_parts( @@ -48,26 +60,28 @@ impl Elf { // .iter() // .filter(|sym| sym.shndx != 0) // .filter_map(|sym| unsafe { - // std::ffi::CStr::from_ptr(std::ptr::addr_of!(symstrtab).add(sym.name as usize) as *const i8).to_str().ok() + // std::ffi::CStr::from_ptr(std::ptr::addr_of!(symstrtab).add(sym.name as usize) as *const i8).to_str().ok() // }) // .filter(|name| name.len() > 1) // .collect(); // dbg!(symbols); - for sym in symbols { - // dbg!(sym); - let name = unsafe { - std::ffi::CStr::from_ptr(bytes.as_ptr().add(symstrtab.offset as usize).add(sym.name as usize) as *const i8) - .to_str() - .unwrap_or("") - }; - dbg!(name); - } + // for sym in symbols { + // // // dbg!(sym); + // let name = unsafe { + // std::ffi::CStr::from_ptr(bytes.as_ptr().add(symstrtab.offset as usize).add(sym.name as usize) as *const i8) + // .to_str() + // .unwrap_or("") + // }; + // dbg!(name); + // } Elf { header, sections, symbols, - strtab, + programs, + shstrtab, + start: bytes.as_ptr(), } } } @@ -86,7 +100,7 @@ impl std::fmt::Display for Elf { for (i, section) in self.sections.iter().enumerate() { let name = unsafe { - std::ffi::CStr::from_ptr(self.strtab.add(section.name as usize) as *const i8) + std::ffi::CStr::from_ptr(self.shstrtab.add(section.name as usize) as *const i8) .to_str() .expect("Bad section name") }; @@ -101,7 +115,25 @@ impl std::fmt::Display for Elf { " L (link order), O (extra OS processing required), G (group), T (TLS),\n", )?; formatter.write_str(" C (compressed), x (unknown), o (OS specific), E (exclude),\n")?; - formatter.write_str(" D (mbind), l (large), p (processor specific)\n")?; + formatter.write_str(" D (mbind), l (large), p (processor specific)\n\n")?; + + formatter.write_str("Program Headers:\n")?; + formatter.write_str(" Type Offset VirtAddr PhysAddr\n")?; + formatter + .write_str(" FileSiz MemSiz Flags Align\n")?; + for program in self.programs { + formatter.write_fmt(format_args!(" {}\n", program)); + if program.r#type == ElfProgramType::Interp { + let interpreter = unsafe { + std::ffi::CStr::from_ptr(self.start.add(program.offset as usize) as *const i8) + .to_str() + .expect("Bad interpreter name") + }; + formatter.write_fmt(format_args!( + " [Requesting program interpreter: {interpreter}]\n" + )); + } + } Ok(()) } } @@ -117,7 +149,7 @@ fn main() { buffer }; let elf = Elf::new(&buffer[..]); - // println!("{}", elf); + println!("{}", elf); // dbg!(symtab); } diff --git a/src/structs.rs b/src/structs.rs index f5c8140..673ae35 100644 --- a/src/structs.rs +++ b/src/structs.rs @@ -323,7 +323,7 @@ pub struct ElfSectionHeader { impl std::fmt::Display for ElfSectionHeader { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { formatter.write_fmt(format_args!( - "{: <16} {:0>16x} {:0>8x}\n {:0>16x} {:0>16x} {: ^10} {: <5} {: <5} {}", + "{: <16} {:0>16x} {:0>8x}\n {:0>16x} {:0>16x} {: <10} {: <5} {: <5} {}", self.r#type, self.addr, self.offset, @@ -451,7 +451,31 @@ bitflags! { // https://github.com/llvm-mirror/llvm/blob/2c4ca6832fa6b306ee6a7010bfb80a3f2596f824/tools/llvm-readobj/ELFDumper.cpp#L1176 impl std::fmt::Display for ElfSectionFlags { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - " A".fmt(formatter); + format!( + "{}{}{}", + { + if self.contains(ElfSectionFlags::WRITE) { + "W" + } else { + "" + } + }, + { + if self.contains(ElfSectionFlags::ALLOC) { + "A" + } else { + "" + } + }, + { + if self.contains(ElfSectionFlags::EXEC) { + "X" + } else { + "" + } + } + ) + .fmt(formatter); Ok(()) } } @@ -502,3 +526,108 @@ pub struct ElfSymbol { /// size. pub size: u64, } + +#[derive(Debug)] +#[repr(C)] +pub struct ElfProgramHeader { + pub r#type: ElfProgramType, + pub flags: ElfProgramFlags, + pub offset: u64, + pub vaddr: u64, + pub paddr: u64, + pub filesz: u64, + pub memsz: u64, + pub align: u64, +} + +impl std::fmt::Display for ElfProgramHeader { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + formatter.write_fmt(format_args!( + "{: <14} {:#016x} {:#016x} {:#016x}\n {:#016x} {:#016x} {: <10} {:#08x}", + self.r#type, + self.offset, + self.vaddr, + self.paddr, + self.filesz, + self.memsz, + self.flags, + self.align, + ))?; + Ok(()) + } +} + +#[derive(PartialEq,Debug)] +#[repr(u32)] +pub enum ElfProgramType { + /// This value marks the section header as inactive. + /// It does not have an associated section. Other + /// members of the section header have undefined + /// values. + PHDR = 6, + Interp = 3, + Load = 1, + Dynamic = 2, + Note = 4, + + GnuProperty = 0x6474E553, + GnuEhFrame = 0x6474E550, + GnuStack = 0x6474E551, + GnuRelro = 0x6474E552, +} + +impl std::fmt::Display for ElfProgramType { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + ElfProgramType::PHDR => "PHDR".fmt(formatter), + ElfProgramType::Interp => "INTERP".fmt(formatter), + ElfProgramType::Note => "NOTE".fmt(formatter), + ElfProgramType::Load => "LOAD".fmt(formatter), + ElfProgramType::Dynamic => "DYNAMIC".fmt(formatter), + ElfProgramType::GnuProperty => "GNU_PROPERTY".fmt(formatter), + ElfProgramType::GnuEhFrame => "GNU_EH_FRAME".fmt(formatter), + ElfProgramType::GnuStack => "GNU_STACK".fmt(formatter), + ElfProgramType::GnuRelro => "GNU_RELRO".fmt(formatter), + } + } +} + +bitflags! { + #[derive(Debug)] + pub struct ElfProgramFlags: u32 { + const EXEC = 0x1; + const WRITE = 0x2; + const READ = 0x4; + } +} + +impl std::fmt::Display for ElfProgramFlags { + fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { + format!( + "{}{}{}", + { + if self.contains(ElfProgramFlags::READ) { + "R" + } else { + " " + } + }, + { + if self.contains(ElfProgramFlags::WRITE) { + "W" + } else { + " " + } + }, + { + if self.contains(ElfProgramFlags::EXEC) { + "E" + } else { + " " + } + } + ) + .fmt(formatter); + Ok(()) + } +} \ No newline at end of file -- cgit 1.4.1