Skip to content

Commit

Permalink
MSFindSymbol seems to work
Browse files Browse the repository at this point in the history
  • Loading branch information
jevinskie committed Jan 22, 2014
1 parent 1514ed1 commit 66359c2
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 38 deletions.
152 changes: 133 additions & 19 deletions PosixFindSymbol.cpp
Expand Up @@ -25,7 +25,33 @@
#include <link.h>
#include <assert.h>
#include <string.h>
#include <elf.h>
#include <gelf.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string>
#include <set>
#include <map>
#include <iterator>
#include <vector>

void *mmap_file(std::string path, size_t *size) {
int fd;
struct stat st;
void *ptr;

fd = open(path.c_str(), O_RDONLY);
assert(fd >= 0);
assert(fstat(fd, &st) == 0);
ptr = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
assert(ptr);
close(fd);
if (size)
*size = st.st_size;
return ptr;
}

_extern MSImageRef MSGetImageByName(const char *file) {
if (!file)
Expand All @@ -35,9 +61,14 @@ _extern MSImageRef MSGetImageByName(const char *file) {
assert(handle);
struct link_map *map;
int ret = dlinfo(handle, RTLD_DI_LINKMAP, &map);
dlclose(handle);
assert(!ret);
assert(map);

// back up to find the first real entry
while (map->l_prev && strlen(map->l_prev->l_name) > 0)
map = map->l_prev;

while (map) {
if (!strcmp(map->l_name, file))
return (MSImageRef)map;
Expand All @@ -46,27 +77,110 @@ _extern MSImageRef MSGetImageByName(const char *file) {
return NULL;
}

static void *MSFindSymbolSub(MSImageRef image, const char *name) {
return 0;
static void MSFindSymbolSub(MSImageRef image, std::set<std::string> &worklist, std::map<std::string, void *> &resolved_symbols) {
Elf *e;
Elf_Scn *scn;
size_t shstrtab_idx;
size_t strtab_idx = 0;
size_t symtab_idx = 0;
size_t dynstr_idx = 0;
size_t dynsym_idx = 0;
GElf_Shdr shdr;
size_t sz;
size_t i;
char *elf;
Elf_Data *data;
GElf_Sym sym;
struct link_map *map = (struct link_map *)image;

assert(elf = (char *)mmap_file(map->l_name, &sz));
assert(elf_version(EV_CURRENT) != EV_NONE);
assert(e = elf_memory(elf, sz));
assert(!elf_getshdrstrndx(e, &shstrtab_idx));

i = 1;
scn = NULL;
while ((scn = elf_nextscn(e, scn)) != NULL) {
assert(gelf_getshdr(scn, &shdr));
std::string name {elf_strptr(e, shstrtab_idx, shdr.sh_name)};
if (name == ".symtab")
symtab_idx = i;
else if (name == ".strtab")
strtab_idx = i;
else if (name == ".dynstr")
dynstr_idx = i;
else if (name == ".dynsym")
dynsym_idx = i;
i++;
}

if (symtab_idx != 0) {
assert(scn = elf_getscn(e, symtab_idx));
assert(gelf_getshdr(scn, &shdr));
assert(data = elf_getdata(scn, NULL));
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
assert(gelf_getsym(data, i, &sym));
std::string sym_name {elf_strptr(e, strtab_idx, sym.st_name)};
if (worklist.find(sym_name) != worklist.end()) {
resolved_symbols[sym_name] = (void *)(map->l_addr + sym.st_value);
}
}
}

if (dynsym_idx != 0) {
assert(scn = elf_getscn(e, dynsym_idx));
assert(gelf_getshdr(scn, &shdr));
assert(data = elf_getdata(scn, NULL));
for (unsigned int i = 0; i < shdr.sh_size / shdr.sh_entsize; i++) {
assert(gelf_getsym(data, i, &sym));
std::string sym_name {elf_strptr(e, dynstr_idx, sym.st_name)};
if (worklist.find(sym_name) != worklist.end()) {
resolved_symbols[sym_name] = (void *)(map->l_addr + sym.st_value);
}
}
}

munmap((void *)elf, sz);
}

_extern void *MSFindSymbol(MSImageRef image, const char *name) {
if (image)
return MSFindSymbolSub(image, name);
void *handle = dlopen("libdl.so", RTLD_LAZY | RTLD_NOW);
assert(handle);
struct link_map *map;
int ret = dlinfo(handle, RTLD_DI_LINKMAP, &map);
assert(!ret);
assert(map);
static void MSFindSymbols(MSImageRef image, size_t count, const char *names[], void *values[]) {
std::set<std::string> worklist {names, names + count};
std::map<std::string, void *> resolved_symbols;

void *sym;
if (image) {
MSFindSymbolSub(image, worklist, resolved_symbols);
} else {
void *handle = dlopen("libdl.so", RTLD_LAZY | RTLD_NOW);
assert(handle);
struct link_map *map;
int ret = dlinfo(handle, RTLD_DI_LINKMAP, &map);
dlclose(handle);
assert(!ret);
assert(map);

while (map) {
sym = MSFindSymbolSub((MSImageRef)map, name);
if (sym)
return sym;
map = map->l_next;
// back up to find the first real entry
while (map->l_prev && strlen(map->l_prev->l_name) > 0)
map = map->l_prev;

while (map && !worklist.empty()) {
MSFindSymbolSub((MSImageRef)map, worklist, resolved_symbols);
map = map->l_next;
}
}
return NULL;

for (size_t i = 0; i < count; i++) {
try {
void *res = resolved_symbols.at(names[i]);
values[i] = res;
} catch (std::out_of_range) {
values[i] = NULL;
}
}

}

_extern void *MSFindSymbol(MSImageRef image, const char *name) {
void *value;
MSFindSymbols(image, 1, &name, &value);
return value;
}
12 changes: 8 additions & 4 deletions linux.mk
Expand Up @@ -21,8 +21,10 @@ flags :=
flags += -O0 -g

flags += -isystem extra
flags += -fno-exceptions
flags += -fvisibility=hidden
flags += -Wall -Wextra
flags += -Wno-bitwise-op-parentheses
flags += -Wno-unused-parameter
flags += -fPIC

flags_Hooker := -Ihde64c/include
Expand All @@ -31,7 +33,9 @@ flags_PosixMessage := -Xarch_armv6 -marm
hde64c := hde64c/src/hde64.c
lsubstrate := Debug.o Hooker.o PosixMemory.o PosixFindSymbol.o hde64c/src/hde64.c

cycc = g++ -o$@ $(flags) $(filter %.o,$^) $(filter %.so,$^)
cyxx = clang++ -std=c++11 -o$@ $(flags) $(filter %.o,$^) $(filter %.so,$^)
cycc = clang -o$@ $(flags) $(filter %.o,$^) $(filter %.so,$^)


all: linux

Expand All @@ -45,13 +49,13 @@ PosixMemory.o: PosixMemory.cpp
PosixFindSymbol.o: PosixFindSymbol.cpp

%.o: %.cpp
$(cycc) $(flags_$*) -c -Iinclude $<
$(cyxx) $(flags_$*) -c -Iinclude $<

%.o: %.mm
$(cycc) $(flags_$*) -c -Iinclude $<

libsubstrate.so: $(lsubstrate)
$(cycc) -shared $(hde64c)
$(cycc) -lelf -shared $(hde64c)

%: %.o
$(cycc)
Expand Down
23 changes: 10 additions & 13 deletions test-dl-hooker.cpp
Expand Up @@ -26,25 +26,22 @@ int my_fact_static_sub(int n) {
}

__attribute__ ((constructor))
void init(void) {
void *handle = dlopen(NULL, RTLD_NOW | RTLD_GLOBAL);
printf("hooker handle = %p\n", handle);
void *fact_sub = dlsym(handle, "fact_sub");
void init_hooking(void) {
void *fact_sub = MSFindSymbol(NULL, "fact_sub");
printf("hooker fact_sub = %p\n", fact_sub);
void *fact = dlsym(handle, "fact");
void *fact = MSFindSymbol(NULL, "fact");
printf("hooker fact = %p\n", fact);
void *a_number_p = dlsym(handle, "a_number");
printf("a_number_p: %p\n", a_number_p);
*(int *)a_number_p = 1337;
void *a_number_p = MSFindSymbol(NULL, "a_number");
printf("hooker a_number_p: %p\n", a_number_p);
if (a_number_p)
*(int *)a_number_p = 1337;
MSHookFunction(fact_sub, (void *)my_fact_sub, (void **)&orig_fact_sub);

void *fact_static_sub = dlsym(handle, "fact_static_sub");
void *a_static_number_p = MSFindSymbol(NULL, "a_static_number");
printf("hooker a_static_number_p: %p\n", a_static_number_p);
void *fact_static_sub = MSFindSymbol(NULL, "fact_static_sub");
printf("hooker fact_static_sub = %p\n", fact_static_sub);
void *a_static_number_p = dlsym(handle, "a_static_number");
printf("a_static_number_p: %p\n", a_static_number_p);
if (a_static_number_p)
*(int *)a_static_number_p = 7;
MSHookFunction(fact_static_sub, (void *)my_fact_static_sub, (void **)&orig_fact_static_sub);

dlclose(handle);
}
1 change: 1 addition & 0 deletions test-dl-substrate-main.cpp
Expand Up @@ -145,6 +145,7 @@ int main(void) {
assert(handle);
struct link_map *map;
int ret = dlinfo(handle, RTLD_DI_LINKMAP, &map);
dlclose(handle);
assert(!ret);
assert(map);

Expand Down
4 changes: 2 additions & 2 deletions test.mk
Expand Up @@ -2,8 +2,8 @@

all: test-hooker.so test-main test-dl-main test-dl-hooker.so libtest-dl-lib.so test-dl-substrate-main

CC=gcc -g -Wall -Wextra -std=c11
CXX=g++ -g -Wall -Wextra -std=c++11
CC=clang -g -Wall -Wextra -std=c11
CXX=clang++ -g -Wall -Wextra -std=c++11

test-main: test-main.c
$(CC) -o test-main -rdynamic -Wall -Wextra test-main.c -fPIE -pie
Expand Down

0 comments on commit 66359c2

Please sign in to comment.