ctf_pwn/unix/
plt.rs

1use crate::unix::error::ElfError;
2use crate::unix::symbol::Symbol;
3use elf::endian::AnyEndian;
4use elf::relocation::{RelIterator, RelaIterator};
5use elf::{abi, ElfBytes};
6use std::collections::HashMap;
7use elf::section::SectionHeader;
8
9
10    fn find_plt_rel_data<'a>(
11        file: &'a ElfBytes<AnyEndian>,
12    ) -> Result<Option<(&'a [u8], bool)>, ElfError> {
13        let (dynamic_table, segment_table) = match (file.dynamic()?, file.segments()) {
14            (Some(dynamic_table), Some(segment_table)) => (dynamic_table, segment_table),
15            _ => return Ok(None),
16        };
17
18        let jmp_rel = match dynamic_table.iter().find(|t| t.d_tag == abi::DT_JMPREL) {
19            Some(jmp_rel) => jmp_rel,
20            None => return Ok(None),
21        };
22
23        let plt_rel = match dynamic_table.iter().find(|t| t.d_tag == abi::DT_PLTREL) {
24            Some(plt_rel) => plt_rel,
25            None => return Ok(None),
26        };
27
28        let plt_rel_sz = match dynamic_table.iter().find(|t| t.d_tag == abi::DT_PLTRELSZ) {
29            Some(plt_rel_sz) => plt_rel_sz,
30            None => return Ok(None),
31        };
32
33        let jmp_rel_addr = jmp_rel.d_val();
34
35        let jmp_rel_header = segment_table
36            .iter()
37            .filter(|s| s.p_type == abi::PT_LOAD)
38            .find(|s| jmp_rel_addr >= s.p_vaddr && (jmp_rel_addr - s.p_vaddr) < s.p_memsz);
39
40        let jmp_rel_header = match jmp_rel_header {
41            Some(jmp_rel_header) => jmp_rel_header,
42            None => return Ok(None),
43        };
44
45        let data = file.segment_data(&jmp_rel_header)?;
46        let data = &data[(jmp_rel_addr - jmp_rel_header.p_vaddr) as usize..];
47        let data = &data[..plt_rel_sz.d_val() as usize];
48
49        let is_rela = (plt_rel.d_val() as usize) == (abi::DT_RELA as usize);
50
51        Ok(Some((data, is_rela)))
52    }
53
54    pub fn parse_plt_from_elf(
55        file: &ElfBytes<AnyEndian>,
56        dynamic_symbols: &[Symbol],
57    ) -> Result<HashMap<String, u64>, ElfError> {
58        let mut result = HashMap::new();
59        let (rel_data, is_rela) = match find_plt_rel_data(file)? {
60            Some((rela_data, is_rela)) => (rela_data, is_rela),
61            None => return Ok(result),
62        };
63
64        let plt_section = match file.section_header_by_name(".plt")?
65        {
66            Some(plt_section) => plt_section,
67            None => return Ok(result),
68        };
69
70        match is_rela {
71            false => parse_rel_iterator(
72                &plt_section,
73                RelIterator::new(file.ehdr.endianness, file.ehdr.class, rel_data),
74                &dynamic_symbols,
75                &mut result,
76            ),
77            true => parse_rela_iterator(
78                &plt_section,
79                RelaIterator::new(file.ehdr.endianness, file.ehdr.class, rel_data),
80                &dynamic_symbols,
81                &mut result,
82            ),
83        }
84
85        Ok(result)
86    }
87
88    fn parse_rela_iterator(
89        plt_section: &SectionHeader,
90        iter: RelaIterator<AnyEndian>,
91        dynamic_symbols: &[Symbol],
92        buf: &mut HashMap<String, u64>,
93    ) {
94        parse_plt(plt_section, iter.map(|r| r.r_sym) , dynamic_symbols, buf)
95    }
96
97    fn parse_rel_iterator(
98        plt_section: &SectionHeader,
99        iter: RelIterator<AnyEndian>,
100        dynamic_symbols: &[Symbol],
101        buf: &mut HashMap<String, u64>,
102    ) {
103        parse_plt(plt_section, iter.map(|r| r.r_sym), dynamic_symbols, buf)
104    }
105
106    fn parse_plt(
107        plt_section: &SectionHeader,
108        iter: impl Iterator<Item = u32>,
109        dynamic_symbols: &[Symbol],
110        buf: &mut HashMap<String, u64>,
111    ) {
112        for (i, r_sym) in iter.enumerate() {
113            match dynamic_symbols.get(r_sym as usize) {
114                Some(sym) =>{
115                    buf.insert(sym.name.to_string(), plt_section.sh_addr + (plt_section.sh_entsize * (i + 1) as u64))
116                },
117                _ => continue,
118            };
119        }
120    }
121