├── .gitignore ├── LICENSE ├── Makefile ├── README.md └── program.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Object files 5 | *.o 6 | *.ko 7 | *.obj 8 | *.elf 9 | 10 | # Linker output 11 | *.ilk 12 | *.map 13 | *.exp 14 | 15 | # Precompiled Headers 16 | *.gch 17 | *.pch 18 | 19 | # Libraries 20 | *.lib 21 | *.a 22 | *.la 23 | *.lo 24 | 25 | # Shared objects (inc. Windows DLLs) 26 | *.dll 27 | *.so 28 | *.so.* 29 | *.dylib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | *.i*86 36 | *.x86_64 37 | *.hex 38 | 39 | # Debug files 40 | *.dSYM/ 41 | *.su 42 | *.idb 43 | *.pdb 44 | 45 | # Kernel Module Compile Results 46 | *.mod* 47 | *.cmd 48 | .tmp_versions/ 49 | modules.order 50 | Module.symvers 51 | Mkfile.old 52 | dkms.conf 53 | 54 | ifunc-resolver 55 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Calle Svensson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | 2 | ifunc-resolver: *.c 3 | gcc -o ifunc-resolver -Wall -Wpedantic program.c 4 | 5 | dump: ifunc-resolver 6 | ./ifunc-resolver 7 | 8 | clean: 9 | rm -f ifunc-resolver 10 | 11 | .PHONY: dump clean 12 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GNU IFUNC offset dumper 2 | 3 | The GNU indirect function support (IFUNC) is a feature of the GNU toolchain that allows a developer to create multiple implementations of a given function and to select amongst them at runtime using a resolver function which is also written by the developer. More info: https://sourceware.org/glibc/wiki/GNU_IFUNC 4 | 5 | These various implementations are not exposed in the symbols table or any other static resource. It is therefore difficult to get the offsets of these functions which are sometimes useful in some program analysis scenarios such as exploit development. 6 | 7 | This tool loads the list of IFUNC functions in libc and prints out the function names and their offsets. This can then be used in further work. 8 | 9 | ``` 10 | > make 11 | > ./ifunc-resolver 12 | 0x18d360 __memcpy_chk_avx512_no_vzeroupper 13 | 0x18dd50 __memcpy_chk_avx512_unaligned 14 | 0x18ddc0 __memcpy_chk_avx512_unaligned_erms 15 | 0x189010 __memcpy_chk_avx_unaligned 16 | 0x189070 __memcpy_chk_avx_unaligned_erms 17 | 0x168e20 __memcpy_chk_ssse3_back 18 | 0x1638b0 __memcpy_chk_ssse3 19 | ... 20 | ``` 21 | 22 | If you want to use this on a different libc version, you can load that with LD_PRELOAD. 23 | 24 | ``` 25 | > make 26 | > LD_PRELOAD=$(pwd)/libc-2.13.37.so ./ifunc-resolver 27 | 0x18d360 __memcpy_chk_avx512_no_vzeroupper 28 | 0x18dd50 __memcpy_chk_avx512_unaligned 29 | ... 30 | ``` 31 | -------------------------------------------------------------------------------- /program.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define MAX_NUM_IMPL 256 8 | 9 | //From "include/ifunc-impl-list.h" 10 | struct libc_ifunc_impl 11 | { 12 | /* The name of function to be tested. */ 13 | const char *name; 14 | /* The address of function to be tested. */ 15 | void (*fn) (void); 16 | /* True if this implementation is usable on this machine. */ 17 | bool usable; 18 | }; 19 | 20 | extern size_t __libc_ifunc_impl_list (const char *name, struct libc_ifunc_impl *array, size_t max); 21 | 22 | const char* function_names[] = { 23 | "__memcpy_chk", 24 | "__memmove_chk", 25 | "__mempcpy_chk", 26 | "__memset_chk", 27 | "__wmemset_chk", 28 | "memchr", 29 | "memcmp", 30 | "memcpy", 31 | "memmove", 32 | "mempcpy", 33 | "memrchr", 34 | "memset", 35 | "rawmemchr", 36 | "stpcpy", 37 | "stpncpy", 38 | "strcasecmp", 39 | "strcasecmp_l", 40 | "strcat", 41 | "strchr", 42 | "strchrnul", 43 | "strcmp", 44 | "strcpy", 45 | "strcspn", 46 | "strlen", 47 | "strncasecmp", 48 | "strncasecmp_l", 49 | "strncat", 50 | "strncmp", 51 | "strncpy", 52 | "strnlen", 53 | "strpbrk", 54 | "strrchr", 55 | "strspn", 56 | "strstr", 57 | "wcschr", 58 | "wcscmp", 59 | "wcscpy", 60 | "wcslen", 61 | "wcsncmp", 62 | "wcsnlen", 63 | "wcsrchr", 64 | "wmemchr", 65 | "wmemcmp", 66 | "wmemset", 67 | NULL 68 | }; 69 | 70 | uintptr_t find_libc_base() { 71 | uintptr_t libc_pointer; 72 | for(libc_pointer = (uintptr_t)printf & (~0xFFF); *(uint32_t*)libc_pointer != 0x464c457f; libc_pointer-=0x1000); 73 | return libc_pointer; 74 | } 75 | 76 | int main() { 77 | struct libc_ifunc_impl entries[MAX_NUM_IMPL]; 78 | uintptr_t libc_base = find_libc_base(); 79 | 80 | for(const char** function_name = function_names; *function_name; function_name++) { 81 | size_t num_entries = __libc_ifunc_impl_list(*function_name, entries, MAX_NUM_IMPL); 82 | for(size_t i = 0; i < num_entries; i++) { 83 | printf("%p %s\n", (void*)((uintptr_t)entries[i].fn - (uintptr_t)libc_base), entries[i].name); 84 | } 85 | } 86 | 87 | return 0; 88 | } 89 | --------------------------------------------------------------------------------