mirror of
https://gitlab.com/BinaryHardening/cfgrip
synced 2026-07-26 12:41:08 +00:00
+248
-4
@@ -171,7 +171,7 @@ bool ELFLoader::parseHeader()
|
|||||||
uint64_t val = r64(m_data, j + 8);
|
uint64_t val = r64(m_data, j + 8);
|
||||||
|
|
||||||
if (tag == DT_NULL) break;
|
if (tag == DT_NULL) break;
|
||||||
if (tag == DT_NEEDED && val && m_needed_libs.empty())
|
if (tag == DT_NEEDED && val)
|
||||||
{
|
{
|
||||||
uint64_t strtab = 0;
|
uint64_t strtab = 0;
|
||||||
for (size_t k = dyn_off; k + 16 <= end; k += 16)
|
for (size_t k = dyn_off; k + 16 <= end; k += 16)
|
||||||
@@ -185,8 +185,10 @@ bool ELFLoader::parseHeader()
|
|||||||
size_t name_off = strtab + val;
|
size_t name_off = strtab + val;
|
||||||
if (name_off < m_data.size())
|
if (name_off < m_data.size())
|
||||||
{
|
{
|
||||||
|
string lib;
|
||||||
for (size_t c = name_off; c < m_data.size() && m_data[c]; c++)
|
for (size_t c = name_off; c < m_data.size() && m_data[c]; c++)
|
||||||
m_needed_libs += (char)m_data[c];
|
lib += (char)m_data[c];
|
||||||
|
if (!lib.empty()) m_needed_libs.push_back(lib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -324,7 +326,12 @@ bool ELFLoader::parseHeader()
|
|||||||
if (str_link < shnum) str_off2 = sections[str_link].offset;
|
if (str_link < shnum) str_off2 = sections[str_link].offset;
|
||||||
uint64_t sym_entsize = sections[symtab_link].entsize ? sections[symtab_link].entsize : 24;
|
uint64_t sym_entsize = sections[symtab_link].entsize ? sections[symtab_link].entsize : 24;
|
||||||
|
|
||||||
string lib_name = m_needed_libs;
|
string lib_name;
|
||||||
|
for (size_t li = 0; li < m_needed_libs.size(); li++)
|
||||||
|
{
|
||||||
|
if (li) lib_name += ", ";
|
||||||
|
lib_name += m_needed_libs[li];
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t j = 0; j < nrela; j++)
|
for (size_t j = 0; j < nrela; j++)
|
||||||
{
|
{
|
||||||
@@ -365,6 +372,241 @@ bool ELFLoader::parseHeader()
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
m_arch = Arch::X86;
|
m_arch = Arch::X86;
|
||||||
|
if (m_data.size() < 52) return false;
|
||||||
|
|
||||||
|
m_entry = r32(m_data, 24);
|
||||||
|
uint32_t phoff = r32(m_data, 28);
|
||||||
|
uint32_t shoff = r32(m_data, 32);
|
||||||
|
uint16_t phnum = r16(m_data, 44);
|
||||||
|
uint16_t shnum = r16(m_data, 48);
|
||||||
|
uint16_t shstrndx = r16(m_data, 50);
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < phnum; i++)
|
||||||
|
{
|
||||||
|
size_t off = phoff + i * 32;
|
||||||
|
if (off + 32 > m_data.size()) break;
|
||||||
|
uint32_t ptype = r32(m_data, off);
|
||||||
|
uint32_t poffset = r32(m_data, off + 4);
|
||||||
|
uint32_t pvaddr = r32(m_data, off + 8);
|
||||||
|
uint32_t pfilesz = r32(m_data, off + 16);
|
||||||
|
uint32_t pmemsz = r32(m_data, off + 20);
|
||||||
|
uint32_t pflags = r32(m_data, off + 24);
|
||||||
|
|
||||||
|
if (ptype == PT_LOAD)
|
||||||
|
{
|
||||||
|
m_file_map.push_back({poffset, pvaddr, pmemsz});
|
||||||
|
if (pflags & 1)
|
||||||
|
m_exec_ranges.push_back({pvaddr, pvaddr + pmemsz});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ptype == PT_DYNAMIC)
|
||||||
|
{
|
||||||
|
size_t dyn_off = poffset;
|
||||||
|
size_t dyn_sz = pmemsz;
|
||||||
|
size_t end = dyn_off + dyn_sz;
|
||||||
|
|
||||||
|
for (size_t j = dyn_off; j + 8 <= end; j += 8)
|
||||||
|
{
|
||||||
|
int32_t tag = (int32_t)r32(m_data, j);
|
||||||
|
uint32_t val = r32(m_data, j + 4);
|
||||||
|
|
||||||
|
if (tag == DT_NULL) break;
|
||||||
|
if (tag == DT_NEEDED && val)
|
||||||
|
{
|
||||||
|
uint32_t strtab = 0;
|
||||||
|
for (size_t k = dyn_off; k + 8 <= end; k += 8)
|
||||||
|
{
|
||||||
|
int32_t t2 = (int32_t)r32(m_data, k);
|
||||||
|
uint32_t v2 = r32(m_data, k + 4);
|
||||||
|
if (t2 == DT_STRTAB) { strtab = v2; break; }
|
||||||
|
}
|
||||||
|
if (strtab)
|
||||||
|
{
|
||||||
|
size_t name_off = strtab + val;
|
||||||
|
if (name_off < m_data.size())
|
||||||
|
{
|
||||||
|
string lib;
|
||||||
|
for (size_t c = name_off; c < m_data.size() && m_data[c]; c++)
|
||||||
|
lib += (char)m_data[c];
|
||||||
|
if (!lib.empty()) m_needed_libs.push_back(lib);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tag == DT_INIT) m_init = val;
|
||||||
|
if (tag == DT_FINI) m_fini = val;
|
||||||
|
if (tag == DT_INIT_ARRAY) m_init_array = val;
|
||||||
|
if (tag == DT_INIT_ARRAYSZ) m_init_array_size = val;
|
||||||
|
if (tag == DT_FINI_ARRAY) m_fini_array = val;
|
||||||
|
if (tag == DT_FINI_ARRAYSZ) m_fini_array_size = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SectionInfo32 {
|
||||||
|
uint32_t type;
|
||||||
|
uint32_t addr;
|
||||||
|
uint32_t offset;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t link;
|
||||||
|
uint32_t entsize;
|
||||||
|
uint32_t name_idx;
|
||||||
|
};
|
||||||
|
vector<SectionInfo32> sections(shnum);
|
||||||
|
uint32_t shstrtab_off = 0;
|
||||||
|
for (uint16_t i = 0; i < shnum; i++)
|
||||||
|
{
|
||||||
|
size_t off = shoff + i * 40;
|
||||||
|
if (off + 40 > m_data.size()) break;
|
||||||
|
sections[i].type = r32(m_data, off + 4);
|
||||||
|
sections[i].addr = r32(m_data, off + 12);
|
||||||
|
sections[i].offset = r32(m_data, off + 16);
|
||||||
|
sections[i].size = r32(m_data, off + 20);
|
||||||
|
sections[i].link = r32(m_data, off + 28);
|
||||||
|
sections[i].entsize = r32(m_data, off + 36);
|
||||||
|
sections[i].name_idx = r32(m_data, off);
|
||||||
|
if (i == shstrndx) shstrtab_off = sections[i].offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sectionName = [&](uint32_t idx) -> string {
|
||||||
|
if (!shstrtab_off) return "";
|
||||||
|
size_t pos = shstrtab_off + idx;
|
||||||
|
string s;
|
||||||
|
for (; pos < m_data.size() && m_data[pos]; pos++)
|
||||||
|
s += (char)m_data[pos];
|
||||||
|
return s;
|
||||||
|
};
|
||||||
|
|
||||||
|
vector<uint32_t> strtab_offsets(shnum, 0);
|
||||||
|
for (uint16_t i = 0; i < shnum; i++)
|
||||||
|
{
|
||||||
|
if (sections[i].type == SHT_SYMTAB || sections[i].type == SHT_DYNSYM)
|
||||||
|
{
|
||||||
|
uint32_t link = sections[i].link;
|
||||||
|
if (link < shnum)
|
||||||
|
strtab_offsets[i] = sections[link].offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < shnum; i++)
|
||||||
|
{
|
||||||
|
if (sections[i].type != SHT_SYMTAB && sections[i].type != SHT_DYNSYM)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t sym_off = sections[i].offset;
|
||||||
|
uint32_t sym_sz = sections[i].size;
|
||||||
|
uint32_t entsize = sections[i].entsize ? sections[i].entsize : 16;
|
||||||
|
uint32_t str_off = strtab_offsets[i];
|
||||||
|
|
||||||
|
size_t nsym = sym_sz / entsize;
|
||||||
|
for (size_t j = 0; j < nsym; j++)
|
||||||
|
{
|
||||||
|
size_t ent = sym_off + j * entsize;
|
||||||
|
if (ent + 16 > m_data.size()) break;
|
||||||
|
uint32_t sym_name_off = r32(m_data, ent);
|
||||||
|
uint8_t sym_info = m_data[ent + 4];
|
||||||
|
uint8_t sym_other = m_data[ent + 5];
|
||||||
|
uint16_t sym_shndx = r16(m_data, ent + 6);
|
||||||
|
uint32_t sym_val = r32(m_data, ent + 8);
|
||||||
|
uint32_t sym_size = r32(m_data, ent + 12);
|
||||||
|
|
||||||
|
uint8_t sym_type = sym_info & 0xF;
|
||||||
|
uint8_t sym_bind = sym_info >> 4;
|
||||||
|
|
||||||
|
if (sym_type != 2) continue;
|
||||||
|
if (!sym_name_off || !str_off) continue;
|
||||||
|
|
||||||
|
size_t name_pos = str_off + sym_name_off;
|
||||||
|
if (name_pos >= m_data.size()) continue;
|
||||||
|
|
||||||
|
string sym_name;
|
||||||
|
for (size_t c = name_pos; c < m_data.size() && m_data[c]; c++)
|
||||||
|
sym_name += (char)m_data[c];
|
||||||
|
if (sym_name.empty()) continue;
|
||||||
|
|
||||||
|
if (sym_shndx != 0 && sym_val)
|
||||||
|
{
|
||||||
|
m_symbols[sym_val] = sym_name;
|
||||||
|
if (sym_bind == 1)
|
||||||
|
m_exports.push_back({sym_val, sym_name});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < shnum; i++)
|
||||||
|
{
|
||||||
|
uint32_t sh_flags = 0;
|
||||||
|
size_t so = shoff + i * 40;
|
||||||
|
if (so + 40 > m_data.size()) continue;
|
||||||
|
sh_flags = r32(m_data, so + 8);
|
||||||
|
bool is_exec = (sh_flags & 0x4) != 0;
|
||||||
|
bool is_alloc = (sh_flags & 0x2) != 0;
|
||||||
|
if (is_alloc && !is_exec && sections[i].addr && sections[i].size)
|
||||||
|
m_data_ranges.push_back({sections[i].addr, sections[i].addr + sections[i].size});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint16_t i = 0; i < shnum; i++)
|
||||||
|
{
|
||||||
|
string sname = sectionName(sections[i].name_idx);
|
||||||
|
if (sections[i].type != SHT_RELA && sname != ".rela.plt" && sname != ".rela.dyn")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint32_t rela_off = sections[i].offset;
|
||||||
|
uint32_t rela_sz = sections[i].size;
|
||||||
|
size_t nrela = rela_sz / 12;
|
||||||
|
if (nrela == 0) continue;
|
||||||
|
|
||||||
|
uint32_t symtab_link = sections[i].link;
|
||||||
|
if (symtab_link >= shnum) continue;
|
||||||
|
|
||||||
|
uint32_t sym_off = sections[symtab_link].offset;
|
||||||
|
uint32_t sym_sz = sections[symtab_link].size;
|
||||||
|
uint32_t str_off2 = 0;
|
||||||
|
uint32_t str_link = sections[symtab_link].link;
|
||||||
|
if (str_link < shnum) str_off2 = sections[str_link].offset;
|
||||||
|
uint32_t sym_entsize = sections[symtab_link].entsize ? sections[symtab_link].entsize : 16;
|
||||||
|
|
||||||
|
string lib_name;
|
||||||
|
for (size_t li = 0; li < m_needed_libs.size(); li++)
|
||||||
|
{
|
||||||
|
if (li) lib_name += ", ";
|
||||||
|
lib_name += m_needed_libs[li];
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < nrela; j++)
|
||||||
|
{
|
||||||
|
size_t ent = rela_off + j * 12;
|
||||||
|
if (ent + 12 > m_data.size()) break;
|
||||||
|
uint32_t r_offset = r32(m_data, ent);
|
||||||
|
uint32_t r_info = r32(m_data, ent + 4);
|
||||||
|
uint32_t sym_idx = r_info >> 8;
|
||||||
|
|
||||||
|
if (!sym_idx) continue;
|
||||||
|
|
||||||
|
size_t sym_ent = sym_off + sym_idx * sym_entsize;
|
||||||
|
if (sym_ent + 16 > m_data.size()) continue;
|
||||||
|
uint32_t func_name_off = r32(m_data, sym_ent);
|
||||||
|
if (!func_name_off || !str_off2) continue;
|
||||||
|
|
||||||
|
size_t fn_pos = str_off2 + func_name_off;
|
||||||
|
if (fn_pos >= m_data.size()) continue;
|
||||||
|
|
||||||
|
string func_name;
|
||||||
|
for (size_t c = fn_pos; c < m_data.size() && m_data[c]; c++)
|
||||||
|
func_name += (char)m_data[c];
|
||||||
|
if (func_name.empty()) continue;
|
||||||
|
|
||||||
|
bool dup = false;
|
||||||
|
for (const auto& imp : m_imports)
|
||||||
|
if (imp.address == r_offset) { dup = true; break; }
|
||||||
|
if (dup) continue;
|
||||||
|
|
||||||
|
ImportEntry e;
|
||||||
|
e.address = r_offset;
|
||||||
|
e.name = func_name;
|
||||||
|
e.library = lib_name;
|
||||||
|
m_imports.push_back(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -395,8 +637,10 @@ vector<uint8_t> ELFLoader::readBytes(addr_t vaddr, size_t size) const
|
|||||||
{
|
{
|
||||||
uint64_t file_off = get<0>(fmap) + (vaddr - seg_vaddr);
|
uint64_t file_off = get<0>(fmap) + (vaddr - seg_vaddr);
|
||||||
size_t avail = min(size, (size_t)(seg_vaddr + seg_size - vaddr));
|
size_t avail = min(size, (size_t)(seg_vaddr + seg_size - vaddr));
|
||||||
if (file_off + avail > m_data.size())
|
if (file_off >= m_data.size()) avail = 0;
|
||||||
|
else if (file_off + avail > m_data.size())
|
||||||
avail = m_data.size() - file_off;
|
avail = m_data.size() - file_off;
|
||||||
|
|
||||||
vector<uint8_t> result(m_data.begin() + file_off, m_data.begin() + file_off + avail);
|
vector<uint8_t> result(m_data.begin() + file_off, m_data.begin() + file_off + avail);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ class ELFLoader : public Binary
|
|||||||
vector<pair<addr_t, string>> m_exports;
|
vector<pair<addr_t, string>> m_exports;
|
||||||
vector<ImportEntry> m_imports;
|
vector<ImportEntry> m_imports;
|
||||||
map<addr_t, string> m_symbols;
|
map<addr_t, string> m_symbols;
|
||||||
string m_needed_libs;
|
vector<string> m_needed_libs;
|
||||||
|
|
||||||
addr_t m_init_array;
|
addr_t m_init_array;
|
||||||
size_t m_init_array_size;
|
size_t m_init_array_size;
|
||||||
|
|||||||
Reference in New Issue
Block a user