mmap load shared object and get function pointer












1















I want to dynamically load a library without using functions from dlfcn.h i have a folder full of .so files compiled with:



gcc -Wall -shared -fPIC -o filename.so filename.c


And all of them have an entry function named:



void __start(int size, char** cmd);


(I know, probably not the best name)



then i try to call open over the so, then read the elf header as an Elf64_Ehdr load it into memory with mmap (i know i should use mprotect but i want to make it work first and then add the security) and finally adding the the elf header entry to the pointer returned by mmap (plus an offset of 0x100).



The test code is the following:



#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 -> %pn", ptr);
printf("Entry at -> %lxn", 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: %pn", func);
getchar();
func(argc, argv);
return 0;
}


Let me explain a bit further:
When i run objdump -d filename.so i get that the _start is at 0x6c0. The elf header entry point returns 0x5c0 (i compensate it adding 256 in dec).



Also pmap shows an executable area being created at lets say 0x7fdf94d0c000
so the function pointer direction that i get and which i call is at 0x7fdf94d0c6c0 this should be the entry point and callable via function pointer. But what i get is, you guessed it: segfault.



Las thing that i would like to point out is that i have the same example running with (dlopen, dlsym, dlclose) but its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how. (perhaps there is a simpler way that im missing).



I based the code on this jit example



Thank you in advance!



Edit: This is the code of the .c that i compile into .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.esn");
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");
}









share|improve this question

























  • printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

    – Andrew Henle
    Nov 14 '18 at 10:25











  • @AndrewHenle edited code.

    – Tretorn
    Nov 14 '18 at 10:28
















1















I want to dynamically load a library without using functions from dlfcn.h i have a folder full of .so files compiled with:



gcc -Wall -shared -fPIC -o filename.so filename.c


And all of them have an entry function named:



void __start(int size, char** cmd);


(I know, probably not the best name)



then i try to call open over the so, then read the elf header as an Elf64_Ehdr load it into memory with mmap (i know i should use mprotect but i want to make it work first and then add the security) and finally adding the the elf header entry to the pointer returned by mmap (plus an offset of 0x100).



The test code is the following:



#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 -> %pn", ptr);
printf("Entry at -> %lxn", 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: %pn", func);
getchar();
func(argc, argv);
return 0;
}


Let me explain a bit further:
When i run objdump -d filename.so i get that the _start is at 0x6c0. The elf header entry point returns 0x5c0 (i compensate it adding 256 in dec).



Also pmap shows an executable area being created at lets say 0x7fdf94d0c000
so the function pointer direction that i get and which i call is at 0x7fdf94d0c6c0 this should be the entry point and callable via function pointer. But what i get is, you guessed it: segfault.



Las thing that i would like to point out is that i have the same example running with (dlopen, dlsym, dlclose) but its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how. (perhaps there is a simpler way that im missing).



I based the code on this jit example



Thank you in advance!



Edit: This is the code of the .c that i compile into .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.esn");
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");
}









share|improve this question

























  • printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

    – Andrew Henle
    Nov 14 '18 at 10:25











  • @AndrewHenle edited code.

    – Tretorn
    Nov 14 '18 at 10:28














1












1








1








I want to dynamically load a library without using functions from dlfcn.h i have a folder full of .so files compiled with:



gcc -Wall -shared -fPIC -o filename.so filename.c


And all of them have an entry function named:



void __start(int size, char** cmd);


(I know, probably not the best name)



then i try to call open over the so, then read the elf header as an Elf64_Ehdr load it into memory with mmap (i know i should use mprotect but i want to make it work first and then add the security) and finally adding the the elf header entry to the pointer returned by mmap (plus an offset of 0x100).



The test code is the following:



#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 -> %pn", ptr);
printf("Entry at -> %lxn", 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: %pn", func);
getchar();
func(argc, argv);
return 0;
}


Let me explain a bit further:
When i run objdump -d filename.so i get that the _start is at 0x6c0. The elf header entry point returns 0x5c0 (i compensate it adding 256 in dec).



Also pmap shows an executable area being created at lets say 0x7fdf94d0c000
so the function pointer direction that i get and which i call is at 0x7fdf94d0c6c0 this should be the entry point and callable via function pointer. But what i get is, you guessed it: segfault.



Las thing that i would like to point out is that i have the same example running with (dlopen, dlsym, dlclose) but its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how. (perhaps there is a simpler way that im missing).



I based the code on this jit example



Thank you in advance!



Edit: This is the code of the .c that i compile into .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.esn");
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");
}









share|improve this question
















I want to dynamically load a library without using functions from dlfcn.h i have a folder full of .so files compiled with:



gcc -Wall -shared -fPIC -o filename.so filename.c


And all of them have an entry function named:



void __start(int size, char** cmd);


(I know, probably not the best name)



then i try to call open over the so, then read the elf header as an Elf64_Ehdr load it into memory with mmap (i know i should use mprotect but i want to make it work first and then add the security) and finally adding the the elf header entry to the pointer returned by mmap (plus an offset of 0x100).



The test code is the following:



#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 -> %pn", ptr);
printf("Entry at -> %lxn", 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: %pn", func);
getchar();
func(argc, argv);
return 0;
}


Let me explain a bit further:
When i run objdump -d filename.so i get that the _start is at 0x6c0. The elf header entry point returns 0x5c0 (i compensate it adding 256 in dec).



Also pmap shows an executable area being created at lets say 0x7fdf94d0c000
so the function pointer direction that i get and which i call is at 0x7fdf94d0c6c0 this should be the entry point and callable via function pointer. But what i get is, you guessed it: segfault.



Las thing that i would like to point out is that i have the same example running with (dlopen, dlsym, dlclose) but its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how. (perhaps there is a simpler way that im missing).



I based the code on this jit example



Thank you in advance!



Edit: This is the code of the .c that i compile into .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.esn");
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");
}






c elf mmap






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 14 '18 at 16:54







Tretorn

















asked Nov 14 '18 at 10:06









TretornTretorn

13510




13510













  • printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

    – Andrew Henle
    Nov 14 '18 at 10:25











  • @AndrewHenle edited code.

    – Tretorn
    Nov 14 '18 at 10:28



















  • printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

    – Andrew Henle
    Nov 14 '18 at 10:25











  • @AndrewHenle edited code.

    – Tretorn
    Nov 14 '18 at 10:28

















printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

– Andrew Henle
Nov 14 '18 at 10:25





printf("PTR AT -> %lxn", ptr); is the wrong format for a pointer. %p is used to print a pointer.

– Andrew Henle
Nov 14 '18 at 10:25













@AndrewHenle edited code.

– Tretorn
Nov 14 '18 at 10:28





@AndrewHenle edited code.

– Tretorn
Nov 14 '18 at 10:28












1 Answer
1






active

oldest

votes


















3















its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.




For this to work, your __start must be completely stand-alone, and not call any other library (you violated that requirement by calling strcmp and printf).



The moment you call an unresolved symbol, you ask the dynamic loader to resolve that symbol, and the loader needs all kinds of info for that. That info is normally set up during dlopen call. Since you bypassed dlopen, it is not at all surprising that your program crashes.



Your first step should be to change your code such that __start doesn't do anything at all (is empty), and verify that you can then call __start. That would confirm that you are computing its address correctly.



Second, add a crash to that code:



void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}


and verify that you are observing the crash now. That will confirm that your code is getting called.



Third, remove the crashing code and use only direct system calls (e.g. write(1, "Hellon", 6) (but don't call write -- you must implement it directly in your library)) to implement whatever you need.






share|improve this answer


























  • Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

    – Tretorn
    Nov 21 '18 at 1:32






  • 1





    @Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

    – Employed Russian
    Nov 21 '18 at 2:52











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297596%2fmmap-load-shared-object-and-get-function-pointer%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









3















its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.




For this to work, your __start must be completely stand-alone, and not call any other library (you violated that requirement by calling strcmp and printf).



The moment you call an unresolved symbol, you ask the dynamic loader to resolve that symbol, and the loader needs all kinds of info for that. That info is normally set up during dlopen call. Since you bypassed dlopen, it is not at all surprising that your program crashes.



Your first step should be to change your code such that __start doesn't do anything at all (is empty), and verify that you can then call __start. That would confirm that you are computing its address correctly.



Second, add a crash to that code:



void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}


and verify that you are observing the crash now. That will confirm that your code is getting called.



Third, remove the crashing code and use only direct system calls (e.g. write(1, "Hellon", 6) (but don't call write -- you must implement it directly in your library)) to implement whatever you need.






share|improve this answer


























  • Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

    – Tretorn
    Nov 21 '18 at 1:32






  • 1





    @Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

    – Employed Russian
    Nov 21 '18 at 2:52
















3















its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.




For this to work, your __start must be completely stand-alone, and not call any other library (you violated that requirement by calling strcmp and printf).



The moment you call an unresolved symbol, you ask the dynamic loader to resolve that symbol, and the loader needs all kinds of info for that. That info is normally set up during dlopen call. Since you bypassed dlopen, it is not at all surprising that your program crashes.



Your first step should be to change your code such that __start doesn't do anything at all (is empty), and verify that you can then call __start. That would confirm that you are computing its address correctly.



Second, add a crash to that code:



void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}


and verify that you are observing the crash now. That will confirm that your code is getting called.



Third, remove the crashing code and use only direct system calls (e.g. write(1, "Hellon", 6) (but don't call write -- you must implement it directly in your library)) to implement whatever you need.






share|improve this answer


























  • Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

    – Tretorn
    Nov 21 '18 at 1:32






  • 1





    @Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

    – Employed Russian
    Nov 21 '18 at 2:52














3












3








3








its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.




For this to work, your __start must be completely stand-alone, and not call any other library (you violated that requirement by calling strcmp and printf).



The moment you call an unresolved symbol, you ask the dynamic loader to resolve that symbol, and the loader needs all kinds of info for that. That info is normally set up during dlopen call. Since you bypassed dlopen, it is not at all surprising that your program crashes.



Your first step should be to change your code such that __start doesn't do anything at all (is empty), and verify that you can then call __start. That would confirm that you are computing its address correctly.



Second, add a crash to that code:



void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}


and verify that you are observing the crash now. That will confirm that your code is getting called.



Third, remove the crashing code and use only direct system calls (e.g. write(1, "Hellon", 6) (but don't call write -- you must implement it directly in your library)) to implement whatever you need.






share|improve this answer
















its required that i use the mmap trick. I have seen my professor implement it successfully but i cannot figure out how.




For this to work, your __start must be completely stand-alone, and not call any other library (you violated that requirement by calling strcmp and printf).



The moment you call an unresolved symbol, you ask the dynamic loader to resolve that symbol, and the loader needs all kinds of info for that. That info is normally set up during dlopen call. Since you bypassed dlopen, it is not at all surprising that your program crashes.



Your first step should be to change your code such that __start doesn't do anything at all (is empty), and verify that you can then call __start. That would confirm that you are computing its address correctly.



Second, add a crash to that code:



void __start(...)
{
int *p = NULL;
*p = 42; // should crash here
}


and verify that you are observing the crash now. That will confirm that your code is getting called.



Third, remove the crashing code and use only direct system calls (e.g. write(1, "Hellon", 6) (but don't call write -- you must implement it directly in your library)) to implement whatever you need.







share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 15 '18 at 15:46

























answered Nov 15 '18 at 15:16









Employed RussianEmployed Russian

124k20166236




124k20166236













  • Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

    – Tretorn
    Nov 21 '18 at 1:32






  • 1





    @Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

    – Employed Russian
    Nov 21 '18 at 2:52



















  • Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

    – Tretorn
    Nov 21 '18 at 1:32






  • 1





    @Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

    – Employed Russian
    Nov 21 '18 at 2:52

















Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

– Tretorn
Nov 21 '18 at 1:32





Thank you for your answer and sorry about not responding until today: What if i need complex code to be loaded?. Actually the code i uploaded as a sample is the simplest of them all. I cannot implement every syscall by myself. Any ideas?

– Tretorn
Nov 21 '18 at 1:32




1




1





@Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

– Employed Russian
Nov 21 '18 at 2:52





@Tretorn "What is I need complex code" -- then you'll need to re-implement part of dynamic loader. But why can't you simply dlopen this library?

– Employed Russian
Nov 21 '18 at 2:52


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53297596%2fmmap-load-shared-object-and-get-function-pointer%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Bressuire

Vorschmack

Quarantine