Commit 83470325 authored by swift_gan's avatar swift_gan

fix parser symb

parent b54e8a19
......@@ -34,7 +34,7 @@ namespace SandHook {
Elf_Addr getSymbOffset(const char* name);
void* getModuleBase(int pid, const char* name);
void* getModuleBase(const char* name);
Elf_Addr getSymbAddress(const char* name);
......@@ -44,10 +44,13 @@ namespace SandHook {
const char* elf = nullptr;
void* base = nullptr;
char* buffer = nullptr;
off_t size = 0;
off_t bias = 0;
Elf_Ehdr* header = nullptr;
Elf_Shdr* section_header = nullptr;
Elf_Shdr* symtab = nullptr;
Elf_Shdr* strtab = nullptr;
Elf_Shdr* dynsym = nullptr;
Elf_Sym* sym_start = nullptr;
Elf_Off symtab_count = 0;
Elf_Off symstr_offset = 0;
......
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include "../includes/elf_util.h"
#include "../includes/log.h"
......@@ -9,41 +11,54 @@ using namespace SandHook;
ElfImg::ElfImg(const char *elf) {
this->elf = elf;
//load elf
FILE *fp = NULL;
if (!(fp = fopen(elf, "rb"))) {
LOGE("Unable to open %s\n", elf);
return;
}
int fd = open(elf, O_RDONLY);
if (fd < 0) LOGE("failed to open %s", elf);
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
size = lseek(fd, 0, SEEK_END);
if (size <= 0) LOGE("lseek() failed for %s", elf);
char *buffer = (char*)malloc(size);
if (fread(buffer, 1, size, fp) != size) {
LOGE("fread error\n");
return;
}
fclose(fp);
header = reinterpret_cast<Elf_Ehdr *>(mmap(0, size, PROT_READ, MAP_SHARED, fd, 0));
close(fd);
Elf_Off symtab_entsize = 0;
header = reinterpret_cast<Elf_Ehdr *>(buffer);
section_header = reinterpret_cast<Elf_Shdr *>(header + header->e_shoff);
Elf_Off shoff = reinterpret_cast<Elf_Off>(((void *) elf) + header->e_shoff);
section_header = reinterpret_cast<Elf_Shdr *>(((void *) header) + header->e_shoff);
void* shoff = section_header;
char* section_str = reinterpret_cast<char *>(section_header[header->e_shstrndx].sh_offset + ((void *) header));
bool has_strtab = false;
bool has_dynsym = false;
for (int i = 0; i < header->e_shnum; i++, shoff += header->e_shentsize) {
Elf_Shdr *section_h = (Elf_Shdr *) shoff;
char* sname = section_h->sh_name + section_str;
switch (section_h->sh_type) {
case SHT_DYNSYM:
has_dynsym = true;
dynsym = section_h;
break;
case SHT_SYMTAB:
symtab = section_h;
symtab_offset = section_h->sh_offset;
symtab_size = section_h->sh_size;
symtab_entsize = section_h->sh_entsize;
symtab_count = symtab_size / symtab_entsize;
if (strcmp(sname, ".symtab") == 0) {
symtab = section_h;
symtab_offset = section_h->sh_offset;
symtab_size = section_h->sh_size;
symtab_entsize = section_h->sh_entsize;
symtab_count = symtab_size / symtab_entsize;
}
break;
case SHT_STRTAB:
symstr_offset = section_h->sh_offset;
has_strtab = true;
if (strcmp(sname, ".strtab") == 0) {
strtab = section_h;
symstr_offset = section_h->sh_offset;
}
break;
case SHT_PROGBITS:
if (has_dynsym && has_strtab && bias == 0) {
bias = (off_t) section_h->sh_addr - (off_t) section_h->sh_offset;
}
break;
}
}
......@@ -52,10 +67,10 @@ ElfImg::ElfImg(const char *elf) {
LOGW("can't find symtab from sections\n");
}
sym_start = reinterpret_cast<Elf_Sym *>(header + symtab_offset);
sym_start = reinterpret_cast<Elf_Sym *>(((void *) header) + symtab_offset);
//load module base
base = getModuleBase(0, elf);
base = getModuleBase(elf);
}
ElfImg::~ElfImg() {
......@@ -63,13 +78,16 @@ ElfImg::~ElfImg() {
free(buffer);
buffer = nullptr;
}
if (header) {
munmap(header, size);
}
}
Elf_Addr ElfImg::getSymbOffset(const char *name) {
Elf_Addr _offset = 0;
for(int i = 0 ; i < symtab_count; i++) {
unsigned int st_type = ELF_ST_TYPE(sym_start[i].st_info);
char* st_name = buffer + symstr_offset + sym_start[i].st_name;
char* st_name = static_cast<char *>(((void *) header) + symstr_offset + sym_start[i].st_name);
if (st_type == STT_FUNC && sym_start[i].st_size) {
if(strcmp(st_name, name) == 0) {
_offset = sym_start[i].st_value;
......@@ -82,34 +100,29 @@ Elf_Addr ElfImg::getSymbOffset(const char *name) {
}
Elf_Addr ElfImg::getSymbAddress(const char *name) {
return reinterpret_cast<Elf_Addr>(base + getSymbOffset(name));
Elf_Addr offset = getSymbOffset(name);
if (offset > 0 && base > 0) {
return reinterpret_cast<Elf_Addr>(base + offset - bias);
} else {
return 0;
}
}
void *ElfImg::getModuleBase(int pid, const char *name) {
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
void *ElfImg::getModuleBase(const char *name) {
FILE *maps;
char buff[256];
off_t load_addr;
int found = 0;
maps = fopen("/proc/self/maps", "r");
while (!found && fgets(buff, sizeof(buff), maps))
if (strstr(buff, "r-xp") && strstr(buff, name)) found = 1;
if (pid <= 0) {
snprintf(filename, sizeof(filename), "/proc/self/maps");
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, name)) {
pch = strtok(line, "-");
addr = strtoul(pch, NULL, 16);
break;
}
}
fclose(fp);
}
if (sscanf(buff, "%lx", &load_addr) != 1)
LOGE("failed to read load address for %s", name);
fclose(maps);
LOGD("get module base %s: %lu", name, addr);
LOGD("get module base %s: %lu", name, load_addr);
return reinterpret_cast<void *>(addr);
return reinterpret_cast<void *>(load_addr);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment