1

I am working with dynamic linked libraries (.dll) on windows or shared objects (.so) on Linux.

My goal is to write some code, that can - give the absolute path of the library on the disk - return a list of all exported functions (the export table) of that library and ultimately be able to call those functions. This should work on windows (wit dll) as well as on Linux (with so).

I am writing kind of a wrapper that delgates function calls to the respective library. Therefore I receive a path, a function name, and a list of parameters which I then want to forward. the thing is: I want to know whether the given function exists before trying to call it

From here I found a platform-independent way of opening and closing the library as well as getting a pointer to the function with the given name.
So the thing that remains is getting the names of available functions in the first place.

On this topic, I found this question dealing with the same kind of problem only that it asks for a Linux specific solution. In the given answer it is said

There is no libc function to do that. However, you can write one yourself (or copy/paste the code from a tool like readelf).

This clearly indicates that there are tools to do what I am looking for. The only question is, is there one that can work on windows as well as on Linux? If not how would I go about this on my own?


Here is a C# implementation (actually this is the code I want to port to C++) doing what I want (though windows only). To me, this appears as if the library structure is handled manually. If this is the way to go then where can I find the necessary information on the library structure?

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
Raven
  • 2,951
  • 2
  • 26
  • 42
  • 2
    Have you had a look at [Boost DLL](https://www.boost.org/doc/libs/1_69_0/doc/html/boost_dll.html)? It says that it can "query libraries for sections and exported symbols", and is designed "in a portable cross-platform manner". – lubgr Jan 15 '19 at 10:05
  • @lubgr Not yet. Will look into it now. Thanks! – Raven Jan 15 '19 at 10:07
  • 2
    What good is that if you wouldn't know the parameters a function accepts? – Eyal Cinamon Jan 15 '19 at 10:11
  • @EyalCinamon plenty: someone with domain knowledge might infer parameters from naming, or someone's actually just trying to write a fuzzer. – Marcus Müller Jan 15 '19 at 10:14
  • @EyalCinamon I am writing kind of a wrapper that delgates function calls to the respective library. Therefore I receive a path, a function name, and a list of parameters which I then want to forward. the thing is: I want to know whether the given function exists before trying to call it – Raven Jan 15 '19 at 10:14
  • you could have stated that in your question! – Marcus Müller Jan 15 '19 at 10:16
  • 1
    because, seriously, Raven, just use `dlopen` and try to get them using `dlsym` and simply check whether `dlsym` returned successfully. That's the way it was meant to be used – remember, shared libraries come from a C, not a C++ background, and for C programmers it's rather normal to check whether their library functions succeeded, so there's usually no "prerequisite check function". – Marcus Müller Jan 15 '19 at 10:17
  • @MarcusMüller So there won't be some sort of `SymbolNotFound` "runtime exception" (using java nomenclature here) that will crash my program? – Raven Jan 15 '19 at 10:19
  • 1
    @Raven if you already know the name of the function you need then you just test if getting a pointer to that function succeeds (`GetProcAddress`would return non-null in Windows.) – Eyal Cinamon Jan 15 '19 at 10:19
  • @lubgrfor Booster it appears to be [this](https://www.boost.org/doc/libs/1_69_0/doc/html/boost_dll/tutorial.html#boost_dll.tutorial.querying_libraries_for_symbols). Especially the used `symbols()` function. I'd add this as an additional answer but it was your idea. Therefore I give you the chance to that yourself - otherwise I'll add it in the next couple f days or so :) – Raven Jan 15 '19 at 10:22
  • 2
    Raven, read what I wrote. The function returns NULL. No exceptions in C. – Marcus Müller Jan 15 '19 at 10:25

2 Answers2

1

So, on unixoids (and both Linux and WinNT have a posix subsytem), the dlopen function can be used to load a dynamic library and get function pointers to known symbols by name of that symbol.

Getting a list of symbols as far as I know was never an aspect that POSIX bothered to specify, so long story short, the functions that can do that for you on Linux are specific to the libc used there (GNU libc, mostly), and on Windows to the libc used there. Portable code means having to different codebases for two different libcs!

If you don't want to depend on your libc, you'd have to have a binary object parser (for ELF shared libraries on Linux, PE on Windows) to read out symbol names from the files. There's actually plenty of those – obviously, WINE has one for PE that is portable (especially works on Linux as well), and every linker (including glibc's runtime linker) under Linux can parse ELF files.

Personally, radare2 is a fine reverse-engineering framework with plenty of language bindings that is actually meant to analyze binary files, and give you exported symbols (as well as being capable of extracting non-exported functions, constructing call-graphs etc). It does have debugger, i.e. jumping-into-functions capabilities, too.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94
1

So, knowing now that

I am writing kind of a wrapper that delgates function calls to the respective library. Therefore I receive a path, a function name, and a list of parameters which I then want to forward. the thing is: I want to know whether the given function exists before trying to call it

things become way easier: you don't actually need to get the list of exports. It's easier and just as fast to simply try.

So, on any POSIX system (and that includes both Windows' POSIX subsystem and Linux), dlopen will open the library and load the symbol table, and dlsym will look up a symbol from that table. If that symbol is not in the table, it simply returns NULL. So, you already have all the tables you think you need; just not explicitly, but queryable.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94