Skip to content

Instantly share code, notes, and snippets.

@rand-tech
Created April 4, 2024 05:19
Show Gist options
  • Select an option

  • Save rand-tech/612fbd1853991dad7e0dac7bea81b6ef to your computer and use it in GitHub Desktop.

Select an option

Save rand-tech/612fbd1853991dad7e0dac7bea81b6ef to your computer and use it in GitHub Desktop.

inspecting an executable using ifunc

  • How to work with ifunc (with handson examples)
  • How to do a quick inspection using CLI commands
  • How to deep dive using IDA

How to work with ifunc (with handson examples)

Go read

Example

code
/* example.c */
#include <stdio.h>

void foo_real() { printf("%p\t->\t%s\n", foo_real, __func__); }

void foo() __attribute__((ifunc("resolve_foo")));

static void *resolve_foo(void) {
    // Return the function address for `foo`
    printf("%p\t->\t%s\n", foo_real, __func__);
    return foo_real;
}

int main() {
    printf("%p\t->\t%s\n", main, __func__);
    foo();  // Calls the resolved function
    return 0;
}
compile
gcc example.c -o example
output
0x57c0f109d169	->	resolve_foo
0x57c0f109d1d5	->	main
0x57c0f109d169	->	foo_real

Comparison with constructor

/* example.c */
#include <stdio.h>

void foo_real() { printf("%p\t->\t%s\n", foo_real, __func__); }

void foo() __attribute__((ifunc("resolve_foo")));

static void *resolve_foo(void) {
    printf("%p\t->\t%s\n", __func__, __func__);
    return foo_real;
}

__attribute__((constructor))
void aloha() {
    printf("%p\t->\t%s\n", __func__, __func__);
}

int main() {
    printf("%p\t->\t%s\n", main, "main");
    foo();  // Calls the resolved function
    return 0;
}
/* output:
0x5d040a9f5028	->	resolve_foo
0x5d040a9f5034	->	aloha
0x5d040a9f4208	->	main
0x5d040a9f4169	->	foo_real
*/

How to do a quick inspection using CLI commands

  • readelf

    readelf -s <executable>
    

    Example:
    Observe that 69th entry (foo) is a IFUNC entry mapped to address 00000000000011e0. The resolver function (resolve_foo) is also mapped to the same address.

    Symbol table '.symtab' contains 78 entries:
       Num:    Value          Size Type    Bind   Vis      Ndx Name
         0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
    ...
        34: 0000000000000000     0 SECTION LOCAL  DEFAULT   34 .debug_ranges
        35: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS example.c
        36: 0000000000002028     9 OBJECT  LOCAL  DEFAULT   18 __func__.2512
        37: 00000000000011e0    53 FUNC    LOCAL  DEFAULT   16 resolve_foo
        38: 0000000000002018    12 OBJECT  LOCAL  DEFAULT   18 __func__.2517
        39: 0000000000002010     5 OBJECT  LOCAL  DEFAULT   18 __func__.2520
        40: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS crtstuff.c
    ...
    
        61: 0000000000001298     0 FUNC    GLOBAL HIDDEN    17 _fini
        62: 00000000000011b0    37 FUNC    GLOBAL DEFAULT   16 foo_real
        63: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND __libc_start_mai[...]
        64: 0000000000004000     0 NOTYPE  GLOBAL DEFAULT   25 __data_start
        65: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
        66: 0000000000004008     0 OBJECT  GLOBAL HIDDEN    25 __dso_handle
        67: 0000000000002000     4 OBJECT  GLOBAL DEFAULT   18 _IO_stdin_used
        68: 0000000000001220   101 FUNC    GLOBAL DEFAULT   16 __libc_csu_init
        69: 00000000000011e0    53 IFUNC   GLOBAL DEFAULT   16 foo
        70: 0000000000004018     0 NOTYPE  GLOBAL DEFAULT   26 _end
        71: 00000000000010c0    47 FUNC    GLOBAL DEFAULT   16 _start
        72: 0000000000004010     0 NOTYPE  GLOBAL DEFAULT   26 __bss_start
        73: 0000000000001080    55 FUNC    GLOBAL DEFAULT   16 main
    ...
    

    The resolve_foo gets called when loaded without any direct flow.

  • nm

    nm <binary file>
    

    Same idea. Now look for 'i' instead of 'IFUNC'.

How to deep dive using IDA

  1. Navigate to the ifunc resolver.
  2. Note the possible return address value.
  3. The rest is the same.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment