Переопределение общих библиотек

Последнее обновление: 30.01.2024

Одним из преимуществ общих библиотек и динамической компоновки является возможность переопределения функций библиотеки. Загрузчик поддерживает переменную среды LD_PRELOAD, которая предварительно загружает символы библиотеки в исполняемый файл перед загрузкой общих библиотек, запрошенных исполняемым файлом. Следовательно, если символ уже определен в библиотеке, указанной в LD_PRELOAD, то он имеет приоритет перед символами, загруженными позже. Мы можем использовать эту возможность для переопределения библиотечных функций своими, даже если код уже скомпилирован, и у нас нет доступа к исходному коду!

Данная возможность часто используется для предоставления более оптимизированных версий различных системных функций, таких как malloc. В качестве простого примера переопределим функцию printf.

Пусть у нас изначально есть файл app.asm, который использует функцию printf для вывода некоторой строки на консоль:

global _start
extern printf 
 
section .data 
message: db "Hello Work",10, 0      ; строка для вывода на консоль

section .text
_start:
    lea rdi, [rel message]
    call printf
    mov rax, 60    
    syscall 

Скомпилируем и выполним программу:

root@Eugene:~/asm# nasm -felf64 app.asm -o app.o
root@Eugene:~/asm# ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -lc app.o -o app
root@Eugene:~/asm# ./app
Hello Work
root@Eugene:~/asm# 

В итоге мы получаем ожидаемый результат.

Далее определим следующий файл print.asm:

global printf:function

section .data 
message: db "new printf test",10, 0 
len equ $-message

section .text
printf:
    mov rdi, 1
    lea rsi, [rel message]
    mov rdx, len
    mov rax, 1      ; системный вызов номер 1 - функция write
    syscall
    ret

Данный код с помощью системного вызова номер 1 (системная функция write) выводит строку на консоль.

Для компиляции и компановки кода этой библиотеки используем команды:

nasm -felf64 print.asm -o print.o
ld -shared print.o -o print.so

Затем установим скомпилированную библиотеку для предзагрузки с помощью команды

export LD_PRELOAD=./print.so

В конце снова выполним приложение "app"

root@Eugene:~/asm# nasm -felf64 app.asm -o app.o
root@Eugene:~/asm# ld --dynamic-linker=/lib64/ld-linux-x86-64.so.2 -lc app.o -o app
root@Eugene:~/asm# ./app
Hello Work
root@Eugene:~/asm# nasm -felf64 print.asm -o print.o
root@Eugene:~/asm# ld -shared print.o -o print.so
root@Eugene:~/asm# export LD_PRELOAD=./print.so
root@Eugene:~/asm# ./app
new printf test
root@Eugene:~/asm# 

Для удаления предзагрузки нашей библиотеки (удаления значения переменной LD_PRELOAD) следует выполнить команду

unset LD_PRELOAD
Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850