Intercept dynamic library methods with LD PRELOAD

From RidgeRun Developer Wiki
Revision as of 16:19, 23 May 2023 by Anavarro (talk | contribs) (Created page with "=Introduction= Let's say you have a binary called 'main' which was compiled against a shared memory 'libprint1.so', which has a method called print_msg() which prints 'hello f...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

Introduction

Let's say you have a binary called 'main' which was compiled against a shared memory 'libprint1.so', which has a method called print_msg() which prints 'hello from print1'. This looks like this

main.c

#include "print.h"

int main(int argc, char *argv[])
{
    print_msg();
    return 0;
}

print.h

#ifndef RR_PRINT_H
#define RR_PRINT_H

#include <stdio.h>

void print_msg();

#endif

print1.c

#include "print.h"

void print_msg(){
    printf("hello from print1\n");
}

This library can be compiled as dynamic and linked to the main program with

gcc -shared -o libprint1.so print1.c
gcc -o main main.c -L. -lprint1

As expected when executed the program will output

hello from print1

Lets say you don't want to recompile main, or you simply do not have that source code, but you want to replace print_msg with another functionality. Here is where the concept of LD_PRELOAD comes in handy. This is an environment variable that will instruct the dynamic linker the priority of the dynamic libraries when executing a binary.

Let's change the message of print_msg()

print2.c

#include "print.h"

void print_msg(){
    printf("hello from print2\n");
}

Again, compile with

gcc -shared -o libprint2.so print2.c

But now, execute main like this

LD_PRELOAD=libprint2.so ./main

The output will be

hello from print2

You can even replace calls to stdlib like malloc and free, to help you keep track of memory allocation.