Задачка!
Задача является хитрым продолжением таски вида:
У вас есть запущенное приложение, исполняемый файл которого удален - как его восстановить?
Ее решение весьма тривиальное и даже могу его озвучить:
Моя задача на порядки сложнее.
Итак, есть некое приложение, пусть это будет /usr/bin/host, которое было запущено с библиотекой libworker.so через LD_PRELOAD следующим образом:
LD_PRELOAD=/somepath/libworker.so /usr/bin/host.
Договоримся о том, что в библиотеке libworker крутится внешний цикл и пока приложение с этой библиотекой (/usr/bin/host) не будет убито - оно будет висеть в памяти.
А теперь самое интересное - удаляем библиотеку libworker с диска.
Теперь псевдофайл /proc/$pid/smaps примет вот такой вид (привожу лишь выдержку):
Есть путь в лоб - использование debugfs и посмотреть содержимое файла из внутренностей ext3/ext4. Но в случае высокой нагрузки и отсутствия настолько высокого уровня доступа - это решение неосуществимо.
Итак, как извлечь удаленную библиотеку из памяти? :)
Задача является хитрым продолжением таски вида:
У вас есть запущенное приложение, исполняемый файл которого удален - как его восстановить?
Ее решение весьма тривиальное и даже могу его озвучить:
cp /proc/$pid/exe /root/rescued_fileЛибо если речь идет о файле, открытом приложением на запись:
cp /proc/$pid/fd/X /root/rescued_file
Моя задача на порядки сложнее.
Итак, есть некое приложение, пусть это будет /usr/bin/host, которое было запущено с библиотекой libworker.so через LD_PRELOAD следующим образом:
LD_PRELOAD=/somepath/libworker.so /usr/bin/host.
Договоримся о том, что в библиотеке libworker крутится внешний цикл и пока приложение с этой библиотекой (/usr/bin/host) не будет убито - оно будет висеть в памяти.
А теперь самое интересное - удаляем библиотеку libworker с диска.
Теперь псевдофайл /proc/$pid/smaps примет вот такой вид (привожу лишь выдержку):
7fc51b53f000-7fc51b540000 rw-p 00006000 b6:ff161 30664 (deleted)/somepath/libworker.soКак видите, мы видим номер inode, принадлежащий данной библиотеке, видим ее имя, но с диска она удалена и возможности ее прочесть нету. В открытых файловых дескрипторах (/proc/$pid/fd) она также не значится.
Size: 4 kB
Rss: 4 kB
Pss: 4 kB
Shared_Clean: 0 kB
Shared_Dirty: 0 kB
Private_Clean: 0 kB
Private_Dirty: 4 kB
Referenced: 4 kB
Anonymous: 4 kB
AnonHugePages: 0 kB
Swap: 0 kB
KernelPageSize: 4 kB
MMUPageSize: 4 kB
Есть путь в лоб - использование debugfs и посмотреть содержимое файла из внутренностей ext3/ext4. Но в случае высокой нагрузки и отсутствия настолько высокого уровня доступа - это решение неосуществимо.
Итак, как извлечь удаленную библиотеку из памяти? :)
через /proc/PID/mem прочитать указанный диапазон адресов с помощью dd например или gdb. Только тут дата-секция, надо читать .text, где права r-xp
ReplyDeleteВопрос в реализации :) Что примерно делать - понятно. А вот работающий PoC по извлечению библиотеки из памяти - отдельный вопрос.
Deletecp /proc/1/map_files/XXXXX-XXXXX xxxx
ReplyDeleteНа OpenVZ ядре этих файликов нету :(
Delete