I'm trying to analyse a compiled file for cybersec learning purposes and want to use a particular function.
Here is the output of nm --defined-only ./compiled_file
:
0000000000200d98 d _DYNAMIC
0000000000200f88 d _GLOBAL_OFFSET_TABLE_
0000000000000ba0 R _IO_stdin_used
0000000000000d64 r __FRAME_END__
0000000000000bfc r __GNU_EH_FRAME_HDR
0000000000201010 D __TMC_END__
0000000000201010 B __bss_start
0000000000201000 D __data_start
00000000000007d0 t __do_global_dtors_aux
0000000000200d90 t __do_global_dtors_aux_fini_array_entry
0000000000201008 D __dso_handle
0000000000200d88 t __frame_dummy_init_array_entry
0000000000200d90 t __init_array_end
0000000000200d88 t __init_array_start
0000000000000b90 T __libc_csu_fini
0000000000000b20 T __libc_csu_init
0000000000201010 D _edata
0000000000201018 B _end
0000000000000b94 T _fini
0000000000000660 T _init
0000000000000710 T _start
0000000000201010 b completed.7696
0000000000201000 W data_start
0000000000000740 t deregister_tm_clones
0000000000000810 t frame_dummy
0000000000000a92 T main
000000000000081a T function_I_would_like_to_use \\ << this one
0000000000000780 t register_tm_clones
I mainly use Python (I know very little about C/C++, just the basics), so, naturally, I've been trying to mess about with this file in Python using the ctypes library, creating a CDLL object with the file, but none of the function names above appear in the dir() of the object or of its attributes as far as I can see.
I started with something similar to this: https://book.pythontips.com/en/latest/python_c_extension.html#ctypes and then went deeper and deeper down the rabbit hole of dir()/__dict__
to try to find things I recognised, no luck.
As you can see, I'm trying to reverse engineer this ELF without any real knowledge of machine code, but hoping I'll learn something in the process haha! For the purposes of the exercise, I'd also rather do this without external (third-party) libraries.
output of file ./compiled_file
is:
./compiled_file: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=cf62f3afa6f99f98a863d44932d2e
0f9f8594e71, not stripped
So, my main question is, as above, is there a way to call one of the 'defined' functions listed by nm
, objdump
, etc. in Python or otherwise? I read that the BuildID[sha1] can be useful for debugging. Do I need this perhaps for my purposes?
I hope this question is not too broad. Essentially, I'm mainly looking for a yes or no, with perhaps a little nod in the right direction, as to whether I can call that function with the info I have above!
EDIT:
thanks to the first, extremely quick answer and comment I've been messing about with dlopen/dlsym
in C. Script is as follows (adapted from here):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
int main(int argc, char** argv) {
void *handle;
void (*func_in_question)(const char*);
handle = dlopen("./compiled_file", RTLD_LAZY);
if (!handle) {
/* fail to load the library */
fprintf(stderr, "Error: %s\n", dlerror());
return EXIT_FAILURE;
}
*(void**)(&func_in_question) = dlsym(handle, "function_I_would_like_to_use");
if (!func_in_question) {
/* no such symbol */
fprintf(stderr, "Error: %s\n", dlerror());
dlclose(handle);
return EXIT_FAILURE;
}
func_in_question(argv[1]);
dlclose(handle);
return EXIT_SUCCESS;
}
Seems to work as expected, apart from it returns:
Error: ./compiled_file: undefined symbol: function_I_would_like_to_use
(the same error, in fact, that led me to ask the question ¯\_(ツ)_/¯ )
The original question, however, has been answered.
Yes, it is possible. The point of having exported symbols in shared libraries is to be able to use them - after all. In C, you can do this either by linking the library to the application (not really an option for python), or runtime loading the library and finding the required symbol (on linux: dlopen, dlsym). The manpage example shows how to do this in C.