Я хочу динамически загрузить библиотеку без использования функций из dlfcn.h
У меня есть папка, полная .so файлов, скомпилированных с:
gcc -Wall -shared -fPIC -o filename.so filename.c
И все они имеют функцию входа с именем:
void __start(int size, char** cmd);
(я знаю, наверное, не лучшее имя)
затем я пытаюсь вызвать open
поверх так, затем прочитать заголовок эльфа как Elf64_Ehdr
загрузить его в память с помощью mmap
(я знаю, что должен использовать mprotect
, но я хочу, чтобы сначала он работал а затем добавьте защиту) и, наконец, добавьте запись заголовка elf к указателю, возвращенному mmap (плюс смещение 0x100).
Тестовый код следующий:
#include <elf.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
typedef void (*ptr_t) (int, char**);
void* alloc_ex_memory(int fd) {
struct stat s;
fstat(fd, &s);
void * ptr = mmap(0, s.st_size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
if (ptr == (void *)-1) {
perror("mmap");
return NULL;
}
return ptr;
}
void* load_ex_file(const char* elfFile) {
Elf64_Ehdr header;
void * ptr;
FILE* file = fopen(elfFile, "rb");
if(file) {
fread(&header, 1, sizeof(header), file);
if (memcmp(header.e_ident, ELFMAG, SELFMAG) == 0) {
ptr = alloc_ex_memory(fileno(file));
printf("PTR AT -> %p\n", ptr);
printf("Entry at -> %lx\n", header.e_entry+256);
ptr = (header.e_entry + 256);
} else {
ptr = NULL;
}
fclose(file);
return ptr;
}
return NULL;
}
int main(int argc, char** argv) {
ptr_t func = load_ex_file(argv[1]);
printf("POINTER AT: %p\n", func);
getchar();
func(argc, argv);
return 0;
}
Позвольте мне объяснить немного подробнее:
Когда я запускаю objdump -d filename.so
, я получаю, что _start
на 0x6c0
. Точка входа заголовка elf возвращает 0x5c0
(я компенсирую это добавлением 256 в декабрь).
Также pmap
показывает исполняемую область, создаваемую, скажем, 0x7fdf94d0c000
, поэтому направление указателя функции, которое я получаю и которое я вызываю, находится на 0x7fdf94d0c6c0
, это должна быть точка входа и вызываемая через указатель функции. Но то, что я получаю, вы уже догадались: segfault.
Еще одна вещь, на которую я хотел бы обратить внимание, это то, что у меня работает тот же пример с (dlopen
, dlsym
, dlclose
), но необходимо использовать трюк mmap. Я видел, как мой профессор успешно его применяет, но я не могу понять, как это сделать. (возможно, есть более простой способ, который мне не хватает).
Я основал код на этом примере jit
Заранее спасибо!
Редактировать: это код .c, который я компилирую в .so:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void __start(int size, char** cmd) {
if (size==2) {
if (!strcmp(cmd[1], "-l")) {
printf("******.********.*****@udc.es\n");
return;
} else if (!strcmp(cmd[1], "-n")) {
printf("****** ******** *****\n");
return;
}
} else if (size==1) {
printf("****** ******** ***** (******.********.*****@udc.es)\n");
return;
}
printf("Wrong command syntax: autores [-l | -n]\n");
}