From fad3a21b1fd66776d986454c50beb64ff8cdeb34 Mon Sep 17 00:00:00 2001 From: mii Date: Sun, 28 Nov 2021 23:19:02 +0900 Subject: [PATCH] Add program/section header parser --- src/elf_parser.rs | 126 +++++++++++++++++++++++++++++++++++++++++++--- src/elf_struct.rs | 76 +++++++++++++++++++++++++++- src/main.rs | 24 ++++----- 3 files changed, 204 insertions(+), 22 deletions(-) diff --git a/src/elf_parser.rs b/src/elf_parser.rs index 838d5d8..c613bdc 100644 --- a/src/elf_parser.rs +++ b/src/elf_parser.rs @@ -1,16 +1,126 @@ -use nom::{IResult, bytes::complete::tag, number::complete::{le_u16, le_u32, le_u64}}; +use nom::{IResult, bytes::complete::{tag, take}, number::complete::{le_u16, le_u32, le_u64}}; -use crate::elf_struct::ElfHeader; +use crate::elf_struct::{Elf, ElfHeader, ProgramHeader, SectionHeader}; pub struct ElfParser { pub file: Vec } impl ElfParser { - pub fn parse_header(input: &[u8]) -> IResult<&[u8], u64> { - let (input, ident) = le_u64(input)?; - let (input, elf_type) = le_u16(input)?; - let (input, version) = le_u32(input)?; - Ok((input, ident)) + + pub fn parse(&mut self) -> IResult<&[u8], Elf> { + let (input_headerless, elf_header) = ElfParser::parse_header(&self.file)?; + let (mut input, _) = take(elf_header.program_header_offset - 64)(input_headerless)?; + + let mut program_header_counter = 0; + let mut program_headers: Vec = vec![]; + while program_header_counter < elf_header.program_header_num { + let (input_tmp, program_header) = ElfParser::parse_program_header(input)?; + program_headers.push(program_header); + input = input_tmp; + program_header_counter += 1; + } + + let (mut input, _) = take(elf_header.section_header_offset - 64)(input_headerless)?; + + let mut section_header_counter = 0; + let mut section_headers: Vec = vec![]; + while section_header_counter < elf_header.section_header_num { + let (input_tmp, section_header) = ElfParser::parse_section_header(input)?; + section_headers.push(section_header); + input = input_tmp; + section_header_counter += 1; + } + + Ok((input, Elf { + header: elf_header, + program_headers, + section_headers + })) } -} \ No newline at end of file + + pub fn parse_section_header(input: &[u8]) -> IResult<&[u8], SectionHeader> { + let (input, name) = le_u32(input)?; + let (input, section_header_type) = le_u32(input)?; + let (input, flags) = le_u64(input)?; + let (input, address) = le_u64(input)?; + let (input, offset) = le_u64(input)?; + let (input, size) = le_u64(input)?; + let (input, link) = le_u32(input)?; + let (input, info) = le_u32(input)?; + let (input, align) = le_u64(input)?; + let (input, entry_size) = le_u64(input)?; + + Ok((input, SectionHeader { + name, + section_header_type, + flags, + address, + offset, + size, + link, + info, + align, + entry_size + })) + } + + pub fn parse_program_header(input: &[u8]) -> IResult<&[u8], ProgramHeader> { + let (input, program_type) = le_u32(input)?; + let (input, flags) = le_u32(input)?; + let (input, offset) = le_u64(input)?; + let (input, virtual_address) = le_u64(input)?; + let (input, physical_address) = le_u64(input)?; + let (input, file_size) = le_u64(input)?; + let (input, memory_size) = le_u64(input)?; + let (input, align) = le_u64(input)?; + + Ok((input, ProgramHeader { + program_type, + flags, + offset, + virtual_address, + physical_address, + file_size, + memory_size, + align + })) + } + + pub fn parse_header(input: &[u8]) -> IResult<&[u8], ElfHeader> { + let (input, ident_1) = le_u64(input)?; + let (input, ident_2) = le_u64(input)?; + let (input, elf_type) = le_u16(input)?; + let (input, machine) = le_u16(input)?; + let (input, version) = le_u32(input)?; + let (input, entry) = le_u64(input)?; + let (input, program_header_offset) = le_u64(input)?; + let (input, section_header_offset) = le_u64(input)?; + let (input, flags) = le_u32(input)?; + let (input, elf_header_size) = le_u16(input)?; + let (input, program_header_entry_size) = le_u16(input)?; + let (input, program_header_num) = le_u16(input)?; + let (input, section_header_entry_size) = le_u16(input)?; + let (input, section_header_num) = le_u16(input)?; + let (input, section_header_name_index) = le_u16(input)?; + + Ok((input, ElfHeader { + ident: (ident_1, ident_2), + elf_type, + machine, + version, + entry, + program_header_offset, + section_header_offset, + flags, + elf_header_size, + program_header_entry_size, + program_header_num, + section_header_entry_size, + section_header_num, + section_header_name_index + })) + } +} + +// 192 \ No newline at end of file diff --git a/src/elf_struct.rs b/src/elf_struct.rs index 1170f76..f5e7b9a 100644 --- a/src/elf_struct.rs +++ b/src/elf_struct.rs @@ -1,6 +1,27 @@ #[derive(Debug)] +pub struct Elf { + pub header: ElfHeader, + pub program_headers: Vec, + pub section_headers: Vec +} + +#[derive(Debug)] +pub struct SectionHeader { + pub name: u32, + pub section_header_type: u32, + pub flags: u64, + pub address: u64, + pub offset: u64, + pub size: u64, + pub link: u32, + pub info: u32, + pub align: u64, + pub entry_size: u64 +} + +#[derive(Debug, Clone, Copy)] pub struct ElfHeader { - pub magic_number: u64, + pub ident: (u64, u64), pub elf_type: u16, pub machine: u16, pub version: u32, @@ -14,4 +35,55 @@ pub struct ElfHeader { pub section_header_entry_size: u16, pub section_header_num: u16, pub section_header_name_index: u16 -} \ No newline at end of file +} +/* ++-----------------------------------------------+ +|e_ident[EI_NIDENT] | ++-----------------------------------------------+ +|7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00| ++-----+-----+-----------+-----------------------+ +|type |mach |ver |e_entry | ++-----+-----+-----------+-----------------------+ +|02 00|3e 00|01 00 00 00|78 00 40 00 00 00 00 00| ++-----+-----+-----------+-----------------------+ +|e_phoff |e_shoff | ++-----------------------+-----------------------+ +|40 00 00 00 00 00 00 00|00 00 00 00 00 00 00 00| ++-----------+-----+-----+-----+-----+-----+-----+ +|e_flags |ehsiz|phesi|phnum|shesi|shnum|shstr| ++-----------+-----+-----+-----+-----+-----+-----+ +|00 00 00 00|40 00|38 00|01 00|40 00|00 00|00 00| ++-----------+-----+-----+-----+-----+-----+-----+ +*/ + +#[derive(Debug)] +pub struct ProgramHeader { + pub program_type: u32, + pub flags: u32, + pub offset: u64, + pub virtual_address: u64, + pub physical_address: u64, + pub file_size: u64, + pub memory_size: u64, + pub align: u64 +} +/* ++-----------+-----------+-----------------------+ +|p_type |p_flags |p_offset | ++-----------+-----------+-----------------------+ +|01 00 00 00|07 00 00 00|00 00 00 00 00 00 00 00| ++-----------+-----------+-----------------------+ +|p_vaddr |p_paddr | ++-----------------------+-----------------------+ +|00 00 40 00 00 00 00 00|00 00 40 00 00 00 00 00| ++-----------------------+-----------------------+ +|p_filesz |p_memsz | ++-----------------------+-----------------------+ +|90 00 00 00 00 00 00 00|90 00 00 00 00 00 00 00| ++-----------------------+-----------------------+ +|p_align | ++-----------------------+ +|00 00 20 00 00 00 00 00| ++-----------------------+ +*/ + diff --git a/src/main.rs b/src/main.rs index b68c1cc..4893f17 100644 --- a/src/main.rs +++ b/src/main.rs @@ -5,23 +5,23 @@ use std::io::Read; use crate::elf_parser::ElfParser; fn main() { - println!("Hello, world!"); let mut file = std::fs::File::open("./test.elf").expect("Failed to open a file."); let mut buf = Vec::new(); file.read_to_end(&mut buf).expect("Failed to read a file."); let mut elf_parser = ElfParser { file: buf }; - match ElfParser::parse_header(&elf_parser.file) { - Ok(input) => { - println!("{:?}", input.0[0]); - println!("{:?}", input.0[1]); - println!("{:?}", input.0[2]); - println!("{:?}", input.0[3]); - println!("{:?}", input.1); + match elf_parser.parse() { + Ok((_, elf)) => { + println!("{:?}", elf.header); + for program_header in elf.program_headers { + println!("{:?}", program_header); + } + + for section_header in elf.section_headers { + println!("{:?}", section_header); + } }, - Err(_) => { - println!("Error."); - } + Err(_) => {} } } -// 282584257676671 \ No newline at end of file +// 1236 \ No newline at end of file