В Linux[1] вы можете переопределить __libc_start_main()
функцию (оболочку, которая вызывает main()
функцию )из вашей библиотеки. Вы можете сделать это несколько раз.
Пример:
#define _GNU_SOURCE /* for RTLD_NEXT */
#include <string.h>
#include <unistd.h>
#include <dlfcn.h>
#include <err.h>
#ifdef __UCLIBC__
#define __libc_start_main __uClibc_main
#endif
#define STR_(s) #s
#define STR(s) STR_(s)
int __libc_start_main(
int (*main)(int,char**,char**), int ac, char **av,
int (*init)(int,char**,char**), void (*fini)(void),
void (*rtld_fini)(void), void *stack_end)
{
typeof(__libc_start_main) *real_lsm;
if(*(void**)&real_lsm = dlsym(RTLD_NEXT, STR(__libc_start_main)))
return real_lsm(main, ac - 1, av + 1, init, fini, rtld_fini, stack_end);
else
errx(1, "BUG: dlsym: %s", dlerror());
}
$ cc -fPIC -shared -Wall -W -Wno-parentheses skip.c -o skip1.so -ldl
$ cc -fPIC -shared -Wall -W -Wno-parentheses skip.c -o skip2.so -ldl
$ LD_PRELOAD="./skip1.so./skip2.so" /bin/echo a b c d
c d
Это также работает, если вы явно связываете программу с библиотеками skip1.so
и т. д. Вы даже можете execve()
создать совершенно другую программу с совершенно другими аргументами.
[1] Это также работает с musl
, хотя его __libc_start_main
не принимает аргумент rtld_fini
. В uclibc эквивалентной функцией является __uClibc_main
.
Да,
dpkg -L package
использует список файлов, хранящихся в /var/lib/dpkg/info/package.list
(, заменяет package
соответствующим образом ).
Вы можете добавить содержимое в файл .list
для проверки:
cd /var/lib/dpkg/info
sudo cp zutils.list{,.bak}
echo /some/random/file | sudo tee -a zutils.list
dpkg -L zutils
sudo mv zutils.list{.bak,}
(замена zutils
на установленный вами пакет ). Вы увидите, что /some/random/file
указан как принадлежащий пакету, даже если файл на самом деле не существует.