Search code examples
c++linuxhookncursesld-preload

Unable to hook ncurses functions with LD_PRELOAD


I'm trying to hook some ncurses functions but they don't have any effect. ncurses isn't statically linked, so I don't see why it wouldn't work.

test.cpp

#include <cstdio>
#include <cstdlib>
#include <curses.h>

int main() {
  initscr();
  cbreak();
  noecho();

  getch();

  endwin();

  return 0;
}

Compiled with: gcc test.cpp -o test -std=c++11 -lncurses

hook.cpp

#include <dlfcn.h>
#include <cstdio>
#include <cstdlib>

int getch() {
  typedef int getch ();
  getch* old_getch = (getch*) dlsym(RTLD_NEXT, "getch");

  int result = old_getch();

  fprintf(stderr, "getch() = %i\n", result);

  return result;
}

int noecho() {
  typedef int noecho ();
  noecho* old_noecho = (noecho*) dlsym(RTLD_NEXT, "noecho");

  int result = old_noecho();

  fprintf(stderr, "noecho() = %i\n", result);

  return result;
}

int endwin() {
  typedef int endwin ();
  endwin* old_endwin = (endwin*) dlsym(RTLD_NEXT, "endwin");

  int result = old_endwin();

  printf("endwin called");

  return result;
}

Compiled with: gcc hook.cpp -o hook.so -shared -ldl -fPIC -std=c++11

It sadly outputs nothing, and I'm completely stumped.


Solution

  • The specification doesn't state getch has to be a function (not a macro). Actually, in ncurses-6.1, getch defined as

    #define getch() wgetch(stdscr)
    

    Nonetheless, there is a getch function in libncurses (which simply calls wgetch(stdscr)), so dlsym(libncurses_handle,"getch") does work.