/proc/[pid]/mem
позволяет получить доступ к виртуальной памяти процесса.
Смещения в этом файле соответствуют виртуальным адресам. /proc/[pid]/maps
говорит вам, какие диапазоны адресов поддерживаются фактической памятью (и где сама память поддерживается файлами ).
Все это задокументировано на странице proc (5 ).
Процесс может обращаться к памяти только тех процессов, которые запущены под тем же пользователем, что и он сам, и которые не имеют setgid/uid. Раньше было так, что вам нужно было ptrace()процесса, чтобы получить доступ к его памяти через /proc/[pid]/mem
, но это НЕ ВЕРНО уже довольно давно (more именно, поскольку этот коммит от января 2012 года (v3.2+ ), целью которого было исправление ошибки безопасности, также отредактированный в статье lwn ).
В окне терминала:
% echo $$ # show our pid
6744
% read -sp 'secret pasword: '; echo
secret pasword:
%
Затем в другом окне терминала:
% grep heap /proc/6744/maps
01bb7000-01c3e000 rw-p 00000000 00:00 0 [heap]
% dd if=/proc/6744/mem bs=1 skip=$((0x01bb7000)) count=$((0x01c3e000-0x01bb7000)) status=none |
strings | less
...
% dd if=/proc/6744/mem bs=1 skip=$((0x01bb7000)) count=$((0x01c3e000-0x01bb7000)) status=none |
strings | grep qwerty
qwertyuiop # here is the "secret password"
Люди обычно используют отладчик, подобный gdb
, чтобы заглянуть в память запущенного процесса вместо элементарных способов, подобных этому (отладчик знает формат структур, используемых процессом, может отслеживать указатели, списки и т. д. ), но принцип в основном тот же.
Последние ядра Linux также имеют более приятный интерфейс вместо /proc/[pid]/mem
, напримерprocess_vm_readv
. Так же, как с /proc/[pid]/mem
или PTRACE_PEEK
и т. д., вам нужен root -как привилегии (CAP_SYS_PTRACE
), чтобы прочитать память процесса, которым вы не владеете.
Я сам нашел решение:
В моем Dockerfile я устанавливаю пакет dbus, но ничего не связанного с X11. Я также устанавливаю все зависимости своего программного обеспечения, в том числе те, которые относятся к скрипту Python, которым я поделился в вопросе.
В моем Dockerfile есть следующие строки:
COPY start.sh /usr/local/bin
RUN chmod +x /usr/local/bin/start.sh
ENTRYPOINT ["/bin/bash", "/usr/local/bin/start.sh"]
Содержимое файла start.sh таково:
#!/usr/bin/env bash
export DBUS_SESSION_BUS_ADDRESS=`dbus-daemon --fork --config-file=/usr/share/dbus-1/session.conf --print-address`
exec bash
Таким образом, запуск контейнера дает мне оболочку с правильно установленным DBUS _SESSION _BUS _ADDRESS. Я могу запустить фон тестового сценария и сказать
dbus-send --print-reply --session --dest=com.testservice /testservice com.testservice.Exit
убить его.