Вы можете использовать динамическую c загрузочную библиотеку (например, -ldl
) и использовать некоторые из ее функций, в частности, dlsym
.
Есть три шага:
- Сначала создайте исходный файл.
- Создайте общую библиотеку (
.so
файл) из этого исходного файла - Вызовите целевую программу (установите переменную среды
LD_PRELOAD
, чтобы она указывала на ваш .so
file
Обратите внимание, что для перехвата данной функции ваша функция должна быть определена с таким же именем.
У вас может быть столько же функции перехвата, как вы хотите, в исходном файле.
Вот пример исходного кода для перехвата (например) read
...
// NOTE: need _GNU_SOURCE above for RTLD_NEXT in dlfcn.h
#define _GNU_SOURCE
#include <unistd.h>
#include <dlfcn.h>
#include <string.h>
static void
msg(const char *buf)
{
int len;
len = strlen(buf);
write(1,buf,len);
}
// read -- read a file
ssize_t
read(int unit,void *buf,size_t buflen)
{
static ssize_t (*proc)(int,void *,size_t) = NULL;
ssize_t rlen;
// get pointer to real function (only needs to be done once)
if (proc == NULL)
proc = dlsym(RTLD_NEXT,"read");
// do [whatever] stuff before real read ...
msg("PHONY: before\n");
// invoke the real function
rlen = proc(unit,buf,buflen);
// do [whatever] stuff after real read ...
msg("PHONY: after\n");
return rlen;
}
Вот пример целевой программы :
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
int
main(void)
{
int fd;
int rlen;
char buf[100];
fd = open("/etc/passwd",O_RDONLY);
rlen = read(fd,buf,sizeof(buf));
close(fd);
printf("main: read %d bytes\n",rlen);
return 0;
}
Теперь создайте общую библиотеку (.so
).
Обратите внимание, что ниже представлен только один исходный файл. Но вы можете создать библиотеку из такого количества отдельные исходные файлы, как вы sh (например, вы можете поместить одну функцию перехвата для каждого исходного файла или поместить все в один источник файл на ваш выбор).
Вот [грубый] Makefile
(который создает общую библиотеку и пример целевой программы):
all: mylib.so target
read.o: read.c
cc -c -fPIC read.c
mylib.so: read.o
cc -shared -o mylib.so read.o -ldl
target: target.c
cc -o target target.c
test:
env LD_PRELOAD=./mylib.so ./target
clean:
rm -f mylib.so *.o target
Теперь, чтобы вызвать целевую программу (например):
make test
Вот сгенерированный результат теста:
env LD_PRELOAD=./mylib.so ./target
PHONY: before
PHONY: after
main: read 100 bytes