Вопрос или проблема
Я задал этот вопрос на сайте reverse engineering stackexchange: https://reverseengineering.stackexchange.com/questions/15169/transferring-control-of-ptrace-to-another-process потому что подумал, что вопрос о ptrace будет наиболее уместным там.
Я не получил никаких ответов, не знаю, связано ли это с тем, что там слишком мало людей, или они не очень знакомы с linux. В любом случае, я подумал, что стоит спросить здесь.
Я хотел бы создать процесс A. В A я хотел бы запустить второй процесс B. Я хотел бы, чтобы A продолжал отслеживать системные ресурсы. Когда будут выполнены определенные условия, я хочу, чтобы A ptrace B, запустил gdb и передал управление ptrace в gdb.
Это возможно? Если нет, есть ли способ, чтобы A приостановил B, запустил gdb с прикрепленным B, а затем “развесил” B?
Не могу комментировать, но поскольку пока нет никаких ответов:
Самый большой вопрос — зачем вообще переключаться на gdb, почему бы не продолжить с ptrace?
Самая сложная часть — это, безусловно, передача управления от ptrace к gdb. В частности, как удерживать процесс в приостановленном состоянии и подключить GDB, чтобы продолжить отладку с этого момента; когда ptrace отключает, дочерний процесс продолжает выполнение, и, насколько я знаю, это неизбежно.
Возможно, есть другой способ это сделать. В любом случае, зависит ли условие для перехода к GDB от системных ресурсов, отслеживаемых A, или условие локально для B?
И похоже, что ваши варианты ‘возможно ли это’ и ‘если нет’ предполагают сделать одно и то же, если я не ошибаюсь.
Вы можете посмотреть, как работает разрешение ptrace: https://www.kernel.org/doc/Documentation/security/Yama.txt
Вкратце:
- вы можете сделать, например,
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
. Это позволит любому процессу прикрепляться к любому другому процессу, однако ослабит безопасность.
Остальная часть этого ответа предполагает ptrace_scope = 1
, что является значением по умолчанию на моей машине.
- если
A
является родителемB
, тоA
можетptrace([B])
. - в противном случае
B
может вызватьprctl(PR_SET_PTRACER, [A], 0, 0, 0);
, чтобы сказать ”A
может ptrace меня”, или (немного менее безопасно)prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
, чтобы сказать “любой может ptrace меня”.
Таким образом, если вы хотите, чтобы gdb
подключался к B
, есть два способа:
-
Сделайте так, чтобы
B
разрешал прикрепление ptrace от процесса gdb. Используйте вышеупомянутый системный вызов.Вам не нужно модифицировать
B
, просто модифицируйтеA
, чтобы вызывать функцию послеfork()
, но доexec([B])
. -
Сделайте
gdb
родителемB
.Это сложно, но план такой:
- A сначала выполняет fork() на A1
- A1 создает B, затем ожидает сигнала от A
- A сигнализирует A1, чтобы
exec(gdb)
, чтобы заменить себя на gdb
Скорее всего, это лучшее, что вы можете получить. Потому что существуют только очень ограниченные способы изменить родительский процесс существующего процесса.
Ответ или решение
Передача контроля ptrace другому процессу
Введение
Запрос на передачу управления инструментом ptrace
другому процессу является актуальной задачей для специалистов в области разработки программного обеспечения и реверс-инжиниринга. В этом ответе мы рассмотрим методику, с помощью которой можно наблюдать за процессом, а затем передать управление от одного процесса другому, используя gdb
для дебага.
Предпосылки
Сначала уточним настройки, касающиеся безопасности в Linux, связанные с ptrace
. По умолчанию система имеет параметры, которые мешают процессу A прикрепляться к процессу B, если A не является родительским процессом B. Мы рассмотрим различные подходы для решения данной задачи с учетом основных требований:
- Система должна быть настроена для разрешения использования
ptrace
. - Процессы A и B должны быть правильно инициализированы.
- Возможность переключения контроля ptrace на gdb должна быть налажена.
Метод передачи управления
1. Разрешение на использование ptrace
Вы можете установить разрешения для ptrace
, используя команду echo
для изменения параметра ptrace_scope
. Например, выполнение следующей команды позволит процессу A прикрепляться к процессу B:
echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
Однако следует помнить, что это ослабляет безопасность системы. В большинстве случаев рекомендуется оставить значение по умолчанию (1).
2. Использование prctl
для разрешения на ptrace
Есть два подхода для разрешения процессу A использовать ptrace
на процессе B:
-
A является родительским для B: В этом случае A может непосредственно использовать
ptrace
. -
B должен разрешить A: В этом случае процесс B может вызвать системный вызов:
prctl(PR_SET_PTRACER, [A], 0, 0, 0);
Этот вызов можно выполнить из процесса A непосредственно перед запуском процесса B с помощью fork()
.
3. Разрешение на подключение gdb
Теперь, когда процесс A может использовать ptrace
с процессом B, необходимо разрешить gdb
взаимодействовать с процессом B:
-
Позволить gdb подключиться к B через prctl: Это можно сделать, вызвав
prctl
из процесса B перед его запуском. -
Являться родителем gdb: Можно добиться этого, создав промежуточный процесс. Для этого:
pid_t pid = fork();
if (pid == 0) {
// A1 будет здесь
pid_t b_pid = fork(); // запускаем B
waitpid(b_pid, 0, 0); // ждем сигнал от A1
execlp("gdb", "gdb", "-p", b_pid); // запускаем gdb с подключением к B
}
Заключение
Таким образом, передача управления инструментом ptrace
другому процессу, такому как gdb, требует тщательной настройки и выполнения ряда шагов. Важным является установка правильных разрешений и использование системных вызовов для управления поведением процессов. Важно учитывать безопасность, так как изменения в ptrace_scope
могут повлиять на систему в целом.
Это решение может быть адаптировано для различных сценариев, позволяя эффективно диагностировать проблемы в процессе B при помощи gdb, не потеряя управления.